Reputation: 3149
I have .NET 7 Web Api application where I m using the AddAzureKeyVault
method to add Azure Key Vault configurations to my IConfigurationBuilder instance. Currently, I am using the DefaultAzureCredential
for authentication.
However, I want to modify this method to authenticate the Key Vault request using clientId and thumbprint. I have access to these values and want to use them for authentication instead of the default credential types.
Here is my current code:
public static IConfigurationBuilder AddAzureKeyVaultConfiguration(this IConfigurationBuilder configurationBuilder, IWebHostEnvironment hostingEnvironment)
{
if (!hostingEnvironment.IsEnvironment("Localhost"))
{
var builtConfig = configurationBuilder.Build();
var keyVaultEndpoint = $"https://{builtConfig["KeyVaultConfigOption:Name"]}.vault.azure.net/";
configurationBuilder.AddAzureKeyVault(
new Uri(keyVaultEndpoint),
new DefaultAzureCredential(new DefaultAzureCredentialOptions
{
ExcludeEnvironmentCredential = true,
ExcludeInteractiveBrowserCredential = true,
ExcludeAzurePowerShellCredential = true,
ExcludeSharedTokenCacheCredential = true,
ExcludeVisualStudioCodeCredential = true,
ExcludeVisualStudioCredential = true,
ExcludeAzureCliCredential = false,
ExcludeManagedIdentityCredential = false,
})
);
}
return configurationBuilder;
}
}
Program.cs
var builder = WebApplication.CreateBuilder(args);
{
// Environment configuration
var configuration = builder.Configuration;
var env = builder.Environment;
configuration.AddAppConfiguration(env);
// Add azure key vault configuration
builder.Configuration.AddAzureKeyVaultConfiguration(env);
builder.Services.AddMediatR(cfg => cfg.RegisterServicesFromAssemblyContaining<Program>());
builder.Services.AddHttpClient();
builder.Services.AddApplication();
builder.Services.AddInfrastructure(builder.Configuration);
builder.Services.AddHelpers();
builder.Services.AddControllers()
// Configures the JSON serialization options for controllers.
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = null;
});
builder.Services.Configure<ApiBehaviorOptions>(options =>
{
options.SuppressModelStateInvalidFilter = true;
});
}
var app = builder.Build();
{
app.UseHttpsRedirection();
// Authentication & Authorization
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.UseRouting();
app.UseSwaggerWithVersioning();
}
if (app.Environment.IsDevelopment())
{
//DEV configurations
}
app.Run();
appsettings.json
"KeyVaultConfigOption": {
"Name": "{KeyValultName}",
"Url": "https://{KeyVaultName}.vault.azure.net",
"Thumbprint": "",
"ClientId": ""
}
How can I modify this method to authenticate the Azure Key Vault request using ClientId
and Thumbprint
?
Upvotes: 0
Views: 598
Reputation: 3149
As Pramod suggested in the previous answer, I made the following changes accordingly and now I am able to authenticate key vault request with certificates.
public static IConfigurationBuilder AddAzureKeyVaultConfiguration(this IConfigurationBuilder configurationBuilder, IWebHostEnvironment hostingEnvironment)
{
if (!hostingEnvironment.IsEnvironment("Development"))
{
var builtConfig = configurationBuilder.Build();
var keyVaultEndpoint = $"https://{builtConfig["KeyVaultConfigOption:Name"]}.vault.azure.net/";
var clientId = builtConfig["KeyVaultConfigOption:ClientId"];
var thumbprint = builtConfig["KeyVaultConfigOption:Thumbprint"];
var tenantId = builtConfig["KeyVaultConfigOption:TenantId"];
var certificate = GetCertificate(thumbprint);
var clientCertificateCredential = new ClientCertificateCredential(tenantId, clientId, certificate);
configurationBuilder.AddAzureKeyVault(new Uri(keyVaultEndpoint), clientCertificateCredential);
var keyVaultClient = new SecretClient(new Uri(keyVaultEndpoint), clientCertificateCredential);
Task.Run(() => LoadKeysFromKeyVault(configurationBuilder, keyVaultClient)).Wait();
}
return configurationBuilder;
}
private static X509Certificate2 GetCertificate(string thumbprint)
{
var store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
store.Open(OpenFlags.ReadOnly);
var cert = store.Certificates.OfType<X509Certificate2>()
.FirstOrDefault(x => x.Thumbprint == thumbprint);
store.Close();
if (cert == null)
throw new InvalidOperationException($"Failed to find the certificate for thumbprint:{thumbprint}");
return cert;
}
private static async Task LoadKeysFromKeyVault(IConfigurationBuilder configurationBuilder, SecretClient keyVaultClient)
{
var serviceBusConfig = configurationBuilder.Build().GetSection(ServiceBusConfigOption.SectionName).Get<ServiceBusConfigOption>();
var propertiesToLoad = new Dictionary<string, string>
{
{ $"{ServiceBusConfigOption.SectionName}:{nameof(serviceBusConfig.ConnectionString)}", serviceBusConfig.ConnectionString },
};
foreach (var kvp in propertiesToLoad)
{
var configurationKey = kvp.Key;
var secretName = kvp.Value;
var secret = await keyVaultClient.GetSecretAsync(secretName);
// Modify the configuration to replace the key value
configurationBuilder.Sources.RemoveAt(configurationBuilder.Sources.Count - 1); // Remove the Key Vault source
configurationBuilder.AddInMemoryCollection(new Dictionary<string, string>
{
{ configurationKey, secret.Value.Value }
});
}
}
Upvotes: 0
Reputation: 6647
You can use the ClientCertificateCredential
along with the X509Certificate2
object.
To first fetch the certificate required, use the thumbprint to find the certificate from the X509Store
.
Upvotes: 1