你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

自动轮换使用一组身份验证凭据的资源的机密

向Azure服务进行身份验证的最佳方式是使用托管标识,但某些方案需要访问密钥、密码或其他机密。 定期轮换这些机密,以减少泄露凭据的影响。

本教程介绍如何为使用一组身份验证凭据的数据库和服务自动执行定期机密轮换。 有关不同资产类型中的自动轮换概述,请参阅了解 Azure 密钥保管库 中的自动轮换

具体而言,本教程使用由Azure 事件网格通知触发的函数轮换存储在Azure 密钥保管库中的SQL Server密码:

Tip

对于 Azure SQL 数据库 和 Azure SQL 托管实例,应优先使用 仅限 Microsoft Entra 的身份验证,而非 SQL 登录。 仅当工作负荷需要 SQL 身份验证时,才在本教程中使用密码轮换模式。

旋转解决方案示意图

  1. 在机密到期日期之前的三十天,密钥保管库将“即将过期”事件发布到事件网格。
  2. 事件网格会检查事件订阅,并使用 HTTP POST 调用已订阅该事件的函数应用终结点。
  3. 函数应用接收机密信息,生成新的随机密码,并在密钥保管库中使用新密码为机密创建新版本。
  4. 函数应用使用新密码更新SQL Server。

注释

步骤 3 和步骤 4 之间可能存在延迟。 在该窗口中,密钥保管库中的机密无法向SQL Server进行身份验证。 如果任何步骤失败,事件网格将重试两个小时。

先决条件

如果还没有密钥保管库和SQL Server实例,请使用以下部署链接:

Image 显示标记为“部署到Azure”的按钮

  1. “资源组”下,选择“ 新建”,并为组命名。 本教程使用 akvrotation
  2. SQL 管理员登录名下,输入 SQL 管理员登录名。
  3. 选择“查看 + 创建”
  4. 选择 创建

创建资源组

现在有一个密钥保管库和一个SQL Server实例。 在Azure CLI中验证此设置:

az resource list -o table -g akvrotation

结果类似于以下输出:

Name                     ResourceGroup         Location    Type                               Status
-----------------------  --------------------  ----------  ---------------------------------  --------
akvrotation-kv           akvrotation      eastus      Microsoft.KeyVault/vaults
akvrotation-sql          akvrotation      eastus      Microsoft.Sql/servers
akvrotation-sql/master   akvrotation      eastus      Microsoft.Sql/servers/databases
akvrotation-sql2         akvrotation      eastus      Microsoft.Sql/servers
akvrotation-sql2/master  akvrotation      eastus      Microsoft.Sql/servers/databases

创建和部署SQL Server密码轮换函数

重要

此模板要求 Key Vault、SQL Server 实例和函数应用位于同一资源组中。

接下来,创建具有系统分配的托管标识和其他必需组件的函数应用,并部署SQL Server密码轮换函数。

函数应用需要以下组件:

  • Azure 应用服务 的计划。
  • 包含具有 Event Grid 触发器和 HTTP 触发器的 SQL 密码轮换函数的函数应用。
  • 用于函数应用触发器管理的存储帐户。
  • 一个 Azure 角色分配,允许函数应用标识访问密钥保管库中的机密。
  • SecretNearExpiry 事件的事件网格事件订阅
  1. 选择Azure模板部署链接:

    Image 显示标记为“部署到Azure”的按钮

  2. 资源组 列表中,选择 akvrotation

  3. SQL Server名称中,输入要轮换其密码的SQL Server实例的名称。

  4. 密钥保管库名称中,输入密钥保管库名称。

  5. 函数应用名称中,输入函数应用名称。

  6. 机密名称中,输入存储密码的机密名称。

  7. 在“存储库 URL”中,输入函数代码的 GitHub 位置:https://github.com/Azure-Samples/KeyVault-Rotation-SQLPassword-Csharp.git

  8. 选择“查看 + 创建”

  9. 选择 创建

注释

