如何在不将客户端机密存储在 appsettings.json 中的情况下获取 Azure Key Vault 机密?

How to get AzureKeyVault Secret without storing the ClientSecret in appsettings.json?

如何在不将 ClientSecret 存储在 appsettings.json 中的情况下获取 AzureKeyVault Secret?我们在 .NET 5 中有一个使用依赖注入的 WinForms 应用程序,我们想向 ServiceProvider 添加两项服务,同时只需要一个 SSO 登录提示 and 从 [=33] 中删除 KeyVault 秘密字符串=] 文件.

当使用 Visual Studio 登录到 Azure 时,对 builder.AddAzureKeyVault(SecretClient, new KeyVaultSecretManager()) 的调用有效。当我们为 Visual Studio 未登录的虚拟机部署应用程序时,这会中断。我们可以通过传入 secret 值来使其工作,但我们不想将其存储在任何一个中代码或应用程序设置。我们如何将 secret 存储在 KeyVault 中,然后检索它以便我们可以添加 AddAzureKeyVault 服务?

当我们注销 Visual Studio(即 ExcludeVisualStudioCredential = true)时,我们会收到以下错误:

Azure.Identity.CredentialUnavailableException: 'DefaultAzureCredential failed to retrieve a token from the included credentials.

  • EnvironmentCredential authentication unavailable. Environment variables are not fully configured.
  • ManagedIdentityCredential authentication unavailable. No Managed Identity endpoint found.
  • Process "C:\Program Files (x86)\Microsoft Visual Studio19\Community\Common7\IDE\Extensions\gwrwzu2y.rwb\TokenService\Microsoft.Asal.TokenService.exe" has failed with unexpected error: TS003: Error, TS005: No accounts found. Please go to Tools->Options->Azure Services Authentication, and add an account to be to authenticate to Azure services during development..
  • Stored credentials not found. Need to authenticate user in VSCode Azure Account.
  • Azure CLI not installed
  • Please run 'Connect-AzAccount' to set up account.'

注1:我们使用的是单点登录,可以取回AccessToken。因此,我们可以访问 AccessToken。

注意 2:我们使用 SlowCheetah 进行多个环境配置,因此我们没有 ENVIRONMENT_VARIABLES 设置。

来自 Program.cs

Static Void Main()
{
...
Host = Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder()
    .ConfigureAppConfiguration((context, builder) =>
    {
        builder.SetBasePath(AppDomain.CurrentDomain.BaseDirectory)
            ;

        builder.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            ;

        // Set the Configuration. We need to build the Configuration here so that we can get access to the Appsettings in order to
        // set the SecretClient and add the Azure Key Vault. We will then need to set the Configuration again in order to capture this
        // new service.
        Configuration = builder.Build();

        SetSecretClient(Configuration);

        // Add the Azure Key Vault. This only works when signed into Azure via Visual Studio
        builder.AddAzureKeyVault(SecretClient, new KeyVaultSecretManager());
    })
    .ConfigureServices((context, services) =>
    {
        Configuration = context.Configuration;

        SignInUserSSO();

        ConfigureServices(Configuration, services);
    })
    .Build();
...
}

private static void SetSecretClient(IConfiguration objConfiguration)
{
    DefaultAzureCredentialOptions objDefaultAzureCredentialOptions;
    SecretClientOptions objSecretClientOptions;

    string strAzureKeyVaultResourceIdentifier = objConfiguration.GetValue<string>("Azure:FirmId:ResourceIdentifiers:KeyVault");
    string strAzureKeyVaultName = objConfiguration.GetValue<string>("Azure:FirmId:KeyVaults:NameOfKeyVault");
    string strAzureKeyVaultUri = strAzureKeyVaultResourceIdentifier.Replace("{KeyVaultName}", strAzureKeyVaultName);

    // Set the options on the SecretClient. These are default values recommended by Microsoft.
    objSecretClientOptions = new SecretClientOptions()
    {
        Retry =
        {
            Delay= TimeSpan.FromSeconds(2),
            MaxDelay = TimeSpan.FromSeconds(16),
            MaxRetries = 5,
            Mode = RetryMode.Exponential
            }
    };

    objDefaultAzureCredentialOptions = new DefaultAzureCredentialOptions
    {
        ExcludeEnvironmentCredential = true,
        ExcludeManagedIdentityCredential = false,
        ExcludeSharedTokenCacheCredential = true,
        ExcludeVisualStudioCredential = true,
        ExcludeVisualStudioCodeCredential = true,
        ExcludeAzureCliCredential = true,
        ExcludeInteractiveBrowserCredential = true
    };

    SecretClient = new SecretClient(
        vaultUri: new Uri(strAzureKeyVaultUri),
        credential: new DefaultAzureCredential(objDefaultAzureCredentialOptions),
        objSecretClientOptions
        );
}

DefaultAzureCredential使用多种身份验证方法来支持生产和开发环境,而无需更改代码。因此,虽然您可以在开发期间使用您的 Visual Studio、Azure CLI 或其他凭据,但您可以在生产中将环境变量与服务主体或托管标识一起使用。对于 VM,托管身份可能是最容易配置的,对于不支持托管身份的服务,您可以使用在您的服务上配置的环境变量,这些环境变量被授权访问您的 Key Vault。

FWIW,如果您想简化代码,建议的默认重试设置已经是默认设置,无需指定 SecretClientOptions 实例。