From e348ee24aba4fd388134ee758e49f57b9f19b756 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 25 Nov 2025 20:27:03 +0000 Subject: [PATCH 1/6] Initial plan From 10e1a4c3bfe42d3472a888b0878b77598b55a8ca Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 25 Nov 2025 20:43:44 +0000 Subject: [PATCH 2/6] Fix multi-certificate loading in SetClusterDetails method Co-authored-by: tg123 <170430+tg123@users.noreply.github.com> --- ...ubernetesClientConfiguration.ConfigFile.cs | 24 +++++------------ .../KubernetesClientConfigurationTests.cs | 26 +++++++++++++++++++ .../assets/kubeconfig.multi-ca-file.yml | 17 ++++++++++++ .../assets/kubeconfig.multi-ca.yml | 17 ++++++++++++ 4 files changed, 67 insertions(+), 17 deletions(-) create mode 100644 tests/KubernetesClient.Tests/assets/kubeconfig.multi-ca-file.yml create mode 100644 tests/KubernetesClient.Tests/assets/kubeconfig.multi-ca.yml diff --git a/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs b/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs index f25c55bbb..52834ec99 100644 --- a/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs +++ b/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs @@ -308,26 +308,16 @@ private void SetClusterDetails(K8SConfiguration k8SConfig, Context activeContext if (!string.IsNullOrEmpty(clusterDetails.ClusterEndpoint.CertificateAuthorityData)) { var data = clusterDetails.ClusterEndpoint.CertificateAuthorityData; -#if NET9_0_OR_GREATER - SslCaCerts = new X509Certificate2Collection(X509CertificateLoader.LoadCertificate(Convert.FromBase64String(data))); -#else - string nullPassword = null; - // This null password is to change the constructor to fix this KB: - // https://support.microsoft.com/en-us/topic/kb5025823-change-in-how-net-applications-import-x-509-certificates-bf81c936-af2b-446e-9f7a-016f4713b46b - SslCaCerts = new X509Certificate2Collection(new X509Certificate2(Convert.FromBase64String(data), nullPassword)); -#endif + var pemText = Encoding.UTF8.GetString(Convert.FromBase64String(data)); + SslCaCerts = new X509Certificate2Collection(); + SslCaCerts.ImportFromPem(pemText); } else if (!string.IsNullOrEmpty(clusterDetails.ClusterEndpoint.CertificateAuthority)) { -#if NET9_0_OR_GREATER - SslCaCerts = new X509Certificate2Collection(X509CertificateLoader.LoadCertificateFromFile(GetFullPath( - k8SConfig, - clusterDetails.ClusterEndpoint.CertificateAuthority))); -#else - SslCaCerts = new X509Certificate2Collection(new X509Certificate2(GetFullPath( - k8SConfig, - clusterDetails.ClusterEndpoint.CertificateAuthority))); -#endif + var certPath = GetFullPath(k8SConfig, clusterDetails.ClusterEndpoint.CertificateAuthority); + var pemText = File.ReadAllText(certPath); + SslCaCerts = new X509Certificate2Collection(); + SslCaCerts.ImportFromPem(pemText); } } } diff --git a/tests/KubernetesClient.Tests/KubernetesClientConfigurationTests.cs b/tests/KubernetesClient.Tests/KubernetesClientConfigurationTests.cs index a1239c9e9..397c4f431 100644 --- a/tests/KubernetesClient.Tests/KubernetesClientConfigurationTests.cs +++ b/tests/KubernetesClient.Tests/KubernetesClientConfigurationTests.cs @@ -822,5 +822,31 @@ public void LoadInClusterNamespace() Assert.Equal("some namespace", config.Namespace); } } + + /// + /// Checks that multiple certificates are loaded from certificate-authority-data + /// + [Fact] + public void LoadMultipleCertificatesFromCertificateAuthorityData() + { + var fi = new FileInfo("assets/kubeconfig.multi-ca.yml"); + var cfg = KubernetesClientConfiguration.BuildConfigFromConfigFile(fi, "multi-ca-context"); + + Assert.NotNull(cfg.SslCaCerts); + Assert.Equal(2, cfg.SslCaCerts.Count); + } + + /// + /// Checks that multiple certificates are loaded from certificate-authority file + /// + [Fact] + public void LoadMultipleCertificatesFromCertificateAuthorityFile() + { + var fi = new FileInfo("assets/kubeconfig.multi-ca-file.yml"); + var cfg = KubernetesClientConfiguration.BuildConfigFromConfigFile(fi, "multi-ca-file-context", useRelativePaths: false); + + Assert.NotNull(cfg.SslCaCerts); + Assert.Equal(2, cfg.SslCaCerts.Count); + } } } diff --git a/tests/KubernetesClient.Tests/assets/kubeconfig.multi-ca-file.yml b/tests/KubernetesClient.Tests/assets/kubeconfig.multi-ca-file.yml new file mode 100644 index 000000000..af1340adf --- /dev/null +++ b/tests/KubernetesClient.Tests/assets/kubeconfig.multi-ca-file.yml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Config +clusters: +- cluster: + certificate-authority: assets/ca-bundle.crt + server: https://multi-ca-file-test.example.com:6443 + name: multi-ca-file-cluster +contexts: +- context: + cluster: multi-ca-file-cluster + user: test-user + name: multi-ca-file-context +current-context: multi-ca-file-context +users: +- name: test-user + user: + token: test-token diff --git a/tests/KubernetesClient.Tests/assets/kubeconfig.multi-ca.yml b/tests/KubernetesClient.Tests/assets/kubeconfig.multi-ca.yml new file mode 100644 index 000000000..0d9f3321a --- /dev/null +++ b/tests/KubernetesClient.Tests/assets/kubeconfig.multi-ca.yml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: Config +clusters: +- cluster: + certificate-authority-data: LS0tIENvbW1lbnRzIHRvIG1ha2Ugc3VyZSB3ZSBzdGlsbCBwYXJzZSB0aGUgY2VydCBjb3JyZWN0bHkKCkludGVybWVkaWF0ZSBDZXJ0aWZpY2F0ZQoKLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUREVENDQWZXZ0F3SUJBZ0lDRUFFd0RRWUpLb1pJaHZjTkFRRUxCUUF3RlRFVE1CRUdBMVVFQXd3S2EzVmkKWlhKdVpYUmxjekFlRncweE9UQXpNRE14TnpBNE1EbGFGdzB5T1RBeU1qZ3hOekE0TURsYU1CWXhGREFTQmdOVgpCQU1NQzJWMFkyaGhibWN0ZFdJMU1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBCngxVHA3RGEzTmJqZEhtWWRZWi9HTnBDUkd2RkZhcDdFRzFwb2toZklMS1NiUHVzcWlPOXduS0RFNEFmZG4vWkUKQ1FWMFdod3RveDNqY3pCT0lSeStQNkZ2bFB5aEFwVXB5blZUd2dDaXVoVE0rdGhnT0RncGU2R1htVmxWSkd2dgpBb0x3N0NNbmRCNXNNczVISCtxQTJVMXE0VkZJL2NzcjMveWVLeldCaWszZFpWb2gwNHNJOVdUVkwrYmwvMVg1CjBkbDVxcnFrWWlEeDh5Y0FIeU9ubDhkaEpXK1JHbDY3SGlsaXVVZVNxNnZ3c2Z2OXJoM1RQOXdIVkYxUFhGSnAKV2ZYeTRXYkxtdWxkNXd4WG5RVk8yZzUxanFmcU45ZkQ4RkhJa2FlMUlrTy9QVVR1Y2xvTmxMaUZzcmFnUU9URApSVlNQK1RWM2dzaEFUQnMyTU1WWE13SURBUUFCbzJZd1pEQWRCZ05WSFE0RUZnUVUvM3c5QVIyY25FZXBXSDRFCjhhMXhMWkFuanlrd0h3WURWUjBqQkJnd0ZvQVVMcy9semN0OENHdlZkSWlxNHQ5VDRpZHU1T3d3RWdZRFZSMFQKQVFIL0JBZ3dCZ0VCL3dJQkFEQU9CZ05WSFE4QkFmOEVCQU1DQVlZd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQgpBS3c3NDFWMXdzekl0aEhCVjhkdkN5UW95b3pCSnVBbzRJSGJpaUZtenVpUXV5c2hNY1grUXM5YStnNk9HNWQxClVid0ZmVWxxem1aUWNiY1IvSmM2d016M3dPNkhveTVwUzN3L0ZSMlVNR1IzOW85NS83WENrVElPd0NxYXU2UHcKZHBndmJuYWlxUEZQcUQzb2hkVXVWUmNYRzN2YTVBbUtUc1VuN20rbFIvOTMvcXB0dCtTVVZwNmp3bmJHY3dvQgpzM3UyWFh4NXMxTTd0cXFqM3RBRU9QQ0tsb2hTNm1RNFgzd3VsZ3BaMVhwSjBXVHZjdm9QWEV0QTU2azd2WDNhCjRFNng2NkxaQ0ZBMlpSLzVDT3Y1RDA1NUFocmloS0w4a2JBdXR4aGZBMjdTSi9NR293em1UVDdrVlFoYTNTdTMKYW9PWVpnY1V3dytTa1JTR1ZydGdNZ1E9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KClJvb3QgY2VydGlmaWNhdGUKLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURFRENDQWZpZ0F3SUJBZ0lKQUpwYjlpcktnMkpqTUEwR0NTcUdTSWIzRFFFQkN3VUFNQlV4RXpBUkJnTlYKQkFNTUNtdDFZbVZ5Ym1WMFpYTXdIaGNOTVRrd016QXpNREF5TVRJM1doY05Nemt3TWpJMk1EQXlNVEkzV2pBVgpNUk13RVFZRFZRUUREQXByZFdKbGNtNWxkR1Z6TUlJQklqQU5CZ2txaGtpRzl3MEJBUUVGQUFPQ0FROEFNSUlCCkNnS0NBUUVBdW9LK05hK0x5S0lpcG1mdEJ3NFkrWjE5Zzh5djZZK2RZdDZLbEJnMjRYSE5BMHYxY013dE9DREYKTWxtNHJzRDdKZDVVTzZ1Z2RrM2Z4RXZHR2hteldUWFNCUlVXY1RiU2NBTTQ5bUFMQkZrQ3ZOVFBLMnZWaGs3UAppbTJRUWw4YTV2all6OEhMS0pUYi9PKzBxK0trdHBkN1hUYVUyVTdaZWJpTFZzNWJ2TmJiM1pEdElqQUFSWTlTCmFsWjRoT3p1Vk5hU1g5TUJScVRXcTNIdUt3RGlWVFQzZGFuL0FCb1U4TmRlZFBmSWJ5WTQ4d2lRZ2pFWWI2NGcKM2dlWXBBckxRZWZmbzhmbWhVRVBSUi8xV3Jmdll2dm04c1Y4alQrcnF4SVRLSjVWbzVrcFpVcG9tRE90R1ZNUwpnR0FsZTZtY1RycWxyc0NGYzRnRlJSb0hpSDFPRFFJREFRQUJvMk13WVRBZEJnTlZIUTRFRmdRVUxzL2x6Y3Q4CkNHdlZkSWlxNHQ5VDRpZHU1T3d3SHdZRFZSMGpCQmd3Rm9BVUxzL2x6Y3Q4Q0d2VmRJaXE0dDlUNGlkdTVPd3cKRHdZRFZSMFRBUUgvQkFVd0F3RUIvekFPQmdOVkhROEJBZjhFQkFNQ0FZWXdEUVlKS29aSWh2Y05BUUVMQlFBRApnZ0VCQUZNcTV6NE9vYUlocXgvaS9idHBWTFJuUURjcER3ZFV1ckUwaU5QejNiZ09JNVFpSWU5NW9Vd1hTRlFMCmNpRUN2T2JmTW1pVnV6K3A3TkQ1ZU5keFlSNGhscTFXMVBZY2dSUWd1c1hDQzRYZC9YQUdhTFpYekgzU0JybXAKYnM1c2Zva2hYS05jY3NuUXU1WWEzSlJrQUx4eFVKK0RjT24rdmk5Z21FQXppK25YYnlxVWpJaFNENW55Z0NsWAowYVNLYnZoVW1YeWFKcFVIMGk3ZFN4V1AzTHFDRGp0cnUvNWVqTnRCMDk3ZE5jeUY4anMzWXVrM2h3cXllZ1F4CkVMbjRjL1RLUEw5TDh2RTd0SmcvTTc4RFBBdlJDaXV3bDBIUWNhc0JFMkFYMHdkcFkwVWVYc05EeXpVZi8yV0YKZkhZNERudUJkZVZkSHRsMXlQbFhtUWtNb1FNPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg== + server: https://multi-ca-test.example.com:6443 + name: multi-ca-cluster +contexts: +- context: + cluster: multi-ca-cluster + user: test-user + name: multi-ca-context +current-context: multi-ca-context +users: +- name: test-user + user: + token: test-token From 3614d017f82beff64f082a50c1b07d9675a150c5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 25 Nov 2025 20:50:24 +0000 Subject: [PATCH 3/6] Specify UTF8 encoding when reading certificate file Co-authored-by: tg123 <170430+tg123@users.noreply.github.com> --- .../KubernetesClientConfiguration.ConfigFile.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs b/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs index 52834ec99..3b17173f8 100644 --- a/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs +++ b/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs @@ -315,7 +315,7 @@ private void SetClusterDetails(K8SConfiguration k8SConfig, Context activeContext else if (!string.IsNullOrEmpty(clusterDetails.ClusterEndpoint.CertificateAuthority)) { var certPath = GetFullPath(k8SConfig, clusterDetails.ClusterEndpoint.CertificateAuthority); - var pemText = File.ReadAllText(certPath); + var pemText = File.ReadAllText(certPath, Encoding.UTF8); SslCaCerts = new X509Certificate2Collection(); SslCaCerts.ImportFromPem(pemText); } From 2016d1f7b91962054aa417ee82959db527bbf0a1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 25 Nov 2025 21:55:13 +0000 Subject: [PATCH 4/6] Fix multi-certificate loading for all .NET frameworks - Add CertUtils.LoadFromPemText() method for both modern .NET and Classic - Use ImportFromPem for .NET 5.0+ (net8.0, net9.0, net10.0) - Use BouncyCastle for .NET Standard 2.0 and .NET Framework 4.8 - Simplify SetClusterDetails to use CertUtils methods for both certificate-authority-data and certificate-authority Co-authored-by: tg123 <170430+tg123@users.noreply.github.com> --- src/KubernetesClient.Classic/CertUtils.cs | 27 +++++++++++++++++++ src/KubernetesClient/CertUtils.cs | 12 +++++++++ ...ubernetesClientConfiguration.ConfigFile.cs | 10 +++---- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/KubernetesClient.Classic/CertUtils.cs b/src/KubernetesClient.Classic/CertUtils.cs index 112ef922e..4ccc1cafa 100644 --- a/src/KubernetesClient.Classic/CertUtils.cs +++ b/src/KubernetesClient.Classic/CertUtils.cs @@ -39,6 +39,33 @@ public static X509Certificate2Collection LoadPemFileCert(string file) return certCollection; } + /// + /// Load pem encoded certificates from text + /// + /// PEM encoded certificate text + /// List of x509 instances. + public static X509Certificate2Collection LoadFromPemText(string pemText) + { + var certCollection = new X509Certificate2Collection(); + using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(pemText))) + { + var certs = new X509CertificateParser().ReadCertificates(stream); + + // Convert BouncyCastle X509Certificates to the .NET cryptography implementation and add + // it to the certificate collection + // + foreach (Org.BouncyCastle.X509.X509Certificate cert in certs) + { + // This null password is to change the constructor to fix this KB: + // https://support.microsoft.com/en-us/topic/kb5025823-change-in-how-net-applications-import-x-509-certificates-bf81c936-af2b-446e-9f7a-016f4713b46b + string nullPassword = null; + certCollection.Add(new X509Certificate2(cert.GetEncoded(), nullPassword)); + } + } + + return certCollection; + } + /// /// Generates pfx from client configuration /// diff --git a/src/KubernetesClient/CertUtils.cs b/src/KubernetesClient/CertUtils.cs index 7a398d7e8..1f1a2180c 100644 --- a/src/KubernetesClient/CertUtils.cs +++ b/src/KubernetesClient/CertUtils.cs @@ -23,6 +23,18 @@ public static X509Certificate2Collection LoadPemFileCert(string file) return certCollection; } + /// + /// Load pem encoded certificates from text + /// + /// PEM encoded certificate text + /// List of x509 instances. + public static X509Certificate2Collection LoadFromPemText(string pemText) + { + var certCollection = new X509Certificate2Collection(); + certCollection.ImportFromPem(pemText); + return certCollection; + } + /// /// Generates pfx from client configuration /// diff --git a/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs b/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs index 3b17173f8..fb18533cd 100644 --- a/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs +++ b/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs @@ -309,15 +309,13 @@ private void SetClusterDetails(K8SConfiguration k8SConfig, Context activeContext { var data = clusterDetails.ClusterEndpoint.CertificateAuthorityData; var pemText = Encoding.UTF8.GetString(Convert.FromBase64String(data)); - SslCaCerts = new X509Certificate2Collection(); - SslCaCerts.ImportFromPem(pemText); + SslCaCerts = CertUtils.LoadFromPemText(pemText); } else if (!string.IsNullOrEmpty(clusterDetails.ClusterEndpoint.CertificateAuthority)) { - var certPath = GetFullPath(k8SConfig, clusterDetails.ClusterEndpoint.CertificateAuthority); - var pemText = File.ReadAllText(certPath, Encoding.UTF8); - SslCaCerts = new X509Certificate2Collection(); - SslCaCerts.ImportFromPem(pemText); + SslCaCerts = CertUtils.LoadPemFileCert(GetFullPath( + k8SConfig, + clusterDetails.ClusterEndpoint.CertificateAuthority)); } } } From a86c2e278fb1512e170fe18440bf1bb47156282e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 26 Nov 2025 09:05:53 +0000 Subject: [PATCH 5/6] Fix build: Remove unnecessary using and add System.Text to Classic - Remove unused System.Security.Cryptography.X509Certificates using from ConfigFile.cs - Add System.Text using to Classic CertUtils.cs for Encoding class Co-authored-by: tg123 <170430+tg123@users.noreply.github.com> --- src/KubernetesClient.Classic/CertUtils.cs | 1 + src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/KubernetesClient.Classic/CertUtils.cs b/src/KubernetesClient.Classic/CertUtils.cs index 4ccc1cafa..21bebebba 100644 --- a/src/KubernetesClient.Classic/CertUtils.cs +++ b/src/KubernetesClient.Classic/CertUtils.cs @@ -7,6 +7,7 @@ using Org.BouncyCastle.Security; using Org.BouncyCastle.X509; using System.Security.Cryptography.X509Certificates; +using System.Text; namespace k8s { diff --git a/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs b/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs index fb18533cd..ca9e206bd 100644 --- a/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs +++ b/src/KubernetesClient/KubernetesClientConfiguration.ConfigFile.cs @@ -4,7 +4,6 @@ using System.Diagnostics; using System.Net; using System.Runtime.InteropServices; -using System.Security.Cryptography.X509Certificates; using System.Text; namespace k8s From d756306ac0c845fe4a32273787a8b55013583c64 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 26 Nov 2025 22:53:52 +0000 Subject: [PATCH 6/6] Add dedicated unit tests for LoadFromPemText method - Add LoadFromPemTextWithMultiCert test for multiple certificates - Add LoadFromPemTextWithSingleCert test for single certificate - Tests follow the same pattern as existing LoadPemWithMultiCert test Co-authored-by: tg123 <170430+tg123@users.noreply.github.com> --- .../KubernetesClient.Tests/CertUtilsTests.cs | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/tests/KubernetesClient.Tests/CertUtilsTests.cs b/tests/KubernetesClient.Tests/CertUtilsTests.cs index 674715462..3f5f84cf5 100644 --- a/tests/KubernetesClient.Tests/CertUtilsTests.cs +++ b/tests/KubernetesClient.Tests/CertUtilsTests.cs @@ -98,5 +98,49 @@ public void LoadPemWithMultiCert() Assert.True(certCollection[0].RawData.SequenceEqual(intermediateCert.RawData)); Assert.True(certCollection[1].RawData.SequenceEqual(rootCert.RawData)); } + + /// + /// Checks that multiple certificates can be loaded from PEM text + /// + [Fact] + public void LoadFromPemTextWithMultiCert() + { + // Read the PEM text from the ca-bundle file + var pemText = System.IO.File.ReadAllText("assets/ca-bundle.crt"); + var certCollection = CertUtils.LoadFromPemText(pemText); + +#if NET9_0_OR_GREATER + using var intermediateCert = X509CertificateLoader.LoadCertificateFromFile("assets/ca-bundle-intermediate.crt"); + using var rootCert = X509CertificateLoader.LoadCertificateFromFile("assets/ca-bundle-root.crt"); +#else + using var intermediateCert = new X509Certificate2("assets/ca-bundle-intermediate.crt"); + using var rootCert = new X509Certificate2("assets/ca-bundle-root.crt"); +#endif + + Assert.Equal(2, certCollection.Count); + + Assert.True(certCollection[0].RawData.SequenceEqual(intermediateCert.RawData)); + Assert.True(certCollection[1].RawData.SequenceEqual(rootCert.RawData)); + } + + /// + /// Checks that a single certificate can be loaded from PEM text + /// + [Fact] + public void LoadFromPemTextWithSingleCert() + { + // Read a single certificate PEM text + var pemText = System.IO.File.ReadAllText("assets/ca-bundle-root.crt"); + var certCollection = CertUtils.LoadFromPemText(pemText); + +#if NET9_0_OR_GREATER + using var rootCert = X509CertificateLoader.LoadCertificateFromFile("assets/ca-bundle-root.crt"); +#else + using var rootCert = new X509Certificate2("assets/ca-bundle-root.crt"); +#endif + + Assert.Single(certCollection); + Assert.True(certCollection[0].RawData.SequenceEqual(rootCert.RawData)); + } } }