安全地保存 Web 应用的密钥应用程序设置

概述

本文介绍如何安全地保存 Azure 应用程序的密钥应用程序配置设置。

传统上,所有 Web 应用配置设置都保存在配置文件(如 Web.config)中。这一做法会导致将密钥设置(如云凭据)签入到公共源代码管理系统(如 GitHub)中。 同时,因为更改源代码和重新配置开发设置都需要开销,因此会难以遵循安全最佳实践。

为了确保开发过程的安全性,创建了工具和框架库,以安全地保存应用程序机密设置,并最大程度地减少对源代码的更改或不对其进行更改。

ASP.NET 和 .NET Core 应用程序

将密钥设置保存在源代码管理文件夹外部的用户密钥存储中。

如果你正在快速建立原型或无法访问 Internet,请先将源代码管理文件夹外部的密钥设置移动到用户密钥存储。 用户密钥存储是保存在用户探查器文件夹下的一个文件,因此密钥不会签入到源代码管理。 下图演示了用户密钥的工作原理。

User Secret keeps secret settings outside of source control

如果正在运行 .NET Core 控制台应用程序,请使用密钥保管库来安全地保存你的密钥。

在 Azure 密钥保管库中保存密钥设置

如果正在开发一个项目,并需要安全地共享源代码,请使用 Azure Key Vault

  1. 在 Azure 订阅中创建密钥保管库。 填写 UI 上的所有必填字段,然后单击边栏选项卡底部的“创建”

    Create Azure Key Vault

  2. 授予你和团队成员访问密钥保管库的权限。 如果团队规模较大,可以创建 Microsoft Entra ID 组并向该安全组添加访问密钥保管库的权限。 在“密钥权限” 下拉列表中,检查“密钥管理操作” 下的“获取” 和“列表” 。 如果已创建 Web 应用,请向 Web 应用授予对 Key Vault 的访问权限,以便它可以访问密钥保管库,而无需在应用设置或文件中存储机密配置。 按名称搜索 Web 应用,并以向用户授予访问权限的相同方式添加该应用。

    Add Key Vault access policy

  3. 在 Azure 门户中将机密添加到 Key Vault。 对于嵌套的配置设置,请将“:”替换为“--”,以使密钥保管库密钥名称有效。 不能在密钥保管库密钥的名称中使用“:”。

    Add Key Vault secret

    注意

    在 Visual Studio 2017 V15.6 之前,我们曾建议安装 Visual Studio 的 Azure 服务身份验证扩展。 但是现在该扩展已弃用,因为它的功能已集成在 Visual Studio 中。 因此,如果你使用的是旧版本的 Visual Studio 2017,我们建议你更新至至少 VS 2017 15.6 或更高版本,以便可以本机使用此功能并使用 Visual Studio 登录标识本身访问密钥保管库。

  4. 将以下 NuGet 包添加到项目:

    Microsoft.Azure.KeyVault
    Microsoft.Azure.Services.AppAuthentication
    Microsoft.Extensions.Configuration.AzureKeyVault
    
  5. 将以下代码添加到 Program.cs 文件:

    public static IHostBuilder CreateHostBuilder(string[] args) =>
             Host.CreateDefaultBuilder(args)
                .ConfigureAppConfiguration((ctx, builder) =>
                {
                    var keyVaultEndpoint = GetKeyVaultEndpoint();
                    if (!string.IsNullOrEmpty(keyVaultEndpoint))
                    {
                        var azureServiceTokenProvider = new AzureServiceTokenProvider();
                        var keyVaultClient = new KeyVaultClient(
                            new KeyVaultClient.AuthenticationCallback(
                                azureServiceTokenProvider.KeyVaultTokenCallback));
                        builder.AddAzureKeyVault(
                        keyVaultEndpoint, keyVaultClient, new DefaultKeyVaultSecretManager());
                    }
                })
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    
        private static string GetKeyVaultEndpoint() => Environment.GetEnvironmentVariable("KEYVAULT_ENDPOINT");
    
  6. 将密钥保管库 URL 添加到 launchsettings.json 文件。 环境变量名称 KEYVAULT_ENDPOINT 将在步骤 6 添加的代码中进行定义 。

    Add Key Vault URL as a project environment variable

  7. 开始调试项目。 它应已成功运行。

ASP.NET 和 .NET 应用程序

.NET 4.7.1 支持密钥保管库和密钥配置生成器,这可以确保在不更改代码的情况下将密钥移动到源代码管理文件夹的外部。 若要继续,请下载 .NET 4.7.1,如果应用程序使用的是较旧版本的 .NET Framework,则将其进行迁移。

将密钥设置保存在源代码管理文件夹外部的密钥文件中。

如果正在快速编写原型,且不想预配 Azure 资源,请使用此选项。

  1. 右键单击项目并选择“管理用户机密”。 这将安装 NuGet 包 Microsoft.Configuration.ConfigurationBuilders.UserSecrets,创建一个文件以将机密设置保存在 web.config 文件之外,并在 web.config 文件中添加 ConfigBuilders 节。

  2. 将机密设置置于 root 元素下。 下面是一个示例

    <?xml version="1.0" encoding="utf-8"?>
    <root>
      <secrets ver="1.0">
        <secret name="secret" value="foo"/>
        <secret name="secret1" value="foo_one" />
        <secret name="secret2" value="foo_two" />
      </secrets>
    </root>
    
  3. 指定 appSettings 部分使用密钥配置生成器。 确保有含有虚拟值的机密设置的条目。

        <appSettings configBuilders="Secrets">
            <add key="webpages:Version" value="3.0.0.0" />
            <add key="webpages:Enabled" value="false" />
            <add key="ClientValidationEnabled" value="true" />
            <add key="UnobtrusiveJavaScriptEnabled" value="true" />
            <add key="secret" value="" />
        </appSettings>
    
  4. 调试应用。 它应已成功运行。

在 Azure Key Vault 中保存密钥设置

按照 ASP.NET Core 部分中的说明为你的项目配置密钥保管库。

  1. 将以下 NuGet 包安装到你的项目

    Microsoft.Configuration.ConfigurationBuilders.Azure
    
  2. 定义 Web.config 中的密钥保管库配置生成器。将该部分置于 appSettings 部分前。 如果 Key Vault 位于全局 Azure 中,则将 vaultName 替换为 Key Vault 名称;如果你在使用主权云,则将其替换为完整的 URI。

     <configBuilders>
        <builders>
            <add name="Secrets" userSecretsId="695823c3-6921-4458-b60b-2b82bbd39b8d" type="Microsoft.Configuration.ConfigurationBuilders.UserSecretsConfigBuilder, Microsoft.Configuration.ConfigurationBuilders.UserSecrets, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
            <add name="AzureKeyVault" vaultName="[VaultName]" type="Microsoft.Configuration.ConfigurationBuilders.AzureKeyVaultConfigBuilder, Microsoft.Configuration.ConfigurationBuilders.Azure, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
        </builders>
      </configBuilders>
    
  3. 指定 appSettings 部分使用密钥保管库配置生成器。 确保有任何含有虚拟值的密钥设置的条目。

    <appSettings configBuilders="AzureKeyVault">
        <add key="webpages:Version" value="3.0.0.0" />
        <add key="webpages:Enabled" value="false" />
        <add key="ClientValidationEnabled" value="true" />
        <add key="UnobtrusiveJavaScriptEnabled" value="true" />
        <add key="secret" value="" />
    </appSettings>
    
  4. 开始调试项目。 它应已成功运行。