Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3,339 changes: 2,278 additions & 1,061 deletions AspNetCore.Diagnostics.HealthChecks.sln

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions build/versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
<HealthCheckAzureDigitalTwin>9.0.0</HealthCheckAzureDigitalTwin>
<HealthCheckAzureSearch>9.0.0</HealthCheckAzureSearch>
<HealthCheckAzureDataTables>9.0.0</HealthCheckAzureDataTables>
<HealthCheckAzureKeyVaultCertificates>9.0.0</HealthCheckAzureKeyVaultCertificates>
<HealthCheckAzureKeyVaultKeys>9.0.0</HealthCheckAzureKeyVaultKeys>
<HealthCheckAzureKeyVaultSecrets>9.0.0</HealthCheckAzureKeyVaultSecrets>
<HealthCheckAzureMessagingEventsHubs>9.0.0</HealthCheckAzureMessagingEventsHubs>
<HealthCheckAzureServiceBus>9.0.0</HealthCheckAzureServiceBus>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using Azure;
using Azure.Security.KeyVault.Certificates;
using Microsoft.Extensions.Diagnostics.HealthChecks;

namespace HealthChecks.Azure.KeyVault.Certificates;

public sealed class AzureKeyVaultCertificatesHealthCheck : IHealthCheck
{
private readonly CertificateClient _certificateClient;
private readonly AzureKeyVaultCertificatesHealthCheckOptions _options;

public AzureKeyVaultCertificatesHealthCheck(CertificateClient certificateClient, AzureKeyVaultCertificatesHealthCheckOptions? options = default)
{
_certificateClient = Guard.ThrowIfNull(certificateClient);
_options = options ?? new AzureKeyVaultCertificatesHealthCheckOptions();
}

public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
{
string certificateName = _options.CertificateName;

try
{
await _certificateClient.GetCertificateAsync(certificateName, cancellationToken).ConfigureAwait(false);
return new HealthCheckResult(HealthStatus.Healthy);
}
catch (RequestFailedException azureEx) when (azureEx.Status == 404)
{
return new HealthCheckResult(HealthStatus.Healthy);
}
catch (Exception ex)
{
return new HealthCheckResult(context.Registration.FailureStatus, exception: ex);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace HealthChecks.Azure.KeyVault.Certificates;

public sealed class AzureKeyVaultCertificatesHealthCheckOptions
{
private string _certificateName = nameof(AzureKeyVaultCertificatesHealthCheck);

public string CertificateName
{
get => _certificateName;
set => _certificateName = Guard.ThrowIfNull(value, throwOnEmptyString: true, paramName: nameof(CertificateName));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Azure.Security.KeyVault.Certificates;
using HealthChecks.Azure.KeyVault.Certificates;
using Microsoft.Extensions.Diagnostics.HealthChecks;

namespace Microsoft.Extensions.DependencyInjection;

public static class AzureKeyVaultCertificatesHealthChecksBuilderExtensions
{
private const string NAME = "azure_key_vault_certificate";

public static IHealthChecksBuilder AddAzureKeyVaultCertificates(
this IHealthChecksBuilder builder,
Func<IServiceProvider, CertificateClient>? clientFactory = default,
Func<IServiceProvider, AzureKeyVaultCertificatesHealthCheckOptions>? optionsFactory = default,
string? name = NAME,
HealthStatus? failureStatus = default,
IEnumerable<string>? tags = default,
TimeSpan? timeout = default)
{
return builder.Add(new HealthCheckRegistration(
name ?? NAME,
sp => new AzureKeyVaultCertificatesHealthCheck(
certificateClient: clientFactory?.Invoke(sp) ?? sp.GetRequiredService<CertificateClient>(),
options: optionsFactory?.Invoke(sp)),
failureStatus,
tags,
timeout));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>$(DefaultLibraryTargetFrameworks)</TargetFrameworks>
<PackageTags>$(PackageTags);Azure Key Vault;Certificates</PackageTags>
<Description>HealthChecks.Azure.KeyVault.Certificates is the health check package for Azure Key Vault certificates</Description>
<VersionPrefix>$(HealthCheckAzureKeyVaultCertificates)</VersionPrefix>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Azure.Security.KeyVault.Certificates" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using Azure;
using Azure.Security.KeyVault.Keys;
using Microsoft.Extensions.Diagnostics.HealthChecks;

namespace HealthChecks.Azure.KeyVault.Keys;

public sealed class AzureKeyVaultKeysHealthCheck : IHealthCheck
{
private readonly KeyClient _keyClient;
private readonly AzureKeyVaultKeysHealthCheckOptions _options;

public AzureKeyVaultKeysHealthCheck(KeyClient keyClient, AzureKeyVaultKeysHealthCheckOptions? options = default)
{
_keyClient = Guard.ThrowIfNull(keyClient);
_options = options ?? new AzureKeyVaultKeysHealthCheckOptions();
}

public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default)
{
string keyName = _options.KeyName;

try
{
await _keyClient.GetKeyAsync(keyName, cancellationToken: cancellationToken).ConfigureAwait(false);
return new HealthCheckResult(HealthStatus.Healthy);
}
catch (RequestFailedException azureEx) when (azureEx.Status == 404)
{
return new HealthCheckResult(HealthStatus.Healthy);
}
catch (Exception ex)
{
return new HealthCheckResult(context.Registration.FailureStatus, exception: ex);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace HealthChecks.Azure.KeyVault.Keys;

public sealed class AzureKeyVaultKeysHealthCheckOptions
{
private string _keyName = nameof(AzureKeyVaultKeysHealthCheck);

public string KeyName
{
get => _keyName;
set => _keyName = Guard.ThrowIfNull(value, throwOnEmptyString: true, paramName: nameof(KeyName));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Azure.Security.KeyVault.Keys;
using HealthChecks.Azure.KeyVault.Keys;
using Microsoft.Extensions.Diagnostics.HealthChecks;

namespace Microsoft.Extensions.DependencyInjection;

public static class AzureKeyVaultKeysHealthChecksBuilderExtensions
{
private const string NAME = "azure_key_vault_key";

public static IHealthChecksBuilder AddAzureKeyVaultKeys(
this IHealthChecksBuilder builder,
Func<IServiceProvider, KeyClient>? clientFactory = default,
Func<IServiceProvider, AzureKeyVaultKeysHealthCheckOptions>? optionsFactory = default,
string? name = NAME,
HealthStatus? failureStatus = default,
IEnumerable<string>? tags = default,
TimeSpan? timeout = default)
{
return builder.Add(new HealthCheckRegistration(
name ?? NAME,
sp => new AzureKeyVaultKeysHealthCheck(
keyClient: clientFactory?.Invoke(sp) ?? sp.GetRequiredService<KeyClient>(),
options: optionsFactory?.Invoke(sp)),
failureStatus,
tags,
timeout));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>$(DefaultLibraryTargetFrameworks)</TargetFrameworks>
<PackageTags>$(PackageTags);Azure Key Vault;Keys</PackageTags>
<Description>HealthChecks.Azure.KeyVault.Keys is the health check package for Azure Key Vault keys</Description>
<VersionPrefix>$(HealthCheckAzureKeyVaultKeys)</VersionPrefix>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Azure.Security.KeyVault.Keys" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Azure.Identity;
using Azure.Security.KeyVault.Certificates;
using HealthChecks.Azure.KeyVault.Certificates;

namespace HealthChecks.Azure.KeyVault.Certificates.Tests;

public class CertificatesConformanceTests : ConformanceTests<CertificateClient, AzureKeyVaultCertificatesHealthCheck, AzureKeyVaultCertificatesHealthCheckOptions>
{
protected override CertificateClient CreateClientForNonExistingEndpoint()
{
CertificateClientOptions clientOptions = new();
clientOptions.Retry.MaxRetries = 0; // don't enable retries (test runs few times faster)
return new(new Uri("https://www.thisisnotarealurl.com"), new DefaultAzureCredential(), clientOptions);
}

protected override AzureKeyVaultCertificatesHealthCheckOptions CreateHealthCheckOptions() => new();

protected override AzureKeyVaultCertificatesHealthCheck CreateHealthCheck(CertificateClient client, AzureKeyVaultCertificatesHealthCheckOptions? options)
=> new(client, options);

protected override IHealthChecksBuilder AddHealthCheck(IHealthChecksBuilder builder, Func<IServiceProvider, CertificateClient>? clientFactory = null, Func<IServiceProvider, AzureKeyVaultCertificatesHealthCheckOptions>? optionsFactory = null, string? healthCheckName = null, HealthStatus? failureStatus = null, IEnumerable<string>? tags = null, TimeSpan? timeout = null)
=> builder.AddAzureKeyVaultCertificates(clientFactory, optionsFactory, healthCheckName, failureStatus, tags, timeout);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using HealthChecks.Azure.KeyVault.Certificates;

namespace HealthChecks.Azure.KeyVault.Certificates.Tests.Functional;

public class AzureKeyVaultCertificateOptionsTests
{
[Fact]
public void CertificateNameThrowsArgumentNullExceptionForNull()
{
AzureKeyVaultCertificatesHealthCheckOptions sut = new();
ArgumentNullException argumentNullException = Assert.ThrowsAny<ArgumentNullException>(() => sut.CertificateName = null!);
Assert.Equal("CertificateName", argumentNullException.ParamName);
}

[Fact]
public void CertificateNameThrowsArgumentNullExceptionForEmptyString()
{
AzureKeyVaultCertificatesHealthCheckOptions sut = new();
ArgumentException argumentException = Assert.ThrowsAny<ArgumentException>(() => sut.CertificateName = string.Empty);
Assert.Equal("CertificateName", argumentException.ParamName);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">

<ItemGroup>
<PackageReference Include="Azure.Identity" />
<ProjectReference Include="..\..\src\HealthChecks.Azure.KeyVault.Certificates\HealthChecks.Azure.KeyVault.Certificates.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace HealthChecks.Azure.KeyVault.Certificates
{
public sealed class AzureKeyVaultCertificatesHealthCheck : Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck
{
public AzureKeyVaultCertificatesHealthCheck(Azure.Security.KeyVault.Certificates.CertificateClient certificateClient, HealthChecks.Azure.KeyVault.Certificates.AzureKeyVaultCertificatesHealthCheckOptions? options = null) { }
public System.Threading.Tasks.Task<Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult> CheckHealthAsync(Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckContext context, System.Threading.CancellationToken cancellationToken = default) { }
}
public sealed class AzureKeyVaultCertificatesHealthCheckOptions
{
public AzureKeyVaultCertificatesHealthCheckOptions() { }
public string CertificateName { get; set; }
}
}
namespace Microsoft.Extensions.DependencyInjection
{
public static class AzureKeyVaultCertificatesHealthChecksBuilderExtensions
{
public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureKeyVaultCertificates(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Func<System.IServiceProvider, Azure.Security.KeyVault.Certificates.CertificateClient>? clientFactory = null, System.Func<System.IServiceProvider, HealthChecks.Azure.KeyVault.Certificates.AzureKeyVaultCertificatesHealthCheckOptions>? optionsFactory = null, string? name = "azure_key_vault_certificate", Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable<string>? tags = null, System.TimeSpan? timeout = default) { }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using HealthChecks.Azure.KeyVault.Keys;

namespace HealthChecks.Azure.KeyVault.Keys.Tests.Functional;

public class AzureKeyVaultKeyOptionsTests
{
[Fact]
public void KeyNameThrowsArgumentNullExceptionForNull()
{
AzureKeyVaultKeysHealthCheckOptions sut = new();
ArgumentNullException argumentNullException = Assert.ThrowsAny<ArgumentNullException>(() => sut.KeyName = null!);
Assert.Equal("KeyName", argumentNullException.ParamName);
}

[Fact]
public void KeyNameThrowsArgumentNullExceptionForEmptyString()
{
AzureKeyVaultKeysHealthCheckOptions sut = new();
ArgumentException argumentException = Assert.ThrowsAny<ArgumentException>(() => sut.KeyName = string.Empty);
Assert.Equal("KeyName", argumentException.ParamName);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">

<ItemGroup>
<PackageReference Include="Azure.Identity" />
<ProjectReference Include="..\..\src\HealthChecks.Azure.KeyVault.Keys\HealthChecks.Azure.KeyVault.Keys.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace HealthChecks.Azure.KeyVault.Keys
{
public sealed class AzureKeyVaultKeysHealthCheck : Microsoft.Extensions.Diagnostics.HealthChecks.IHealthCheck
{
public AzureKeyVaultKeysHealthCheck(Azure.Security.KeyVault.Keys.KeyClient keyClient, HealthChecks.Azure.KeyVault.Keys.AzureKeyVaultKeysHealthCheckOptions? options = null) { }
public System.Threading.Tasks.Task<Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckResult> CheckHealthAsync(Microsoft.Extensions.Diagnostics.HealthChecks.HealthCheckContext context, System.Threading.CancellationToken cancellationToken = default) { }
}
public sealed class AzureKeyVaultKeysHealthCheckOptions
{
public AzureKeyVaultKeysHealthCheckOptions() { }
public string KeyName { get; set; }
}
}
namespace Microsoft.Extensions.DependencyInjection
{
public static class AzureKeyVaultKeysHealthChecksBuilderExtensions
{
public static Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder AddAzureKeyVaultKeys(this Microsoft.Extensions.DependencyInjection.IHealthChecksBuilder builder, System.Func<System.IServiceProvider, Azure.Security.KeyVault.Keys.KeyClient>? clientFactory = null, System.Func<System.IServiceProvider, HealthChecks.Azure.KeyVault.Keys.AzureKeyVaultKeysHealthCheckOptions>? optionsFactory = null, string? name = "azure_key_vault_key", Microsoft.Extensions.Diagnostics.HealthChecks.HealthStatus? failureStatus = default, System.Collections.Generic.IEnumerable<string>? tags = null, System.TimeSpan? timeout = default) { }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Azure.Identity;
using Azure.Security.KeyVault.Keys;
using HealthChecks.Azure.KeyVault.Keys;

namespace HealthChecks.Azure.KeyVault.Keys.Tests;

public class KeysConformanceTests : ConformanceTests<KeyClient, AzureKeyVaultKeysHealthCheck, AzureKeyVaultKeysHealthCheckOptions>
{
protected override KeyClient CreateClientForNonExistingEndpoint()
{
KeyClientOptions clientOptions = new();
clientOptions.Retry.MaxRetries = 0; // don't enable retries (test runs few times faster)
return new(new Uri("https://www.thisisnotarealurl.com"), new DefaultAzureCredential(), clientOptions);
}

protected override AzureKeyVaultKeysHealthCheckOptions CreateHealthCheckOptions() => new();

protected override AzureKeyVaultKeysHealthCheck CreateHealthCheck(KeyClient client, AzureKeyVaultKeysHealthCheckOptions? options)
=> new(client, options);

protected override IHealthChecksBuilder AddHealthCheck(IHealthChecksBuilder builder, Func<IServiceProvider, KeyClient>? clientFactory = null, Func<IServiceProvider, AzureKeyVaultKeysHealthCheckOptions>? optionsFactory = null, string? healthCheckName = null, HealthStatus? failureStatus = null, IEnumerable<string>? tags = null, TimeSpan? timeout = null)
=> builder.AddAzureKeyVaultKeys(clientFactory, optionsFactory, healthCheckName, failureStatus, tags, timeout);
}