此 ARM 模板使用应用服务源代码管理(Kudu)部署,以从 GitHub 拉取函数代码。 对于生产工作负载,我们建议使用基于包的部署,例如 func azure functionapp publish配合 WEBSITE_RUN_FROM_PACKAGE 的 zip 部署。

选择“审阅+创建”

完成上述步骤后,你有一个存储帐户、服务器场和一个函数应用。 在Azure CLI中验证此设置:

az resource list -o table -g akvrotation

结果类似于以下输出:

Name                     ResourceGroup         Location    Type                               Status
-----------------------  --------------------  ----------  ---------------------------------  --------
akvrotation-kv           akvrotation       eastus      Microsoft.KeyVault/vaults
akvrotation-sql          akvrotation       eastus      Microsoft.Sql/servers
akvrotation-sql/master   akvrotation       eastus      Microsoft.Sql/servers/databases
cfogyydrufs5wazfunctions akvrotation       eastus      Microsoft.Storage/storageAccounts
akvrotation-fnapp        akvrotation       eastus      Microsoft.Web/serverFarms
akvrotation-fnapp        akvrotation       eastus      Microsoft.Web/sites
akvrotation-fnapp        akvrotation       eastus      Microsoft.insights/components

有关创建函数应用和使用托管标识访问密钥保管库的详细信息,请参阅从 Azure 门户创建函数应用如何使用应用服务和Azure Functions的托管标识,以及通过 Azure RBAC 提供对密钥保管库的访问权限

注释

示例函数面向 Azure Functions 的 .NET 进程内模型。 对于新开发,请使用 .NET 隔离工作器模型,这是未来将持续受支持的模型。

旋转函数

在上一步中部署的函数使用事件来触发机密轮换。 它更新密钥保管库和 SQL 数据库。

函数触发器事件

此函数读取事件数据并运行旋转逻辑:

public static class SimpleRotationEventHandler
{
   [FunctionName("AKVSQLRotation")]
   public static void Run([EventGridTrigger]EventGridEvent eventGridEvent, ILogger log)
   {
      log.LogInformation("C# Event trigger function processed a request.");
      var secretName = eventGridEvent.Subject;
      var secretVersion = Regex.Match(eventGridEvent.Data.ToString(), "Version\":\"([a-z0-9]*)").Groups[1].ToString();
      var keyVaultName = Regex.Match(eventGridEvent.Topic, ".vaults.(.*)").Groups[1].ToString();
      log.LogInformation($"Key Vault Name: {keyVaultName}");
      log.LogInformation($"Secret Name: {secretName}");
      log.LogInformation($"Secret Version: {secretVersion}");

      SecretRotator.RotateSecret(log, secretName, keyVaultName);
   }
}

机密轮换逻辑

此轮换方法从机密中读取数据库信息,创建新版本的机密,并使用新机密更新数据库:

    public class SecretRotator
    {
		private const string CredentialIdTag = "CredentialId";
		private const string ProviderAddressTag = "ProviderAddress";
		private const string ValidityPeriodDaysTag = "ValidityPeriodDays";

		public static void RotateSecret(ILogger log, string secretName, string keyVaultName)
        {
            //Retrieve Current Secret
            var kvUri = "https://" + keyVaultName + ".vault.azure.net";
            var client = new SecretClient(new Uri(kvUri), new DefaultAzureCredential());
            KeyVaultSecret secret = client.GetSecret(secretName);
            log.LogInformation("Secret Info Retrieved");

            //Retrieve Secret Info
            var credentialId = secret.Properties.Tags.ContainsKey(CredentialIdTag) ? secret.Properties.Tags[CredentialIdTag] : "";
            var providerAddress = secret.Properties.Tags.ContainsKey(ProviderAddressTag) ? secret.Properties.Tags[ProviderAddressTag] : "";
            var validityPeriodDays = secret.Properties.Tags.ContainsKey(ValidityPeriodDaysTag) ? secret.Properties.Tags[ValidityPeriodDaysTag] : "";
            log.LogInformation($"Provider Address: {providerAddress}");
            log.LogInformation($"Credential Id: {credentialId}");

            //Check Service Provider connection
            CheckServiceConnection(secret);
            log.LogInformation("Service Connection Validated");
            
            //Create new password
            var randomPassword = CreateRandomPassword();
            log.LogInformation("New Password Generated");

            //Add secret version with new password to Key Vault
            CreateNewSecretVersion(client, secret, randomPassword);
            log.LogInformation("New Secret Version Generated");

            //Update Service Provider with new password
            UpdateServicePassword(secret, randomPassword);
            log.LogInformation("Password Changed");
            log.LogInformation($"Secret Rotated Successfully");
        }
}

