diff --git a/src/HealthChecks.RavenDB/RavenDBHealthCheck.cs b/src/HealthChecks.RavenDB/RavenDBHealthCheck.cs index 66158c8fd7..ca30b05ed7 100644 --- a/src/HealthChecks.RavenDB/RavenDBHealthCheck.cs +++ b/src/HealthChecks.RavenDB/RavenDBHealthCheck.cs @@ -49,6 +49,10 @@ public async Task CheckHealthAsync(HealthCheckContext context Certificate = o.Certificate }; + // Health check doesn't own the certificate lifetime; it may be shared (e.g. DI/KeyVault). + // Disposing it can break other RavenDB stores in the process. + store.Conventions.DisposeCertificate = false; + try { store.Initialize(); diff --git a/test/HealthChecks.RavenDb.Tests/Functional/RavenDbHealthCheckTests.cs b/test/HealthChecks.RavenDb.Tests/Functional/RavenDbHealthCheckTests.cs index b727039a9e..6efa6aa771 100644 --- a/test/HealthChecks.RavenDb.Tests/Functional/RavenDbHealthCheckTests.cs +++ b/test/HealthChecks.RavenDb.Tests/Functional/RavenDbHealthCheckTests.cs @@ -1,4 +1,7 @@ using System.Net; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using HealthChecks.RavenDB; using HealthChecks.UI.Client; namespace HealthChecks.RavenDb.Tests.Functional; @@ -151,4 +154,31 @@ public async Task be_unhealthy_if_ravendb_is_available_but_database_doesnot_exis response.StatusCode.ShouldBe(HttpStatusCode.ServiceUnavailable, await response.Content.ReadAsStringAsync()); } + + [Fact] + public async Task not_dispose_shared_certificate_when_store_initialization_fails() + { + using var rsa = RSA.Create(2048); + var certificateRequest = new CertificateRequest("CN=ravendb-healthcheck-test", rsa, HashAlgorithmName.SHA256, RSASignaturePadding.Pkcs1); + using var certificate = certificateRequest.CreateSelfSigned(DateTimeOffset.UtcNow.AddDays(-1), DateTimeOffset.UtcNow.AddDays(1)); + + var options = new RavenDBOptions + { + Urls = ["http://localhost:0"], + Certificate = certificate + }; + + var healthCheck = new RavenDBHealthCheck(options); + var context = new HealthCheckContext + { + Registration = new HealthCheckRegistration("ravendb", _ => healthCheck, HealthStatus.Unhealthy, tags: null) + }; + + var result = await healthCheck.CheckHealthAsync(context); + + result.Status.ShouldBe(HealthStatus.Unhealthy); + + using var privateKey = certificate.GetRSAPrivateKey(); + privateKey.ShouldNotBeNull(); + } }