如何在.NET 7 Web Api中使用clientId和thumbprint对Azure Key Vault请求进行身份验证?

huangapple go评论64阅读模式
英文:

How to authenticate Azure Key Vault request using clientId and thumbprint in .NET 7 Web Api?

问题

我可以帮你修改这个方法,以便使用 ClientIdThumbprint 进行 Azure Key Vault 的身份验证。请查看下面的修改后的代码:

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/";

        var clientId = builtConfig["KeyVaultConfigOption:ClientId"];
        var thumbprint = builtConfig["KeyVaultConfigOption:Thumbprint"];

        var tokenCredential = new ClientCertificateCredential(clientId, thumbprint);

        configurationBuilder.AddAzureKeyVault(
            new Uri(keyVaultEndpoint),
            tokenCredential
        );
    }

    return configurationBuilder;
}

在这个修改后的方法中,我使用了 ClientCertificateCredential 类来创建凭据,其中包括了 ClientIdThumbprint。这将用于 Azure Key Vault 的身份验证。请确保在 appsettings.json 文件中设置了正确的 ClientIdThumbprint 值。

希望这可以帮助你实现所需的修改。如果你有任何其他问题,请随时提问。

英文:

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?

答案1

得分: 1

你可以使用 ClientCertificateCredentialX509Certificate2 对象。

首先,使用指纹来从 X509Store 中查找所需的证书。

英文:

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.

答案2

得分: 0

如Pramod在先前的回答中建议的,我做出了相应的更改,现在我能够使用证书对密钥保管库请求进行身份验证。

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 }
        });
    }
}
英文:

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(&quot;Development&quot;))
            {
                var builtConfig = configurationBuilder.Build();
                var keyVaultEndpoint = $&quot;https://{builtConfig[&quot;KeyVaultConfigOption:Name&quot;]}.vault.azure.net/&quot;;

                var clientId = builtConfig[&quot;KeyVaultConfigOption:ClientId&quot;];
                var thumbprint = builtConfig[&quot;KeyVaultConfigOption:Thumbprint&quot;];
                var tenantId = builtConfig[&quot;KeyVaultConfigOption:TenantId&quot;];

                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(() =&gt; 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&lt;X509Certificate2&gt;()
                .FirstOrDefault(x =&gt; x.Thumbprint == thumbprint);
            store.Close();

            if (cert == null)
                throw new InvalidOperationException($&quot;Failed to find the certificate for thumbprint:{thumbprint}&quot;);

            return cert;
        }

        private static async Task LoadKeysFromKeyVault(IConfigurationBuilder configurationBuilder, SecretClient keyVaultClient)
        {
            var serviceBusConfig = configurationBuilder.Build().GetSection(ServiceBusConfigOption.SectionName).Get&lt;ServiceBusConfigOption&gt;();

            var propertiesToLoad = new Dictionary&lt;string, string&gt;
            {
                { $&quot;{ServiceBusConfigOption.SectionName}:{nameof(serviceBusConfig.ConnectionString)}&quot;, 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&lt;string, string&gt;
                {
                    { configurationKey, secret.Value.Value }
                });
            }
        }

huangapple
  • 本文由 发表于 2023年6月1日 14:58:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/76379386.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定