教程:使用托管标识将 Key Vault 连接到 .NET 中的 Azure Web 应用

Azure Key Vault 提供了一种更安全的存储凭据和其他机密的方法。 但代码需要对 Key Vault 进行身份验证才能检索它们。 Azure 资源的托管标识可帮助你解决此问题,其中介绍了如何在 Microsoft Entra ID 中为 Azure 服务提供自动托管的标识。 此标识可用于通过支持 Microsoft Entra 身份验证的任何服务(包括 Key Vault)的身份验证,这样就无需在代码中插入任何凭据了。

在本教程中,你将创建 Azure Web 应用程序并将其部署到 Azure 应用服务。 你将使用托管标识对 Azure Web 应用进行身份验证,该应用具有使用适用于 .NET 的 Azure 密钥保管库机密客户端库Azure CLI 的 Azure 密钥保管库。 当你使用所选的开发语言 Azure PowerShell 和/或 Azure 门户时,同样的基本原则也适用。

有关本教程中介绍的 Azure 应用服务 Web 应用程序和部署的详细信息,请参阅:

先决条件

要完成本教程,需要:

如果已在 Azure 应用服务中部署了 Web 应用程序,则可以跳到配置对密钥保管库的 Web 应用访问修改 Web 应用程序代码部分。

创建 .NET Core 应用

在此步骤中,你将设置本地 .NET Core 项目。

在计算机的终端窗口中,创建一个名为 akvwebapp 的目录,并将其设为当前目录:

mkdir akvwebapp
cd akvwebapp

使用 dotnet new web 命令创建 .NET Core 应用:

dotnet new web

在本地运行应用程序,以便了解将它部署到 Azure 时的情形:

dotnet run

在 Web 浏览器中,转到 http://localhost:5000 处的应用。

页面中会显示该示例应用发出的“Hello World!”消息。

有关为 Azure 创建 Web 应用程序的详细信息,请参阅在 Azure 应用服务中创建 ASP.NET Core Web 应用

将应用部署到 Azure

在此步骤中,你将使用本地 Git 将 .NET Core 应用程序部署到 Azure 应用服务。 有关如何创建和部署应用程序的详细信息,请参阅在 Azure 中创建 ASP.NET Core Web 应用

配置本地 Git 部署

在终端窗口中,选择 Ctrl+C 关闭 Web 服务器。 为 .NET Core 项目初始化 Git 存储库:

git init --initial-branch=main
git add .
git commit -m "first commit"

可以通过 FTP 和本地 Git 使用 deployment user 来部署 Azure Web 应用。 配置部署用户之后,可对所有 Azure 部署使用此用户。 帐户级部署用户名和密码不同于 Azure 订阅凭据。

若要配置部署用户,请运行 az webapp deployment user set 命令。 选择符合以下准则的用户名和密码:

  • 用户名在 Azure 中必须唯一。 对于本地 Git 推送,它不能包含 at 符号 (@)。
  • 密码必须至少为 8 个字符,且包含字母、数字和符号这三种元素中的两种。
az webapp deployment user set --user-name "<username>" --password "<password>"

JSON 输出会将该密码显示为 null。 如果收到 'Conflict'. Details: 409 错误,请更改用户名。 如果收到 'Bad Request'. Details: 400 错误,请使用更强的密码。

记录用户名和密码,以便可以使用它来部署 Web 应用。

创建资源组

资源组是一个逻辑容器,可以在其中部署和管理 Azure 资源。 使用 az group Create 命令创建一个资源组用于包含密钥保管库和 Web 应用:

az group create --name "myResourceGroup" -l "ChinaEast"

创建应用服务计划

使用 Azure CLI az appservice plan create 命令创建应用程序服务计划。 以下示例在 myAppServicePlan 定价层中创建名为 FREE 的应用服务计划:

az appservice plan create --name myAppServicePlan --resource-group myResourceGroup --sku FREE

创建应用服务计划时,Azure CLI 将显示与在此处看到的类似信息:

