diff --git a/src/KubernetesClient/Kubernetes.ConfigInit.cs b/src/KubernetesClient/Kubernetes.ConfigInit.cs index 5177129..f8f504c 100644 --- a/src/KubernetesClient/Kubernetes.ConfigInit.cs +++ b/src/KubernetesClient/Kubernetes.ConfigInit.cs @@ -90,27 +90,27 @@ namespace k8s // set credentails for the kubernetes client SetCredentials(config); - var clientCert = CertUtils.GetClientCert(config); - if (clientCert != null) + ClientCert = CertUtils.GetClientCert(config); + if (ClientCert != null) { #if NET5_0_OR_GREATER - HttpClientHandler.SslOptions.ClientCertificates.Add(clientCert); + HttpClientHandler.SslOptions.ClientCertificates.Add(ClientCert); // TODO this is workaround for net7.0, remove it when the issue is fixed // seems the client certificate is cached and cannot be updated HttpClientHandler.SslOptions.LocalCertificateSelectionCallback = (sender, targetHost, localCertificates, remoteCertificate, acceptableIssuers) => { - return clientCert; + return ClientCert; }; #else - HttpClientHandler.ClientCertificates.Add(clientCert); + HttpClientHandler.ClientCertificates.Add(ClientCert); #endif } } private X509Certificate2Collection CaCerts { get; } - private X509Certificate2 ClientCert { get; } + private X509Certificate2 ClientCert { get; set; } private bool SkipTlsVerify { get; } diff --git a/src/KubernetesClient/Kubernetes.WebSocket.cs b/src/KubernetesClient/Kubernetes.WebSocket.cs index de3721d..54922a8 100644 --- a/src/KubernetesClient/Kubernetes.WebSocket.cs +++ b/src/KubernetesClient/Kubernetes.WebSocket.cs @@ -239,11 +239,6 @@ namespace k8s } // Set Credentials - if (this.ClientCert != null) - { - webSocketBuilder.AddClientCertificate(this.ClientCert); - } - if (this.HttpClientHandler != null) { #if NET5_0_OR_GREATER diff --git a/src/KubernetesClient/Kubernetes.cs b/src/KubernetesClient/Kubernetes.cs index a100a23..848ac49 100644 --- a/src/KubernetesClient/Kubernetes.cs +++ b/src/KubernetesClient/Kubernetes.cs @@ -202,12 +202,27 @@ namespace k8s /// True to release both managed and unmanaged resources; false to releases only unmanaged resources. protected virtual void Dispose(bool disposing) { - if (!_disposed) + if (disposing && !_disposed) { _disposed = true; // Dispose the client HttpClient?.Dispose(); + + // Dispose the certificates + if (CaCerts is not null) + { + foreach (var caCert in CaCerts) + { + caCert.Dispose(); + } + + CaCerts.Clear(); + } + + + ClientCert?.Dispose(); + HttpClient = null; FirstMessageHandler = null; HttpClientHandler = null; diff --git a/tests/E2E.Tests/MinikubeTests.cs b/tests/E2E.Tests/MinikubeTests.cs index de68c2f..508bbd8 100644 --- a/tests/E2E.Tests/MinikubeTests.cs +++ b/tests/E2E.Tests/MinikubeTests.cs @@ -28,7 +28,7 @@ namespace k8s.E2E var namespaceParameter = "default"; var podName = "k8scsharp-e2e-pod"; - var client = CreateClient(); + using var client = CreateClient(); void Cleanup() { @@ -79,7 +79,7 @@ namespace k8s.E2E var namespaceParameter = "default"; var podName = "k8scsharp-e2e-patch-pod"; - var client = CreateClient(); + using var client = CreateClient(); void Cleanup() { @@ -183,7 +183,7 @@ namespace k8s.E2E [MinikubeFact] public async Task WatcherIntegrationTest() { - var kubernetes = CreateClient(); + using var kubernetes = CreateClient(); var job = await kubernetes.BatchV1.CreateNamespacedJobAsync( new V1Job() @@ -251,7 +251,7 @@ namespace k8s.E2E [MinikubeFact] public void LeaderIntegrationTest() { - var client = CreateClient(); + using var client = CreateClient(); var namespaceParameter = "default"; void Cleanup() @@ -350,7 +350,7 @@ namespace k8s.E2E var namespaceParameter = "default"; var podName = "k8scsharp-e2e-logstream-pod"; - var client = CreateClient(); + using var client = CreateClient(); void Cleanup() { @@ -446,7 +446,7 @@ namespace k8s.E2E [MinikubeFact] public async Task DatetimeFieldTest() { - var kubernetes = CreateClient(); + using var kubernetes = CreateClient(); await kubernetes.CoreV1.CreateNamespacedEventAsync( new Corev1Event( @@ -478,7 +478,7 @@ namespace k8s.E2E var namespaceParameter = "default"; var podName = "k8scsharp-e2e-generic-pod"; - var client = CreateClient(); + using var client = CreateClient(); var genericPods = new GenericClient(client, "", "v1", "pods"); void Cleanup() @@ -590,7 +590,7 @@ namespace k8s.E2E var namespaceParameter = "default"; var podName = "k8scsharp-e2e-cp-pod"; - var client = CreateClient(); + using var client = CreateClient(); async Task CopyFileToPodAsync(string name, string @namespace, string container, Stream inputFileStream, string destinationFilePath, CancellationToken cancellationToken = default(CancellationToken)) { diff --git a/tests/Kubectl.Tests/KubectlTests.Version.cs b/tests/Kubectl.Tests/KubectlTests.Version.cs index 04c7609..fa584f5 100644 --- a/tests/Kubectl.Tests/KubectlTests.Version.cs +++ b/tests/Kubectl.Tests/KubectlTests.Version.cs @@ -1,4 +1,5 @@ using k8s.E2E; +using k8s.kubectl.beta; using System.Text.Json; using Xunit; @@ -9,7 +10,8 @@ public partial class KubectlTests [MinikubeFact] public void Version() { - var client = CreateClient(); + using var kubernetes = MinikubeTests.CreateClient(); + var client = new Kubectl(kubernetes); var version = client.Version(); var serverobj = version.ServerVersion; diff --git a/tests/Kubectl.Tests/KubectlTests.cs b/tests/Kubectl.Tests/KubectlTests.cs index b16b304..c9e1036 100644 --- a/tests/Kubectl.Tests/KubectlTests.cs +++ b/tests/Kubectl.Tests/KubectlTests.cs @@ -1,16 +1,9 @@ -using k8s.E2E; -using k8s.kubectl.beta; using System.Diagnostics; namespace k8s.kubectl.Tests; public partial class KubectlTests { - private Kubectl CreateClient() - { - return new Kubectl(MinikubeTests.CreateClient()); - } - private string RunKubectl(string args) { var p = new Process diff --git a/tests/KubernetesClient.Tests/CertUtilsTests.cs b/tests/KubernetesClient.Tests/CertUtilsTests.cs index ca09ff7..b7e0e31 100644 --- a/tests/KubernetesClient.Tests/CertUtilsTests.cs +++ b/tests/KubernetesClient.Tests/CertUtilsTests.cs @@ -29,7 +29,7 @@ namespace k8s.Tests useRelativePaths: false); // Just validate that this doesn't throw and private key is non-null - var cert = CertUtils.GeneratePfx(cfg); + using var cert = CertUtils.GeneratePfx(cfg); Assert.NotNull(cert.GetRSAPrivateKey()); } @@ -44,7 +44,7 @@ namespace k8s.Tests "federal-context"); // Just validate that this doesn't throw and private key is non-null - var cert = CertUtils.GeneratePfx(cfg); + using var cert = CertUtils.GeneratePfx(cfg); Assert.NotNull(cert.GetRSAPrivateKey()); } @@ -58,7 +58,7 @@ namespace k8s.Tests useRelativePaths: false); // Just validate that this doesn't throw and private key is non-null - var cert = CertUtils.GeneratePfx(cfg); + using var cert = CertUtils.GeneratePfx(cfg); Assert.NotNull(cert.GetRSAPrivateKey()); } @@ -73,7 +73,7 @@ namespace k8s.Tests "victorian-context"); // Just validate that this doesn't throw and private key is non-null - var cert = CertUtils.GeneratePfx(cfg); + using var cert = CertUtils.GeneratePfx(cfg); Assert.NotNull(cert.GetRSAPrivateKey()); } @@ -85,8 +85,8 @@ namespace k8s.Tests { 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"); + using var intermediateCert = new X509Certificate2("assets/ca-bundle-intermediate.crt"); + using var rootCert = new X509Certificate2("assets/ca-bundle-root.crt"); Assert.Equal(2, certCollection.Count);