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));
+ }
}
}