ASP.NET Core 中的 azure Key Vault 組態提供者Azure Key Vault Configuration Provider in ASP.NET Core

藉由Luke LathamAndrew Stanton-nurseBy Luke Latham and Andrew Stanton-Nurse

本文件說明如何使用Microsoft Azure Key Vault組態提供者,從 Azure Key Vault 祕密載入應用程式組態值。This document explains how to use the Microsoft Azure Key Vault Configuration Provider to load app configuration values from Azure Key Vault secrets. Azure Key Vault 是雲端式服務,可以協助使用者保護密碼編譯金鑰和應用程式和服務所使用的密碼。Azure Key Vault is a cloud-based service that assists in safeguarding cryptographic keys and secrets used by apps and services. ASP.NET Core 應用程式使用 Azure 金鑰保存庫的常見案例包括:Common scenarios for using Azure Key Vault with ASP.NET Core apps include:

  • 控制對敏感的組態資料的存取。Controlling access to sensitive configuration data.
  • 儲存組態資料時,符合 fips 需求 140-2 Level 2 驗證的硬體安全性模組 (HSM)。Meeting the requirement for FIPS 140-2 Level 2 validated Hardware Security Modules (HSM's) when storing configuration data.

此案例是適用於應用程式為目標的 ASP.NET Core 2.1 或更新版本。This scenario is available for apps that target ASP.NET Core 2.1 or later.

檢視或下載範例程式碼 (英文) (如何下載)View or download sample code (how to download)

封裝Packages

若要使用 Azure 金鑰保存庫的組態提供者,將新增的套件參考Microsoft.Extensions.Configuration.AzureKeyVault封裝。To use the Azure Key Vault Configuration Provider, add a package reference to the Microsoft.Extensions.Configuration.AzureKeyVault package.

採用管理 Azure 資源的身分識別案例中,新增的套件參考Microsoft.Azure.Services.AppAuthentication封裝。To adopt the Managed identities for Azure resources scenario, add a package reference to the Microsoft.Azure.Services.AppAuthentication package.

注意

在本文撰寫之際,最新穩定版本Microsoft.Azure.Services.AppAuthentication,版本1.0.3,可讓您系統指派給受控身分識別At the time of writing, the latest stable release of Microsoft.Azure.Services.AppAuthentication, version 1.0.3, provides support for system-assigned managed identities. 支援指派使用者給受控身分識別位於1.2.0-preview2封裝。Support for user-assigned managed identities is available in the 1.2.0-preview2 package. 本主題示範如何使用系統管理的身分識別,並提供的範例應用程式使用的版本1.0.3Microsoft.Azure.Services.AppAuthentication封裝。This topic demonstrates the use of system-managed identities, and the provided sample app uses version 1.0.3 of the Microsoft.Azure.Services.AppAuthentication package.

範例應用程式Sample app

範例應用程式執行所決定的兩種模式之一#define陳述式,在頂端Program.cs檔案:The sample app runs in either of two modes determined by the #define statement at the top of the Program.cs file:

  • Certificate – 示範如何使用 Azure Key Vault 中儲存的存取祕密的 Azure 金鑰保存庫用戶端識別碼和 X.509 憑證。Certificate – Demonstrates the use of an Azure Key Vault Client ID and X.509 certificate to access secrets stored in Azure Key Vault. 從任何位置,部署至 Azure App Service 或任何能夠為 ASP.NET Core 應用程式的主機,可以執行此版本的範例。This version of the sample can be run from any location, deployed to Azure App Service or any host capable of serving an ASP.NET Core app.
  • Managed – 示範如何使用管理 Azure 資源的身分識別驗證的應用程式至 Azure Key Vault 與 Azure AD 驗證不含認證儲存在應用程式的程式碼或組態。Managed – Demonstrates how to use Managed identities for Azure resources to authenticate the app to Azure Key Vault with Azure AD authentication without credentials stored in the app's code or configuration. 當使用受管理的身分識別進行驗證,不需要的 Azure AD 應用程式識別碼和密碼 (用戶端祕密)。When using managed identities to authenticate, an Azure AD Application ID and Password (Client Secret) aren't required. Managed範例版本必須部署至 Azure。The Managed version of the sample must be deployed to Azure. 請依照下列中的指導方針適用於 Azure 資源使用受控身分識別一節。Follow the guidance in the Use the Managed identities for Azure resources section.

如需有關如何設定範例應用程式使用前置處理器指示詞 (#define),請參閱ASP.NET Core 簡介For more information on how to configure a sample app using preprocessor directives (#define), see ASP.NET Core 簡介.

在開發環境中的祕密儲存體Secret storage in the Development environment

設定在本機使用的祕密Secret Manager 工具Set secrets locally using the Secret Manager tool. 當在開發環境中本機電腦上,執行範例應用程式時,會載入密碼從本機的祕密管理員存放區。When the sample app runs on the local machine in the Development environment, secrets are loaded from the local Secret Manager store.

Secret Manager 工具需要<UserSecretsId>應用程式的專案檔中的屬性。The Secret Manager tool requires a <UserSecretsId> property in the app's project file. 設定屬性值 ({GUID}) 任何唯一的 guid:Set the property value ({GUID}) to any unique GUID:

<PropertyGroup>
  <UserSecretsId>{GUID}</UserSecretsId>
</PropertyGroup>

密碼會建立為名稱 / 值組。Secrets are created as name-value pairs. 階層式的值 (組態區段) 會使用:(冒號) 為分隔符號ASP.NET Core 組態索引鍵名稱。Hierarchical values (configuration sections) use a : (colon) as a separator in ASP.NET Core configuration key names.

Secret Manager 可從命令殼層,開啟專案的內容根目錄,其中{SECRET NAME}名稱和{SECRET VALUE}的值:The Secret Manager is used from a command shell opened to the project's content root, where {SECRET NAME} is the name and {SECRET VALUE} is the value:

dotnet user-secrets set "{SECRET NAME}" "{SECRET VALUE}"

從專案的內容根目錄設定範例應用程式祕密命令殼層中執行下列命令:Execute the following commands in a command shell from the project's content root to set the secrets for the sample app:

dotnet user-secrets set "SecretName" "secret_value_1_dev"
dotnet user-secrets set "Section:SecretName" "secret_value_2_dev"

當這些祕密儲存在 Azure Key Vault生產環境使用 Azure Key Vault 中密碼的儲存體區段中,_dev後置詞變更為_prodWhen these secrets are stored in Azure Key Vault in the Secret storage in the Production environment with Azure Key Vault section, the _dev suffix is changed to _prod. 後置詞提供視覺提示,指出組態值的來源的應用程式的輸出中。The suffix provides a visual cue in the app's output indicating the source of the configuration values.

在生產環境使用 Azure Key Vault 的祕密儲存體Secret storage in the Production environment with Azure Key Vault

所提供的指示快速入門:設定並從使用 Azure CLI 的 Azure 金鑰保存庫擷取祕密主題會彙總以供建立 Azure Key Vault 及儲存範例應用程式所使用的密碼。The instructions provided by the Quickstart: Set and retrieve a secret from Azure Key Vault using Azure CLI topic are summarized here for creating an Azure Key Vault and storing secrets used by the sample app. 請參閱本主題以取得詳細資料。Refer to the topic for further details.

  1. 開啟 Azure Cloud shell 中使用中的下列方法的任一Azure 入口網站:Open Azure Cloud shell using any one of the following methods in the Azure portal:

    • 選取 試試的程式碼區塊右上角。Select Try It in the upper-right corner of a code block. 使用搜尋字串"Azure CLI 」,在文字方塊中。Use the search string "Azure CLI" in the text box.
    • 在您的瀏覽器中開啟 Cloud Shell啟動 Cloud Shell 按鈕。Open Cloud Shell in your browser with the Launch Cloud Shell button.
    • 選取 Cloud Shell在 Azure 入口網站右上角的功能表上的按鈕。Select the Cloud Shell button on the menu in the upper-right corner of the Azure portal.

    如需詳細資訊,請參閱 < Azure 命令列介面 (CLI)Azure Cloud Shell 概觀For more information, see Azure Command-Line Interface (CLI) and Overview of Azure Cloud Shell.

  2. 如果您不已通過驗證,登入的az login命令。If you aren't already authenticated, sign in with the az login command.

  3. 建立資源群組,使用下列命令,其中{RESOURCE GROUP NAME}是新的資源群組的資源群組名稱和{LOCATION}是 Azure 區域 (資料中心):Create a resource group with the following command, where {RESOURCE GROUP NAME} is the resource group name for the new resource group and {LOCATION} is the Azure region (datacenter):

    az group create --name "{RESOURCE GROUP NAME}" --location {LOCATION}
    
  4. 在資源群組中,使用下列命令,建立金鑰保存庫所在{KEY VAULT NAME}是新的金鑰保存庫的名稱和{LOCATION}是 Azure 區域 (資料中心):Create a key vault in the resource group with the following command, where {KEY VAULT NAME} is the name for the new key vault and {LOCATION} is the Azure region (datacenter):

    az keyvault create --name "{KEY VAULT NAME}" --resource-group "{RESOURCE GROUP NAME}" --location {LOCATION}
    
  5. 建立金鑰保存庫中的密碼,做為名稱 / 值組。Create secrets in the key vault as name-value pairs.

    Azure Key Vault 祕密名稱必須是限制為英數字元及虛線。Azure Key Vault secret names are limited to alphanumeric characters and dashes. 階層式的值 (組態區段) 使用--(兩個連字號) 做為分隔符號。Hierarchical values (configuration sections) use -- (two dashes) as a separator. 通常用來分隔的區段中的子機碼的冒號ASP.NET Core 組態,不允許在金鑰保存庫祕密名稱。Colons, which are normally used to delimit a section from a subkey in ASP.NET Core configuration, aren't allowed in key vault secret names. 因此,兩個連字號是用,而且密碼會載入應用程式的設定時,已還原為冒號。Therefore, two dashes are used and swapped for a colon when the secrets are loaded into the app's configuration.

    下列的機密資料是範例應用程式搭配使用。The following secrets are for use with the sample app. 值包括_prod後置詞來區別從_dev後置詞從使用者的機密資訊的開發環境中載入的值。The values include a _prod suffix to distinguish them from the _dev suffix values loaded in the Development environment from User Secrets. 取代{KEY VAULT NAME}與您在先前步驟中建立的金鑰保存庫名稱:Replace {KEY VAULT NAME} with the name of the key vault that you created in the prior step:

    az keyvault secret set --vault-name "{KEY VAULT NAME}" --name "SecretName" --value "secret_value_1_prod"
    az keyvault secret set --vault-name "{KEY VAULT NAME}" --name "Section--SecretName" --value "secret_value_2_prod"
    

使用非 Azure 代管應用程式的應用程式識別碼和 X.509 憑證Use Application ID and X.509 certificate for non-Azure-hosted apps

設定 Azure AD、 Azure 金鑰保存庫和應用程式使用 Azure Active Directory 應用程式識別碼和 X.509 憑證來向 key vault當應用程式裝載在 Azure 之外Configure Azure AD, Azure Key Vault, and the app to use an Azure Active Directory Application ID and X.509 certificate to authenticate to a key vault when the app is hosted outside of Azure. 如需詳細資訊,請參閱 < 關於金鑰、 祕密和憑證For more information, see About keys, secrets, and certificates.

注意

雖然在 Azure 中託管的應用程式支援使用應用程式識別碼和 X.509 憑證,但我們建議您使用管理 Azure 資源的身分識別裝載在 Azure 中的應用程式時。Although using an Application ID and X.509 certificate is supported for apps hosted in Azure, we recommend using Managed identities for Azure resources when hosting an app in Azure. 受管理的身分識別不需要將憑證儲存在應用程式或開發環境。Managed identities don't require storing a certificate in the app or in the development environment.

範例應用程式會使用的應用程式識別碼和 X.509 憑證的時機#define陳述式,在頂端Program.cs檔案設定為CertificateThe sample app uses an Application ID and X.509 certificate when the #define statement at the top of the Program.cs file is set to Certificate.

  1. 建立 PKCS #12 封存 (.pfx) 憑證。Create a PKCS#12 archive (.pfx) certificate. 建立憑證的選項包括在 Windows 上的 MakeCertOpenSSLOptions for creating certificates include MakeCert on Windows and OpenSSL.
  2. 將憑證安裝到目前使用者的個人憑證存放區。Install the certificate into the current user's personal certificate store. 將金鑰標示為可匯出是選擇性的。Marking the key as exportable is optional. 請注意憑證的指紋,這將會稍後在此程序。Note the certificate's thumbprint, which is used later in this process.
  3. 匯出 PKCS #12 封存 (.pfx) 做為 DER 編碼的憑證的憑證 (.cer)。Export the PKCS#12 archive (.pfx) certificate as a DER-encoded certificate (.cer).
  4. 使用 Azure AD 註冊應用程式 (應用程式註冊)。Register the app with Azure AD (App registrations).
  5. 上傳 DER 編碼的憑證 (.cer) 至 Azure AD:Upload the DER-encoded certificate (.cer) to Azure AD:
    1. 在 Azure AD 中選取的應用程式。Select the app in Azure AD.
    2. 瀏覽至憑證與祕密Navigate to Certificates & secrets.
    3. 選取 上傳憑證來上傳包含公開金鑰的憑證。Select Upload certificate to upload the certificate, which contains the public key. A .cer.pem,或 .crt是可接受的憑證。A .cer, .pem, or .crt certificate is acceptable.
  6. 在應用程式中儲存的金鑰保存庫名稱、 應用程式識別碼和憑證指紋appsettings.json檔案。Store the key vault name, Application ID, and certificate thumbprint in the app's appsettings.json file.
  7. 瀏覽至金鑰保存庫在 Azure 入口網站中。Navigate to Key vaults in the Azure portal.
  8. 選取您在建立金鑰保存庫生產環境使用 Azure Key Vault 中密碼的儲存體一節。Select the key vault that you created in the Secret storage in the Production environment with Azure Key Vault section.
  9. 選取 存取原則Select Access policies.
  10. 選取 新增Select Add new.
  11. 選取 選取主體依名稱選取的已註冊的應用程式。Select Select principal and select the registered app by name. 選取 [選取] 按鈕。Select the Select button.
  12. 開啟祕密權限,並提供應用程式與取得清單權限。Open Secret permissions and provide the app with Get and List permissions.
  13. 選取 [確定]。Select OK.
  14. 選取 [儲存]。Select Save.
  15. 部署應用程式。Deploy the app.

Certificate範例應用程式取得其組態值從IConfigurationRoot具有相同名稱與祕密名稱:The Certificate sample app obtains its configuration values from IConfigurationRoot with the same name as the secret name:

  • 非階層式的值:值SecretName取得config["SecretName"]Non-hierarchical values: The value for SecretName is obtained with config["SecretName"].
  • (區段) 的階層式值:使用:(冒號) 標記法或GetSection擴充方法。Hierarchical values (sections): Use : (colon) notation or the GetSection extension method. 您可以使用任一種方法來取得組態值:Use either of these approaches to obtain the configuration value:
    • config["Section:SecretName"]
    • config.GetSection("Section")["SecretName"]

X.509 憑證是由 OS 管理。The X.509 certificate is managed by the OS. 應用程式呼叫AddAzureKeyVault所提供的值appsettings.json檔案:The app calls AddAzureKeyVault with values supplied by the appsettings.json file:

// using System.Linq;
// using System.Security.Cryptography.X509Certificates;
// using Microsoft.Extensions.Configuration;
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((context, config) =>
        {
            if (context.HostingEnvironment.IsProduction())
            {
                var builtConfig = config.Build();

                using (var store = new X509Store(StoreName.My,
                    StoreLocation.CurrentUser))
                {
                    store.Open(OpenFlags.ReadOnly);
                    var certs = store.Certificates
                        .Find(X509FindType.FindByThumbprint,
                            builtConfig["AzureADCertThumbprint"], false);

                    config.AddAzureKeyVault(
                        $"https://{builtConfig["KeyVaultName"]}.vault.azure.net/",
                        builtConfig["AzureADApplicationId"],
                        certs.OfType<X509Certificate2>().Single());

                    store.Close();
                }
            }
        })
        .UseStartup<Startup>();

範例值:Example values:

  • 金鑰保存庫名稱: contosovaultKey vault name: contosovault
  • 應用程式識別碼: 627e911e-43cc-61d4-992e-12db9c81b413Application ID: 627e911e-43cc-61d4-992e-12db9c81b413
  • 憑證指紋: fe14593dd66b2406c5269d742d04b6e1ab03adb1Certificate thumbprint: fe14593dd66b2406c5269d742d04b6e1ab03adb1

appsettings.jsonappsettings.json:

{
  "KeyVaultName": "Key Vault Name",
  "AzureADApplicationId": "Azure AD Application ID",
  "AzureADCertThumbprint": "Azure AD Certificate Thumbprint"
}

當您執行應用程式時,網頁就會顯示載入的祕密值。When you run the app, a webpage shows the loaded secret values. 使用,在開發環境中,載入祕密值_dev後置詞。In the Development environment, secret values load with the _dev suffix. 在生產環境中,值則是使用載入_prod後置詞。In the Production environment, the values load with the _prod suffix.

適用於 Azure 資源的使用受管理身分識別Use Managed identities for Azure resources

應用程式部署至 Azure可以充分善用管理適用於 Azure 資源的身分識別,可讓應用程式,以向 Azure Key Vault 使用不含認證的 Azure AD 驗證 (應用程式識別碼和Password/Client 密碼) 儲存在應用程式。An app deployed to Azure can take advantage of Managed identities for Azure resources, which allows the app to authenticate with Azure Key Vault using Azure AD authentication without credentials (Application ID and Password/Client Secret) stored in the app.

範例應用程式會使用適用於 Azure 資源的受管理身分識別時#define陳述式,在頂端Program.cs檔案設定為ManagedThe sample app uses Managed identities for Azure resources when the #define statement at the top of the Program.cs file is set to Managed.

輸入應用程式的保存庫名稱appsettings.json檔案。Enter the vault name into the app's appsettings.json file. 範例應用程式不需要應用程式識別碼和密碼 (用戶端秘密),當設定為Managed版本,因此您可以忽略這些組態項目。The sample app doesn't require an Application ID and Password (Client Secret) when set to the Managed version, so you can ignore those configuration entries. 應用程式部署至 Azure,以及 Azure 驗證應用程式存取只使用 保存庫名稱儲存在 Azure Key Vault appsettings.json檔案。The app is deployed to Azure, and Azure authenticates the app to access Azure Key Vault only using the vault name stored in the appsettings.json file.

將範例應用程式部署至 Azure App Service。Deploy the sample app to Azure App Service.

應用程式部署至 Azure App Service 與 Azure AD 建立服務時,會自動註冊。An app deployed to Azure App Service is automatically registered with Azure AD when the service is created. 從下列命令中使用的部署中取得的物件識別碼。Obtain the Object ID from the deployment for use in the following command. 物件識別碼時,會顯示在 Azure 入口網站上,在識別App Service 的面板。The Object ID is shown in the Azure portal on the Identity panel of the App Service.

使用 Azure CLI 和應用程式的物件識別碼,提供應用程式與listget存取金鑰保存庫的權限:Using Azure CLI and the app's Object ID, provide the app with list and get permissions to access the key vault:

az keyvault set-policy --name '{KEY VAULT NAME}' --object-id {OBJECT ID} --secret-permissions get list

重新啟動應用程式使用 Azure CLI、 PowerShell 或 Azure 入口網站。Restart the app using Azure CLI, PowerShell, or the Azure portal.

範例應用程式:The sample app:

  • 建立的執行個體AzureServiceTokenProvider類別,而不需要的連接字串。Creates an instance of the AzureServiceTokenProvider class without a connection string. 當未提供的連接字串時,提供者會嘗試從適用於 Azure 資源的受管理身分識別取得存取權杖。When a connection string isn't provided, the provider attempts to obtain an access token from Managed identities for Azure resources.
  • KeyVaultClient會透過AzureServiceTokenProvider執行個體權杖回呼。A new KeyVaultClient is created with the AzureServiceTokenProvider instance token callback.
  • KeyVaultClient的預設實作會使用執行個體IKeyVaultSecretManager載入所有祕密的值,會取代雙連字號 (--) 加上冒號 (:) 中索引鍵名稱。The KeyVaultClient instance is used with a default implementation of IKeyVaultSecretManager that loads all secret values and replaces double-dashes (--) with colons (:) in key names.
// using Microsoft.Azure.KeyVault;
// using Microsoft.Azure.Services.AppAuthentication;
// using Microsoft.Extensions.Configuration.AzureKeyVault;

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((context, config) =>
        {
            if (context.HostingEnvironment.IsProduction())
            {
                var builtConfig = config.Build();

                    var azureServiceTokenProvider = new AzureServiceTokenProvider();
                    var keyVaultClient = new KeyVaultClient(
                        new KeyVaultClient.AuthenticationCallback(
                            azureServiceTokenProvider.KeyVaultTokenCallback));

                    config.AddAzureKeyVault(
                        $"https://{builtConfig["KeyVaultName"]}.vault.azure.net/",
                        keyVaultClient,
                        new DefaultKeyVaultSecretManager());
            }
        })
        .UseStartup<Startup>();

當您執行應用程式時,網頁就會顯示載入的祕密值。When you run the app, a webpage shows the loaded secret values. 在開發環境中,有祕密值_dev後置詞,因為它們由使用者祕密。In the Development environment, secret values have the _dev suffix because they're provided by User Secrets. 在生產環境中,值則是使用載入_prod後置詞,因為它們由 Azure 金鑰保存庫。In the Production environment, the values load with the _prod suffix because they're provided by Azure Key Vault.

如果您收到Access denied錯誤,確認已向 Azure AD 註冊應用程式,且提供存取金鑰保存庫。If you receive an Access denied error, confirm that the app is registered with Azure AD and provided access to the key vault. 請確認您已重新開啟的服務在 Azure 中。Confirm that you've restarted the service in Azure.

使用索引鍵名稱前置詞Use a key name prefix

AddAzureKeyVault 提供的多載,接受的實作IKeyVaultSecretManager,這可讓您控制如何金鑰保存庫祕密會轉換成設定的索引鍵。AddAzureKeyVault provides an overload that accepts an implementation of IKeyVaultSecretManager, which allows you to control how key vault secrets are converted into configuration keys. 比方說,您可以實作的介面,將根據您在應用程式啟動時所提供的前置詞值的祕密值。For example, you can implement the interface to load secret values based on a prefix value you provide at app startup. 這可讓您,比方說,若要載入的應用程式的版本為基礎的祕密。This allows you, for example, to load secrets based on the version of the app.

警告

若要將多個應用程式的祕密放入相同的金鑰保存庫,或將環境的密碼,請勿使用前置詞上的金鑰保存庫祕密 (例如開發生產祕密) 置於同一個保存庫。Don't use prefixes on key vault secrets to place secrets for multiple apps into the same key vault or to place environmental secrets (for example, development versus production secrets) into the same vault. 我們建議,不同的應用程式和開發/生產環境使用不同的金鑰保存庫來隔離應用程式環境,以最高層級的安全性。We recommend that different apps and development/production environments use separate key vaults to isolate app environments for the highest level of security.

在下列範例中,祕密建立金鑰保存庫 」 (並使用 Secret Manager 工具開發環境) 的5000-AppSecret(期間不允許在金鑰保存庫祕密名稱)。In the following example, a secret is established in the key vault (and using the Secret Manager tool for the Development environment) for 5000-AppSecret (periods aren't allowed in key vault secret names). 此祕密表示 version=5.0.0.0 新版應用程式的應用程式祕密。This secret represents an app secret for version 5.0.0.0 of the app. 應用程式,5.1.0.0,另一個版本的祕密加入至金鑰保存庫 (並使用 Secret Manager 工具) 的5100-AppSecretFor another version of the app, 5.1.0.0, a secret is added to the key vault (and using the Secret Manager tool) for 5100-AppSecret. 每個應用程式版本載入其組態設為其建立版本的祕密值AppSecret、 清除關閉版本載入祕密。Each app version loads its versioned secret value into its configuration as AppSecret, stripping off the version as it loads the secret.

AddAzureKeyVault 自訂呼叫IKeyVaultSecretManager:AddAzureKeyVault is called with a custom IKeyVaultSecretManager:

// using System.Reflection;
// using Microsoft.Azure.KeyVault;
// using Microsoft.Azure.Services.AppAuthentication;
// using Microsoft.Extensions.Configuration;
// using Microsoft.Extensions.Configuration.AzureKeyVault;

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((context, config) =>
        {
            if (context.HostingEnvironment.IsProduction())
            {
                // The appVersion obtains the app version (5.0.0.0), which 
                // is set in the project file and obtained from the entry 
                // assembly. The versionPrefix holds the version without 
                // dot notation for the PrefixKeyVaultSecretManager.
                var appVersion = Assembly.GetEntryAssembly().GetName().Version.ToString();
                var versionPrefix = appVersion.Replace(".", string.Empty);

                var builtConfig = config.Build();

                using (var store = new X509Store(StoreName.My,
                    StoreLocation.CurrentUser))
                {
                    store.Open(OpenFlags.ReadOnly);
                    var certs = store.Certificates
                        .Find(X509FindType.FindByThumbprint,
                            builtConfig["AzureADCertThumbprint"], false);

                    config.AddAzureKeyVault(
                        $"https://{builtConfig["KeyVaultName"]}.vault.azure.net/",
                        builtConfig["AzureADApplicationId"],
                        certs.OfType<X509Certificate2>().Single(),
                        new PrefixKeyVaultSecretManager(versionPrefix));

                    store.Close();
                }
            }
        })
        .UseStartup<Startup>();

IKeyVaultSecretManager實作回應組態中載入適當的祕密的祕密版本前置詞:The IKeyVaultSecretManager implementation reacts to the version prefixes of secrets to load the proper secret into configuration:

public class PrefixKeyVaultSecretManager : IKeyVaultSecretManager
{
    private readonly string _prefix;

    public PrefixKeyVaultSecretManager(string prefix)
    {
        _prefix = $"{prefix}-";
    }

    public bool Load(SecretItem secret)
    {
        // Load a vault secret when its secret name starts with the 
        // prefix. Other secrets won't be loaded.
        return secret.Identifier.Name.StartsWith(_prefix);
    }

    public string GetKey(SecretBundle secret)
    {
        // Remove the prefix from the secret name and replace two 
        // dashes in any name with the KeyDelimiter, which is the 
        // delimiter used in configuration (usually a colon). Azure 
        // Key Vault doesn't allow a colon in secret names.
        return secret.SecretIdentifier.Name
            .Substring(_prefix.Length)
            .Replace("--", ConfigurationPath.KeyDelimiter);
    }
}

Load逐一查看,找出有版本前置詞的保存庫祕密提供者演算法所呼叫方法。The Load method is called by a provider algorithm that iterates through the vault secrets to find the ones that have the version prefix. 當版本的前置詞上有Load,此演算法會使用GetKey方法傳回的密碼名稱的組態名稱。When a version prefix is found with Load, the algorithm uses the GetKey method to return the configuration name of the secret name. 它會除去版本前置詞,從 祕密的名稱,並傳回載入的祕密名稱的其餘部分,將應用程式設定成名稱 / 值組。It strips off the version prefix from the secret's name and returns the rest of the secret name for loading into the app's configuration name-value pairs.

當這個方法的實作方式:When this approach is implemented:

  1. 應用程式的專案檔中指定的應用程式的版本。The app's version specified in the app's project file. 在下列範例中,應用程式的版本設為5.0.0.0:In the following example, the app's version is set to 5.0.0.0:

    <PropertyGroup>
      <Version>5.0.0.0</Version>
    </PropertyGroup>
    
  2. 確認<UserSecretsId>屬性會出現在應用程式的專案檔案,其中{GUID}是使用者所提供的 GUID:Confirm that a <UserSecretsId> property is present in the app's project file, where {GUID} is a user-supplied GUID:

    <PropertyGroup>
      <UserSecretsId>{GUID}</UserSecretsId>
    </PropertyGroup>
    

    儲存在本機使用下列的祕密Secret Manager 工具:Save the following secrets locally with the Secret Manager tool:

    dotnet user-secrets set "5000-AppSecret" "5.0.0.0_secret_value_dev"
    dotnet user-secrets set "5100-AppSecret" "5.1.0.0_secret_value_dev"
    
  3. 密碼會儲存在 Azure Key Vault 中使用下列 Azure CLI 命令:Secrets are saved in Azure Key Vault using the following Azure CLI commands:

    az keyvault secret set --vault-name "{KEY VAULT NAME}" --name "5000-AppSecret" --value "5.0.0.0_secret_value_prod"
    az keyvault secret set --vault-name "{KEY VAULT NAME}" --name "5100-AppSecret" --value "5.1.0.0_secret_value_prod"
    
  4. 執行應用程式時,會載入的金鑰保存庫祕密。When the app is run, the key vault secrets are loaded. 字串密碼5000-AppSecret會對應到應用程式的專案檔中指定的應用程式的版本 (5.0.0.0)。The string secret for 5000-AppSecret is matched to the app's version specified in the app's project file (5.0.0.0).

  5. 版本, 5000 (與 dash),移除的索引鍵名稱。The version, 5000 (with the dash), is stripped from the key name. 在整個應用程式,讀取具有索引鍵的組態AppSecret載入祕密的值。Throughout the app, reading configuration with the key AppSecret loads the secret value.

  6. 如果應用程式的版本會變更專案檔案中5.1.0.0再次執行應用程式,則傳回的祕密值是5.1.0.0_secret_value_dev在開發環境和5.1.0.0_secret_value_prod在生產環境中。If the app's version is changed in the project file to 5.1.0.0 and the app is run again, the secret value returned is 5.1.0.0_secret_value_dev in the Development environment and 5.1.0.0_secret_value_prod in Production.

注意

您也可以提供您自己KeyVaultClient實作AddAzureKeyVaultYou can also provide your own KeyVaultClient implementation to AddAzureKeyVault. 自訂用戶端會允許跨應用程式共用用戶端的單一執行個體。A custom client permits sharing a single instance of the client across the app.

將陣列繫結到類別Bind an array to a class

提供者可以讀入繫結到 POCO 陣列的陣列中的組態值。The provider is capable of reading configuration values into an array for binding to a POCO array.

從允許包含冒號的索引鍵的組態來源讀取時 (:) 的數值索引鍵的區段分隔符號用來區別構成陣列的索引鍵 (:0::1:,...When reading from a configuration source that allows keys to contain colon (:) separators, a numeric key segment is used to distinguish the keys that make up an array (:0:, :1:, … :{n}:)。:{n}:). 如需詳細資訊,請參閱組態:將陣列繫結至類別For more information, see Configuration: Bind an array to a class.

Azure Key Vault 金鑰無法使用冒號做為分隔符號。Azure Key Vault keys can't use a colon as a separator. 本主題中所述的方法會使用雙連字號 (--) 當作分隔符號 (區段) 的階層式值。The approach described in this topic uses double dashes (--) as a separator for hierarchical values (sections). 陣列索引鍵時,會儲存在 Azure 金鑰保存庫上,使用雙連字號和數值的重要片段 (--0----1--, … --{n}--)。Array keys are stored in Azure Key Vault with double dashes and numeric key segments (--0--, --1--, … --{n}--).

檢查下列Serilog記錄的 JSON 檔案所提供的提供者組態。Examine the following Serilog logging provider configuration provided by a JSON file. 有兩個物件中定義的常值WriteTo陣列,其中會反映兩個 Serilog接收,可描述記錄輸出的目的地:There are two object literals defined in the WriteTo array that reflect two Serilog sinks, which describe destinations for logging output:

"Serilog": {
  "WriteTo": [
    {
      "Name": "AzureTableStorage",
      "Args": {
        "storageTableName": "logs",
        "connectionString": "DefaultEnd...ountKey=Eby8...GMGw=="
      }
    },
    {
      "Name": "AzureDocumentDB",
      "Args": {
        "endpointUrl": "https://contoso.documents.azure.com:443",
        "authorizationKey": "Eby8...GMGw=="
      }
    }
  ]
}

在上述的 JSON 檔案中所示的組態會儲存在 Azure 金鑰保存庫使用雙破折號 (--) 標記法和數值的區段:The configuration shown in the preceding JSON file is stored in Azure Key Vault using double dash (--) notation and numeric segments:

KeyKey Value
Serilog--WriteTo--0--Name AzureTableStorage
Serilog--WriteTo--0--Args--storageTableName logs
Serilog--WriteTo--0--Args--connectionString DefaultEnd...ountKey=Eby8...GMGw==
Serilog--WriteTo--1--Name AzureDocumentDB
Serilog--WriteTo--1--Args--endpointUrl https://contoso.documents.azure.com:443
Serilog--WriteTo--1--Args--authorizationKey Eby8...GMGw==

重新載入祕密Reload secrets

密碼會快取直到IConfigurationRoot.Reload()呼叫。Secrets are cached until IConfigurationRoot.Reload() is called. 過期,停用,以及更新金鑰保存庫中的祕密未遵守應用程式,直到Reload執行。Expired, disabled, and updated secrets in the key vault are not respected by the app until Reload is executed.

Configuration.Reload();

已停用和到期的祕密Disabled and expired secrets

已停用及過期的密碼會擲回KeyVaultClientExceptionDisabled and expired secrets throw a KeyVaultClientException. 若要防止您的應用程式擲回,取代您的應用程式或更新已停用/過期的祕密。To prevent your app from throwing, replace your app or update the disabled/expired secret.

疑難排解Troubleshoot

當應用程式無法載入組態使用的提供者時,錯誤訊息會寫入ASP.NET Core 記錄基礎結構When the app fails to load configuration using the provider, an error message is written to the ASP.NET Core Logging infrastructure. 在下列情況會造成無法載入組態:The following conditions will prevent configuration from loading:

  • 應用程式或憑證未正確設定 Azure Active Directory 中。The app or certificate isn't configured correctly in Azure Active Directory.
  • 金鑰保存庫不存在於 Azure 金鑰保存庫。The key vault doesn't exist in Azure Key Vault.
  • 應用程式未獲授權存取金鑰保存庫。The app isn't authorized to access the key vault.
  • 存取原則不包含GetList權限。The access policy doesn't include Get and List permissions.
  • 在金鑰保存庫中,設定資料 (名稱 / 值組) 錯誤命名為,遺漏,停用,或已過期。In the key vault, the configuration data (name-value pair) is incorrectly named, missing, disabled, or expired.
  • 應用程式有錯誤的金鑰保存庫名稱 (KeyVaultName),Azure AD 應用程式識別碼 (AzureADApplicationId),或 Azure AD 憑證指紋 (AzureADCertThumbprint)。The app has the wrong key vault name (KeyVaultName), Azure AD Application Id (AzureADApplicationId), or Azure AD certificate thumbprint (AzureADCertThumbprint).
  • 不正確的值,您想要載入的應用程式中設定金鑰 (名稱)。The configuration key (name) is incorrect in the app for the value you're trying to load.

其他資源Additional resources