{ 
  "adminSiteName": null,
  "appServicePlanName": "myAppServicePlan",
  "geoRegion": "China North",
  "hostingEnvironmentProfile": null,
  "id": "/subscriptions/0000-0000/resourceGroups/myResourceGroup/providers/Microsoft.Web/serverfarms/myAppServicePlan",
  "kind": "app",
  "location": "China North",
  "maximumNumberOfWorkers": 1,
  "name": "myAppServicePlan",
  < JSON data removed for brevity. >
  "targetWorkerSizeId": 0,
  "type": "Microsoft.Web/serverfarms",
  "workerTierName": null
} 

有关详细信息,请参阅在 Azure 中管理应用服务计划

创建 Web 应用

应用程序服务计划中创建 Azure Web 应用myAppServicePlan

重要

与密钥保管库一样,Azure Web 应用必须具有独一无二的名称。 在以下示例中,将 <your-webapp-name> 替换为 Web 应用的名称。

az webapp create --resource-group "myResourceGroup" --plan "myAppServicePlan" --name "<your-webapp-name>" --deployment-local-git

创建 Web 应用时,Azure CLI 将显示与你在此处看到的类似的输出:

Local git is configured with url of 'https://<username>@<your-webapp-name>.scm.chinacloudsites.cn/<ayour-webapp-name>.git'
{
  "availabilityState": "Normal",
  "clientAffinityEnabled": true,
  "clientCertEnabled": false,
  "clientCertExclusionPaths": null,
  "cloningInfo": null,
  "containerSize": 0,
  "dailyMemoryTimeQuota": 0,
  "defaultHostName": "<your-webapp-name>.chinacloudsites.cn",
  "deploymentLocalGitUrl": "https://<username>@<your-webapp-name>.scm.chinacloudsites.cn/<your-webapp-name>.git",
  "enabled": true,
  < JSON data removed for brevity. >
}

Git 远程的 URL 将显示在 deploymentLocalGitUrl 属性中,其格式为 https://<username>@<your-webapp-name>.scm.chinacloudsites.cn/<your-webapp-name>.git。 保存此 URL。 稍后需要用到此信息。

现在,将 Web 应用配置为从 main 分支部署:

 az webapp config appsettings set -g MyResourceGroup --name "<your-webapp-name>" --settings deployment_branch=main

使用以下命令转到新应用。 将 <your-webapp-name> 替换为你的应用名称。

https://<your-webapp-name>.chinacloudsites.cn

你将看到新 Azure Web 应用的默认网页。

部署本地应用

回到本地终端窗口,将 Azure 远程功能添加到本地 Git 存储库。 在以下命令中,将 <deploymentLocalGitUrl-from-create-step> 替换为保存在创建 Web 应用部分中的 Git 远程的 URL。

git remote add azure <deploymentLocalGitUrl-from-create-step>

使用以下命令推送到 Azure 远程以部署应用。 当 Git 凭据管理器提示你输入凭据时,请使用你在配置本地 Git 部署部分中创建的凭据。

git push azure main

该命令可能需要几分钟时间才能运行。 运行时,它会显示与此处所示类似的信息:

Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 285 bytes | 95.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0), pack-reused 0
remote: Deploy Async
remote: Updating branch 'main'.
remote: Updating submodules.
remote: Preparing deployment for commit id 'd6b54472f7'.
remote: Repository path is /home/site/repository
remote: Running oryx build...
remote: Build orchestrated by Azure Oryx, https://github.com/Microsoft/Oryx
remote: You can report issues at https://github.com/Microsoft/Oryx/issues
remote:
remote: Oryx Version      : 0.2.20200114.13, Commit: 204922f30f8e8d41f5241b8c218425ef89106d1d, ReleaseTagName: 20200114.13
remote: Build Operation ID: |imoMY2y77/s=.40ca2a87_
remote: Repository Commit : d6b54472f7e8e9fd885ffafaa64522e74cf370e1
.
.
.
remote: Deployment successful.
remote: Deployment Logs : 'https://<your-webapp-name>.scm.chinacloudsites.cn/newui/jsonviewer?view_url=/api/deployments/d6b54472f7e8e9fd885ffafaa64522e74cf370e1/log'
To https://<your-webapp-name>.scm.chinacloudsites.cn:443/<your-webapp-name>.git
   d87e6ca..d6b5447  main -> main

