diff --git a/src/KubernetesClient/CertUtils.cs b/src/KubernetesClient/CertUtils.cs index 6ac4a787..dd0ba71b 100644 --- a/src/KubernetesClient/CertUtils.cs +++ b/src/KubernetesClient/CertUtils.cs @@ -1,15 +1,14 @@ -using System; -using System.IO; -using System.Security.Cryptography.X509Certificates; -using System.Text; using k8s.Exceptions; using Org.BouncyCastle.Crypto; -using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.OpenSsl; using Org.BouncyCastle.Pkcs; using Org.BouncyCastle.Security; using Org.BouncyCastle.X509; -using X509Certificate = Org.BouncyCastle.X509.X509Certificate; +using System; +using System.Collections.Generic; +using System.IO; +using System.Security.Cryptography.X509Certificates; +using System.Text.RegularExpressions; namespace k8s { @@ -19,22 +18,21 @@ public static class CertUtils /// Load pem encoded cert file /// /// Path to pem encoded cert file - /// x509 instance. - public static X509Certificate2 LoadPemFileCert(string file) + /// List of x509 instances. + public static X509Certificate2Collection LoadPemFileCert(string file) { - var certs = new X509CertificateParser().ReadCertificates(File.OpenRead(file)); - var store = new Pkcs12StoreBuilder().Build(); - foreach (X509Certificate cert in certs) - { - store.SetCertificateEntry(Guid.NewGuid().ToString(), new X509CertificateEntry(cert)); - } + var certs = new X509CertificateParser().ReadCertificates(File.OpenRead(file)); + var certCollection = new X509Certificate2Collection(); - using (var pkcs = new MemoryStream()) + // Convert BouncyCastle X509Certificates to the .NET cryptography implementation and add + // it to the certificate collection + // + foreach (Org.BouncyCastle.X509.X509Certificate cert in certs) { - store.Save(pkcs, new char[0], new SecureRandom()); - // TODO not a chain - return new X509Certificate2(pkcs.ToArray()); + certCollection.Add(new X509Certificate2(cert.GetEncoded())); } + + return certCollection; } /// diff --git a/src/KubernetesClient/Kubernetes.ConfigInit.cs b/src/KubernetesClient/Kubernetes.ConfigInit.cs index 1e6f228f..47f0342e 100644 --- a/src/KubernetesClient/Kubernetes.ConfigInit.cs +++ b/src/KubernetesClient/Kubernetes.ConfigInit.cs @@ -39,7 +39,7 @@ public Kubernetes(KubernetesClientConfiguration config, params DelegatingHandler throw new KubeConfigException("Bad host url", e); } - CaCert = config.SslCaCert; + CaCerts = config.SslCaCerts; SkipTlsVerify = config.SkipTlsVerify; if (BaseUri.Scheme == "https") @@ -53,21 +53,26 @@ public Kubernetes(KubernetesClientConfiguration config, params DelegatingHandler } else { - if (CaCert == null) + if (CaCerts == null) { throw new KubeConfigException("a CA must be set when SkipTlsVerify === false"); } - using (System.IO.MemoryStream certStream = new System.IO.MemoryStream(config.SslCaCert.RawData)) - { - Java.Security.Cert.Certificate cert = Java.Security.Cert.CertificateFactory.GetInstance("X509").GenerateCertificate(certStream); - Xamarin.Android.Net.AndroidClientHandler handler = (Xamarin.Android.Net.AndroidClientHandler)this.HttpClientHandler; + var certList = new System.Collections.Generic.List(); - handler.TrustedCerts = new System.Collections.Generic.List() + foreach (X509Certificate2 caCert in CaCerts) + { + using (System.IO.MemoryStream certStream = new System.IO.MemoryStream(caCert.RawData)) { - cert - }; + Java.Security.Cert.Certificate cert = Java.Security.Cert.CertificateFactory.GetInstance("X509").GenerateCertificate(certStream); + + certList.Add(cert); + } } + + Xamarin.Android.Net.AndroidClientHandler handler = (Xamarin.Android.Net.AndroidClientHandler)this.HttpClientHandler; + + handler.TrustedCerts = certList; } } @@ -100,7 +105,7 @@ public Kubernetes(KubernetesClientConfiguration config, params DelegatingHandler throw new KubeConfigException("Bad host url", e); } - CaCert = config.SslCaCert; + CaCerts = config.SslCaCerts; SkipTlsVerify = config.SkipTlsVerify; if (BaseUri.Scheme == "https") @@ -122,7 +127,7 @@ public Kubernetes(KubernetesClientConfiguration config, params DelegatingHandler } else { - if (CaCert == null) + if (CaCerts == null) { throw new KubeConfigException("a CA must be set when SkipTlsVerify === false"); } @@ -130,18 +135,18 @@ public Kubernetes(KubernetesClientConfiguration config, params DelegatingHandler #if NET452 ((WebRequestHandler) HttpClientHandler).ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => { - return Kubernetes.CertificateValidationCallBack(sender, CaCert, certificate, chain, sslPolicyErrors); + return Kubernetes.CertificateValidationCallBack(sender, CaCerts, certificate, chain, sslPolicyErrors); }; #elif XAMARINIOS1_0 System.Net.ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => { var cert = new X509Certificate2(certificate); - return Kubernetes.CertificateValidationCallBack(sender, CaCert, cert, chain, sslPolicyErrors); + return Kubernetes.CertificateValidationCallBack(sender, CaCerts, cert, chain, sslPolicyErrors); }; #else HttpClientHandler.ServerCertificateCustomValidationCallback = (sender, certificate, chain, sslPolicyErrors) => { - return Kubernetes.CertificateValidationCallBack(sender, CaCert, certificate, chain, sslPolicyErrors); + return Kubernetes.CertificateValidationCallBack(sender, CaCerts, certificate, chain, sslPolicyErrors); }; #endif } @@ -152,7 +157,7 @@ public Kubernetes(KubernetesClientConfiguration config, params DelegatingHandler } #endif - private X509Certificate2 CaCert { get; } + private X509Certificate2Collection CaCerts { get; } private bool SkipTlsVerify { get; } @@ -241,7 +246,7 @@ private void SetCredentials(KubernetesClientConfiguration config, HttpClientHand [SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", Justification = "Unused by design")] public static bool CertificateValidationCallBack( object sender, - X509Certificate2 caCert, + X509Certificate2Collection caCerts, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) @@ -257,15 +262,29 @@ public static bool CertificateValidationCallBack( { chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; - // add all your extra certificate chain - chain.ChainPolicy.ExtraStore.Add(caCert); + // Added our trusted certificates to the chain + // + chain.ChainPolicy.ExtraStore.AddRange(caCerts); + chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllowUnknownCertificateAuthority; var isValid = chain.Build((X509Certificate2)certificate); + var isTrusted = false; + var rootCert = chain.ChainElements[chain.ChainElements.Count - 1].Certificate; - isValid = isValid && rootCert.RawData.SequenceEqual(caCert.RawData); - return isValid; + // Make sure that one of our trusted certs exists in the chain provided by the server. + // + foreach (var cert in caCerts) + { + if (rootCert.RawData.SequenceEqual(cert.RawData)) + { + isTrusted = true; + break; + } + } + + return isValid && isTrusted; } // In all other cases, return false. diff --git a/src/KubernetesClient/Kubernetes.WebSocket.cs b/src/KubernetesClient/Kubernetes.WebSocket.cs index 6a0623db..a8310883 100644 --- a/src/KubernetesClient/Kubernetes.WebSocket.cs +++ b/src/KubernetesClient/Kubernetes.WebSocket.cs @@ -260,16 +260,16 @@ public partial class Kubernetes } #if NET452 - if (this.CaCert != null) + if (this.CaCerts != null) { webSocketBuilder.SetServerCertificateValidationCallback(this.ServerCertificateValidationCallback); } #endif #if NETCOREAPP2_1 - if (this.CaCert != null) + if (this.CaCerts != null) { - webSocketBuilder.ExpectServerCertificate(this.CaCert); + webSocketBuilder.ExpectServerCertificate(this.CaCerts); } if (this.SkipTlsVerify) @@ -347,7 +347,7 @@ public partial class Kubernetes ServiceClientTracing.Exit(invocationId, null); } #if NET452 - if (this.CaCert != null) + if (this.CaCerts != null) { webSocketBuilder.CleanupServerCertificateValidationCallback(this.ServerCertificateValidationCallback); } @@ -359,7 +359,7 @@ public partial class Kubernetes #if NET452 internal bool ServerCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) { - return Kubernetes.CertificateValidationCallBack(sender, this.CaCert, certificate, chain, sslPolicyErrors); + return Kubernetes.CertificateValidationCallBack(sender, this.CaCerts, certificate, chain, sslPolicyErrors); } #endif } diff --git a/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs b/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs index 41fc3656..84a23a66 100644 --- a/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs +++ b/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices; @@ -189,17 +190,17 @@ private void SetClusterDetails(K8SConfiguration k8SConfig, Context activeContext { throw new KubeConfigException($"Bad server host URL `{Host}` (cannot be parsed)"); } - + if (uri.Scheme == "https") { if (!string.IsNullOrEmpty(clusterDetails.ClusterEndpoint.CertificateAuthorityData)) { var data = clusterDetails.ClusterEndpoint.CertificateAuthorityData; - SslCaCert = new X509Certificate2(Convert.FromBase64String(data)); + SslCaCerts = new X509Certificate2Collection(new X509Certificate2(Convert.FromBase64String(data))); } else if (!string.IsNullOrEmpty(clusterDetails.ClusterEndpoint.CertificateAuthority)) { - SslCaCert = new X509Certificate2(GetFullPath(k8SConfig, clusterDetails.ClusterEndpoint.CertificateAuthority)); + SslCaCerts = new X509Certificate2Collection(new X509Certificate2(GetFullPath(k8SConfig, clusterDetails.ClusterEndpoint.CertificateAuthority))); } } } diff --git a/src/KubernetesClient/KubernetesClientConfiguration.InCluster.cs b/src/KubernetesClient/KubernetesClientConfiguration.InCluster.cs index 86c576e5..7fa46749 100644 --- a/src/KubernetesClient/KubernetesClientConfiguration.InCluster.cs +++ b/src/KubernetesClient/KubernetesClientConfiguration.InCluster.cs @@ -43,7 +43,7 @@ public static KubernetesClientConfiguration InClusterConfig() { Host = new UriBuilder("https", host, Convert.ToInt32(port)).ToString(), AccessToken = token, - SslCaCert = CertUtils.LoadPemFileCert(rootCAFile) + SslCaCerts = CertUtils.LoadPemFileCert(rootCAFile) }; } } diff --git a/src/KubernetesClient/KubernetesClientConfiguration.cs b/src/KubernetesClient/KubernetesClientConfiguration.cs index a16cd6cb..73e6c6fc 100644 --- a/src/KubernetesClient/KubernetesClientConfiguration.cs +++ b/src/KubernetesClient/KubernetesClientConfiguration.cs @@ -1,3 +1,4 @@ +using System.Collections.Generic; using System.Security.Cryptography.X509Certificates; namespace k8s @@ -18,9 +19,9 @@ public partial class KubernetesClientConfiguration public string Host { get; set; } /// - /// Gets SslCaCert + /// Gets SslCaCerts /// - public X509Certificate2 SslCaCert { get; set; } + public X509Certificate2Collection SslCaCerts { get; set; } /// /// Gets ClientCertificateData diff --git a/src/KubernetesClient/WebSocketBuilder.cs b/src/KubernetesClient/WebSocketBuilder.cs index e850e7b3..3e9ad3c8 100644 --- a/src/KubernetesClient/WebSocketBuilder.cs +++ b/src/KubernetesClient/WebSocketBuilder.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Net.WebSockets; #if NET452 using System.Net.Security; @@ -52,7 +53,7 @@ public void CleanupServerCertificateValidationCallback(RemoteCertificateValidati #endif #if NETCOREAPP2_1 - public WebSocketBuilder ExpectServerCertificate(X509Certificate2 serverCertificate) + public WebSocketBuilder ExpectServerCertificate(X509Certificate2Collection serverCertificate) { Options.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => { diff --git a/tests/KubernetesClient.Tests/AuthTests.cs b/tests/KubernetesClient.Tests/AuthTests.cs index 0d83999a..22e3f03a 100644 --- a/tests/KubernetesClient.Tests/AuthTests.cs +++ b/tests/KubernetesClient.Tests/AuthTests.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; @@ -221,7 +222,7 @@ public void Cert() Host = server.Uri.ToString(), ClientCertificateData = clientCertificateData, ClientCertificateKeyData = clientCertificateKeyData, - SslCaCert = serverCertificate, + SslCaCerts = new X509Certificate2Collection(serverCertificate), SkipTlsVerify = false }); diff --git a/tests/KubernetesClient.Tests/CertUtilsTests.cs b/tests/KubernetesClient.Tests/CertUtilsTests.cs index 549c26be..10679cbd 100644 --- a/tests/KubernetesClient.Tests/CertUtilsTests.cs +++ b/tests/KubernetesClient.Tests/CertUtilsTests.cs @@ -2,6 +2,9 @@ using Xunit; using k8s; using System.IO; +using System.Security.Cryptography.X509Certificates; +using System.Net.Security; +using System.Linq; namespace k8s.Tests { @@ -72,13 +75,20 @@ public void LoadFromInlineDataRelativePath() } /// - /// Checks + /// Checks that the bundle certificate was loaded correctly /// [Fact] public void LoadPemWithMultiCert() { - var cert = CertUtils.LoadPemFileCert("assets/ca3.crt"); - Assert.NotNull(cert.PublicKey); + var certCollection = CertUtils.LoadPemFileCert("assets/ca-bundle.crt"); + + var intermediateCert = new X509Certificate2("assets/ca-bundle-intermediate.crt"); + var rootCert = new X509Certificate2("assets/ca-bundle-root.crt"); + + Assert.Equal(2, certCollection.Count); + + Assert.True(certCollection[0].RawData.SequenceEqual(intermediateCert.RawData)); + Assert.True(certCollection[1].RawData.SequenceEqual(rootCert.RawData)); } } } diff --git a/tests/KubernetesClient.Tests/CertificateValidationTests.cs b/tests/KubernetesClient.Tests/CertificateValidationTests.cs index 0fc79225..d653c24f 100644 --- a/tests/KubernetesClient.Tests/CertificateValidationTests.cs +++ b/tests/KubernetesClient.Tests/CertificateValidationTests.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Net.Security; using System.Security.Cryptography.X509Certificates; @@ -11,7 +12,7 @@ public class CertificateValidationTests [Fact] public void ValidCert() { - var caCert = new X509Certificate2("assets/ca.crt"); + var caCert = CertUtils.LoadPemFileCert("assets/ca.crt"); var testCert = new X509Certificate2("assets/ca.crt"); var chain = new X509Chain(); var errors = SslPolicyErrors.RemoteCertificateChainErrors; @@ -24,7 +25,36 @@ public void ValidCert() [Fact] public void InvalidCert() { - var caCert = new X509Certificate2("assets/ca.crt"); + var caCert = CertUtils.LoadPemFileCert("assets/ca.crt"); + var testCert = new X509Certificate2("assets/ca2.crt"); + var chain = new X509Chain(); + var errors = SslPolicyErrors.RemoteCertificateChainErrors; + + var result = Kubernetes.CertificateValidationCallBack(this, caCert, testCert, chain, errors); + + Assert.False(result); + } + + [Fact] + public void ValidBundleCert() + { + var caCert = CertUtils.LoadPemFileCert("assets/ca-bundle.crt"); + + // Load the intermediate cert + // + var testCert = caCert[0]; + var chain = new X509Chain(); + var errors = SslPolicyErrors.RemoteCertificateChainErrors; + + var result = Kubernetes.CertificateValidationCallBack(this, caCert, testCert, chain, errors); + + Assert.True(result); + } + + [Fact] + public void InvalidBundleCert() + { + var caCert = CertUtils.LoadPemFileCert("assets/ca-bundle.crt"); var testCert = new X509Certificate2("assets/ca2.crt"); var chain = new X509Chain(); var errors = SslPolicyErrors.RemoteCertificateChainErrors; diff --git a/tests/KubernetesClient.Tests/KubernetesClientConfigurationTests.cs b/tests/KubernetesClient.Tests/KubernetesClientConfigurationTests.cs index d504c1f0..de55ca3b 100755 --- a/tests/KubernetesClient.Tests/KubernetesClientConfigurationTests.cs +++ b/tests/KubernetesClient.Tests/KubernetesClientConfigurationTests.cs @@ -79,7 +79,7 @@ public void ClientData(string context) var fi = new FileInfo("assets/kubeconfig.yml"); var cfg = KubernetesClientConfiguration.BuildConfigFromConfigFile(fi, context); Assert.Equal(context, cfg.CurrentContext); - Assert.NotNull(cfg.SslCaCert); + Assert.NotNull(cfg.SslCaCerts); Assert.Equal(File.ReadAllText("assets/client-certificate-data.txt"), cfg.ClientCertificateData); Assert.Equal(File.ReadAllText("assets/client-key-data.txt"), cfg.ClientCertificateKeyData); } @@ -94,7 +94,7 @@ public void CheckClusterTlsSkipCorrectness() var fi = new FileInfo("assets/kubeconfig.tls-skip.yml"); var cfg = KubernetesClientConfiguration.BuildConfigFromConfigFile(fi); Assert.NotNull(cfg.Host); - Assert.Null(cfg.SslCaCert); + Assert.Null(cfg.SslCaCerts); Assert.True(cfg.SkipTlsVerify); } diff --git a/tests/KubernetesClient.Tests/assets/ca-bundle-intermediate.crt b/tests/KubernetesClient.Tests/assets/ca-bundle-intermediate.crt new file mode 100644 index 00000000..e8546082 --- /dev/null +++ b/tests/KubernetesClient.Tests/assets/ca-bundle-intermediate.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDDTCCAfWgAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwFTETMBEGA1UEAwwKa3Vi +ZXJuZXRlczAeFw0xOTAzMDMxNzA4MDlaFw0yOTAyMjgxNzA4MDlaMBYxFDASBgNV +BAMMC2V0Y2hhbmctdWI1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA +x1Tp7Da3NbjdHmYdYZ/GNpCRGvFFap7EG1pokhfILKSbPusqiO9wnKDE4Afdn/ZE +CQV0Whwtox3jczBOIRy+P6FvlPyhApUpynVTwgCiuhTM+thgODgpe6GXmVlVJGvv +AoLw7CMndB5sMs5HH+qA2U1q4VFI/csr3/yeKzWBik3dZVoh04sI9WTVL+bl/1X5 +0dl5qrqkYiDx8ycAHyOnl8dhJW+RGl67HiliuUeSq6vwsfv9rh3TP9wHVF1PXFJp +WfXy4WbLmuld5wxXnQVO2g51jqfqN9fD8FHIkae1IkO/PUTucloNlLiFsragQOTD +RVSP+TV3gshATBs2MMVXMwIDAQABo2YwZDAdBgNVHQ4EFgQU/3w9AR2cnEepWH4E +8a1xLZAnjykwHwYDVR0jBBgwFoAULs/lzct8CGvVdIiq4t9T4idu5OwwEgYDVR0T +AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggEB +AKw741V1wszIthHBV8dvCyQoyozBJuAo4IHbiiFmzuiQuyshMcX+Qs9a+g6OG5d1 +UbwFfUlqzmZQcbcR/Jc6wMz3wO6Hoy5pS3w/FR2UMGR39o95/7XCkTIOwCqau6Pw +dpgvbnaiqPFPqD3ohdUuVRcXG3va5AmKTsUn7m+lR/93/qptt+SUVp6jwnbGcwoB +s3u2XXx5s1M7tqqj3tAEOPCKlohS6mQ4X3wulgpZ1XpJ0WTvcvoPXEtA56k7vX3a +4E6x66LZCFA2ZR/5COv5D055AhrihKL8kbAutxhfA27SJ/MGowzmTT7kVQha3Su3 +aoOYZgcUww+SkRSGVrtgMgQ= +-----END CERTIFICATE----- diff --git a/tests/KubernetesClient.Tests/assets/ca-bundle-root.crt b/tests/KubernetesClient.Tests/assets/ca-bundle-root.crt new file mode 100644 index 00000000..21c71739 --- /dev/null +++ b/tests/KubernetesClient.Tests/assets/ca-bundle-root.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDEDCCAfigAwIBAgIJAJpb9irKg2JjMA0GCSqGSIb3DQEBCwUAMBUxEzARBgNV +BAMMCmt1YmVybmV0ZXMwHhcNMTkwMzAzMDAyMTI3WhcNMzkwMjI2MDAyMTI3WjAV +MRMwEQYDVQQDDAprdWJlcm5ldGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAuoK+Na+LyKIipmftBw4Y+Z19g8yv6Y+dYt6KlBg24XHNA0v1cMwtOCDF +Mlm4rsD7Jd5UO6ugdk3fxEvGGhmzWTXSBRUWcTbScAM49mALBFkCvNTPK2vVhk7P +im2QQl8a5vjYz8HLKJTb/O+0q+Kktpd7XTaU2U7ZebiLVs5bvNbb3ZDtIjAARY9S +alZ4hOzuVNaSX9MBRqTWq3HuKwDiVTT3dan/ABoU8NdedPfIbyY48wiQgjEYb64g +3geYpArLQeffo8fmhUEPRR/1WrfvYvvm8sV8jT+rqxITKJ5Vo5kpZUpomDOtGVMS +gGAle6mcTrqlrsCFc4gFRRoHiH1ODQIDAQABo2MwYTAdBgNVHQ4EFgQULs/lzct8 +CGvVdIiq4t9T4idu5OwwHwYDVR0jBBgwFoAULs/lzct8CGvVdIiq4t9T4idu5Oww +DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQAD +ggEBAFMq5z4OoaIhqx/i/btpVLRnQDcpDwdUurE0iNPz3bgOI5QiIe95oUwXSFQL +ciECvObfMmiVuz+p7ND5eNdxYR4hlq1W1PYcgRQgusXCC4Xd/XAGaLZXzH3SBrmp +bs5sfokhXKNccsnQu5Ya3JRkALxxUJ+DcOn+vi9gmEAzi+nXbyqUjIhSD5nygClX +0aSKbvhUmXyaJpUH0i7dSxWP3LqCDjtru/5ejNtB097dNcyF8js3Yuk3hwqyegQx +ELn4c/TKPL9L8vE7tJg/M78DPAvRCiuwl0HQcasBE2AX0wdpY0UeXsNDyzUf/2WF +fHY4DnuBdeVdHtl1yPlXmQkMoQM= +-----END CERTIFICATE----- diff --git a/tests/KubernetesClient.Tests/assets/ca-bundle.crt b/tests/KubernetesClient.Tests/assets/ca-bundle.crt new file mode 100644 index 00000000..ff887ab9 --- /dev/null +++ b/tests/KubernetesClient.Tests/assets/ca-bundle.crt @@ -0,0 +1,44 @@ +--- Comments to make sure we still parse the cert correctly + +Intermediate Certificate + +-----BEGIN CERTIFICATE----- +MIIDDTCCAfWgAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwFTETMBEGA1UEAwwKa3Vi +ZXJuZXRlczAeFw0xOTAzMDMxNzA4MDlaFw0yOTAyMjgxNzA4MDlaMBYxFDASBgNV +BAMMC2V0Y2hhbmctdWI1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA +x1Tp7Da3NbjdHmYdYZ/GNpCRGvFFap7EG1pokhfILKSbPusqiO9wnKDE4Afdn/ZE +CQV0Whwtox3jczBOIRy+P6FvlPyhApUpynVTwgCiuhTM+thgODgpe6GXmVlVJGvv +AoLw7CMndB5sMs5HH+qA2U1q4VFI/csr3/yeKzWBik3dZVoh04sI9WTVL+bl/1X5 +0dl5qrqkYiDx8ycAHyOnl8dhJW+RGl67HiliuUeSq6vwsfv9rh3TP9wHVF1PXFJp +WfXy4WbLmuld5wxXnQVO2g51jqfqN9fD8FHIkae1IkO/PUTucloNlLiFsragQOTD +RVSP+TV3gshATBs2MMVXMwIDAQABo2YwZDAdBgNVHQ4EFgQU/3w9AR2cnEepWH4E +8a1xLZAnjykwHwYDVR0jBBgwFoAULs/lzct8CGvVdIiq4t9T4idu5OwwEgYDVR0T +AQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggEB +AKw741V1wszIthHBV8dvCyQoyozBJuAo4IHbiiFmzuiQuyshMcX+Qs9a+g6OG5d1 +UbwFfUlqzmZQcbcR/Jc6wMz3wO6Hoy5pS3w/FR2UMGR39o95/7XCkTIOwCqau6Pw +dpgvbnaiqPFPqD3ohdUuVRcXG3va5AmKTsUn7m+lR/93/qptt+SUVp6jwnbGcwoB +s3u2XXx5s1M7tqqj3tAEOPCKlohS6mQ4X3wulgpZ1XpJ0WTvcvoPXEtA56k7vX3a +4E6x66LZCFA2ZR/5COv5D055AhrihKL8kbAutxhfA27SJ/MGowzmTT7kVQha3Su3 +aoOYZgcUww+SkRSGVrtgMgQ= +-----END CERTIFICATE----- + +Root certificate +-----BEGIN CERTIFICATE----- +MIIDEDCCAfigAwIBAgIJAJpb9irKg2JjMA0GCSqGSIb3DQEBCwUAMBUxEzARBgNV +BAMMCmt1YmVybmV0ZXMwHhcNMTkwMzAzMDAyMTI3WhcNMzkwMjI2MDAyMTI3WjAV +MRMwEQYDVQQDDAprdWJlcm5ldGVzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAuoK+Na+LyKIipmftBw4Y+Z19g8yv6Y+dYt6KlBg24XHNA0v1cMwtOCDF +Mlm4rsD7Jd5UO6ugdk3fxEvGGhmzWTXSBRUWcTbScAM49mALBFkCvNTPK2vVhk7P +im2QQl8a5vjYz8HLKJTb/O+0q+Kktpd7XTaU2U7ZebiLVs5bvNbb3ZDtIjAARY9S +alZ4hOzuVNaSX9MBRqTWq3HuKwDiVTT3dan/ABoU8NdedPfIbyY48wiQgjEYb64g +3geYpArLQeffo8fmhUEPRR/1WrfvYvvm8sV8jT+rqxITKJ5Vo5kpZUpomDOtGVMS +gGAle6mcTrqlrsCFc4gFRRoHiH1ODQIDAQABo2MwYTAdBgNVHQ4EFgQULs/lzct8 +CGvVdIiq4t9T4idu5OwwHwYDVR0jBBgwFoAULs/lzct8CGvVdIiq4t9T4idu5Oww +DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQAD +ggEBAFMq5z4OoaIhqx/i/btpVLRnQDcpDwdUurE0iNPz3bgOI5QiIe95oUwXSFQL +ciECvObfMmiVuz+p7ND5eNdxYR4hlq1W1PYcgRQgusXCC4Xd/XAGaLZXzH3SBrmp +bs5sfokhXKNccsnQu5Ya3JRkALxxUJ+DcOn+vi9gmEAzi+nXbyqUjIhSD5nygClX +0aSKbvhUmXyaJpUH0i7dSxWP3LqCDjtru/5ejNtB097dNcyF8js3Yuk3hwqyegQx +ELn4c/TKPL9L8vE7tJg/M78DPAvRCiuwl0HQcasBE2AX0wdpY0UeXsNDyzUf/2WF +fHY4DnuBdeVdHtl1yPlXmQkMoQM= +-----END CERTIFICATE-----