可以在 GitHub 上找到完整的代码。

将机密添加到密钥保管库

为自己分配密钥保管库机密管理员角色,以便管理保管库中的机密:

az role assignment create --role "Key Vault Secrets Officer" --assignee <email-address-of-user> --scope /subscriptions/<subscription-id>/resourceGroups/<resource-group>/providers/Microsoft.KeyVault/vaults/akvrotation-kv

创建包含SQL Server资源 ID、SQL Server登录名和机密有效期(以天为单位)的标记的机密。 设置机密名称、SQL 数据库的初始密码(Simple123 在本示例中),并将过期日期设置为明天,以便立即触发轮换。

tomorrowDate=$(date -u -d "+1 day" +"%Y-%m-%dT%H:%M:%SZ")
az keyvault secret set --name sqlPassword --vault-name akvrotation-kv --value "Simple123" --tags "CredentialId=sqlAdmin" "ProviderAddress=<sql-database-resource-id>" "ValidityPeriodDays=90" --expires $tomorrowDate

将到期时间设置得较短,会在 15 分钟内发布一个 SecretNearExpiry 事件,从而触发该函数轮换机密。

测试和验证

若要验证机密是否已轮换,请转到 密钥保管库>Secrets

截图展示如何访问 密钥保管库 > Secrets。

打开 sqlPassword 机密并查看原始版本和旋转版本:

转到“机密”

创建 Web 应用

若要验证 SQL 凭据,请创建 Web 应用。 Web 应用从密钥保管库检索机密,从机密中提取 SQL 数据库信息和凭据,并测试与SQL Server的连接。

Web 应用需要以下组件:

  • 具有系统分配的托管标识的 Web 应用。
  • 一个角色分配,允许 Web 应用的托管标识读取密钥保管库中的机密。
  1. 选择Azure模板部署链接:

    Image 显示标记为“部署到Azure”的按钮

  2. 选择 akvrotation 资源组。

  3. SQL Server 名称字段中,输入其密码已轮换的 SQL Server 名称。

  4. 密钥保管库名称中,输入密钥保管库名称。

  5. 机密名称中,输入存储密码的机密名称。

  6. 在“存储库 URL”中,输入 Web 应用代码的 GitHub 位置:https://github.com/Azure-Samples/KeyVault-Rotation-SQLPassword-Csharp-WebApp.git

  7. 选择“查看 + 创建”

  8. 选择 创建

打开 Web 应用

转到已部署的应用程序 URL: https://akvrotation-app.azurewebsites.net/

当应用程序在浏览器中打开时,页面会显示 生成的机密值数据库连接true

使用 AI 自定义数据库的旋转函数

本教程演示SQL Server的机密轮换,但你可以针对其他数据库类型调整轮换函数。 GitHub Copilot 可以帮助你修改轮换函数的代码,使其适用于你的数据库或凭据类型。

I'm using the Azure Key Vault secret rotation tutorial for SQL Server. Help me modify the rotation function to work with PostgreSQL instead. The function should:
1. Generate a new secure password
2. Update the PostgreSQL database user password
3. Store the new password in Key Vault
Show me the changes needed to the C# function code, including the correct PostgreSQL connection library and password update command.

Copilot还有助于为其他凭据类型(如 API 密钥、连接字符串或服务帐户密码)调整此模式。

GitHub Copilot由 AI 提供支持,因此可能会带来惊喜和错误。 有关详细信息,请参阅 Copilot 常见问题解答

了解详细信息