使用 Web 浏览器转到(或刷新)已部署的应用程序:

http://<your-webapp-name>.chinacloudsites.cn

你将看到之前在访问 http://localhost:5000 时显示的“Hello World!”消息。

有关使用 Git 部署 Web 应用程序的详细信息,请参阅从本地 Git 部署到 Azure 应用服务

配置 Web 应用以连接到 Key Vault

在本部分中,你将配置对 Key Vault 的 Web 访问,并更新应用程序代码以从 Key Vault 中检索机密。

创建托管标识并为其分配访问权限

在本教程中,我们将使用托管标识对 Key Vault 进行身份验证。 托管标识会自动管理应用程序凭据。

在 Azure CLI 中,若要为此应用程序创建标识,请运行 az webapp-identity assign 命令:

az webapp identity assign --name "<your-webapp-name>" --resource-group "myResourceGroup"

该命令将返回此 JSON 代码片段:

{
  "principalId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "tenantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
  "type": "SystemAssigned"
}

若要为 Web 应用授予在密钥保管库上执行 getlist 的权限,请将 principalId 传递到 Azure CLI az keyvault set-policy 命令 :

az keyvault set-policy --name "<your-keyvault-name>" --object-id "<principalId>" --secret-permissions get list

还可以使用 Azure 门户来分配访问策略。

修改应用以访问密钥保管库

在本教程中,你将使用 Azure Key Vault 机密客户端库进行演示。 你还可以使用 Azure Key Vault 证书客户端库Azure Key Vault 密钥客户端库

安装包

在终端窗口中,安装适用于 .NET 的 Azure Key Vault 机密客户端库和 Azure 标识客户端库包:

dotnet add package Azure.Identity
dotnet add package Azure.Security.KeyVault.Secrets

更新代码

对于 .NET 5.0 或更早版本,找到并打开 Startup.cs 文件,而对于 .NET 6.0,则在 akvwebapp 项目中找到并打开 Program.cs 文件。

将以下行添加到标头:

using Azure.Identity;
using Azure.Security.KeyVault.Secrets;
using Azure.Core;

app.UseEndpoints 调用(.NET 5.0 或更早版本)或 app.MapGet 调用 (.NET 6.0) 之前添加以下行,更新 URI 以反映密钥保管库的 vaultUri。 此代码使用 DefaultAzureCredential() 对密钥保管库进行身份验证,后者使用托管标识中的令牌进行身份验证。 有关向 Key Vault 进行身份验证的详细信息,请参阅开发人员指南。 该代码还会使用指数退避,以便在 Key Vault 受到限制的情况下进行重试。 有关 Key Vault 事务限制的详细信息,请参阅 Azure Key Vault 限制指南

SecretClientOptions options = new SecretClientOptions()
    {
        Retry =
        {
            Delay= TimeSpan.FromSeconds(2),
            MaxDelay = TimeSpan.FromSeconds(16),
            MaxRetries = 5,
            Mode = RetryMode.Exponential
         }
    };
var client = new SecretClient(new Uri("https://<your-unique-key-vault-name>.vault.azure.cn/"), new DefaultAzureCredential(),options);

KeyVaultSecret secret = client.GetSecret("<mySecret>");

string secretValue = secret.Value;
.NET 5.0 或更早版本

将行 await context.Response.WriteAsync("Hello World!"); 更新为如下行:

await context.Response.WriteAsync(secretValue);
.NET 6.0

将行 app.MapGet("/", () => "Hello World!"); 更新为如下行:

app.MapGet("/", () => secretValue);

在继续下一步之前,请务必保存所做的更改。

重新部署 Web 应用

现已更新了代码,可以使用以下 Git 命令将其重新部署到 Azure:

git add .
git commit -m "Updated web app to access my key vault"
git push azure main

转到已完成的 Web 应用

http://<your-webapp-name>.chinacloudsites.cn

在以前显示“Hello World!”的地方,现在应显示机密值。

后续步骤