Update certificate validation to use custom trust store for .NET 5.0+ (#1653)
* Update certificate validation to use custom trust store for .NET 5.0 and greater * Update src/KubernetesClient/Kubernetes.ConfigInit.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update apiserver-pfx-data.txt with new certificate data * Update tests/KubernetesClient.Tests/CertificateValidationTests.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Brendan Burns <5751682+brendandburns@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
using System.Security.Cryptography;
|
||||
using System.Net.Security;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using Xunit;
|
||||
@@ -6,6 +8,62 @@ namespace k8s.Tests
|
||||
{
|
||||
public class CertificateValidationTests
|
||||
{
|
||||
[Fact]
|
||||
public void ShouldRejectCertFromDifferentCA()
|
||||
{
|
||||
// Load our "trusted" Kubernetes CA
|
||||
var trustedCaCert = CertUtils.LoadPemFileCert("assets/ca.crt");
|
||||
|
||||
// Generate a completely different CA and server cert in memory
|
||||
using (var differentCA = CreateSelfSignedCA("CN=Different CA"))
|
||||
using (var untrustedServerCert = CreateServerCert(differentCA, "CN=fake-server.com"))
|
||||
{
|
||||
var chain = new X509Chain();
|
||||
|
||||
// Pre-populate the chain like SSL validation would do
|
||||
// This will likely succeed because we allow unknown CAs in the validation
|
||||
chain.Build(untrustedServerCert);
|
||||
|
||||
var errors = SslPolicyErrors.RemoteCertificateChainErrors;
|
||||
|
||||
var result = Kubernetes.CertificateValidationCallBack(this, trustedCaCert, untrustedServerCert, chain, errors);
|
||||
|
||||
// This SHOULD be false because the server cert wasn't signed by our trusted CA
|
||||
// But the current K8s validation logic might incorrectly return true
|
||||
Assert.False(result, "Should reject certificates not signed by trusted CA");
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
// differentCA.Dispose();
|
||||
// untrustedServerCert.Dispose();
|
||||
}
|
||||
|
||||
// Helper methods to create test certificates
|
||||
private static X509Certificate2 CreateSelfSignedCA(string subject)
|
||||
{
|
||||
using (var rsa = RSA.Create(2048))
|
||||
{
|
||||
var req = new CertificateRequest(subject, rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
|
||||
req.CertificateExtensions.Add(new X509BasicConstraintsExtension(true, false, 0, true));
|
||||
req.CertificateExtensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.KeyCertSign | X509KeyUsageFlags.CrlSign, true));
|
||||
|
||||
return req.CreateSelfSigned(DateTimeOffset.UtcNow.AddDays(-1), DateTimeOffset.UtcNow.AddDays(365));
|
||||
}
|
||||
}
|
||||
|
||||
private static X509Certificate2 CreateServerCert(X509Certificate2 issuerCA, string subject)
|
||||
{
|
||||
using (var rsa = RSA.Create(2048))
|
||||
{
|
||||
var req = new CertificateRequest(subject, rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1);
|
||||
req.CertificateExtensions.Add(new X509BasicConstraintsExtension(false, false, 0, true));
|
||||
req.CertificateExtensions.Add(new X509KeyUsageExtension(X509KeyUsageFlags.DigitalSignature | X509KeyUsageFlags.KeyEncipherment, true));
|
||||
req.CertificateExtensions.Add(new X509EnhancedKeyUsageExtension(new OidCollection { new Oid("1.3.6.1.5.5.7.3.1") }, true));
|
||||
|
||||
return req.Create(issuerCA, DateTimeOffset.UtcNow.AddDays(-1), DateTimeOffset.UtcNow.AddDays(90), new byte[] { 1, 2, 3, 4 });
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ValidCert()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user