你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
向 Azure 服务进行身份验证的最佳方式是使用 托管标识,但在某些情况下,这不是一个选项。 在这些情况下,使用访问密钥或机密。 应定期轮换访问密钥或机密。
本教程介绍如何为使用一组身份验证凭据的数据库和服务自动轮换机密。 有关不同资产类型中自动轮换的概念和优势的综合概述,请参阅 了解 Azure Key Vault 中的自动轮换。
具体而言,本教程使用 Azure 事件网格通知触发的函数轮换存储在 Azure Key Vault 中的 SQL Server 密码:
- 在机密过期之前的 30 天,Key Vault 会向事件网格发布“即将过期”事件。
- 事件网格会检查事件订阅,并使用 HTTP POST 调用已订阅该事件的函数应用终结点。
- 函数应用接收机密信息,生成新的随机密码,然后在 Key Vault 中使用新密码为机密创建新的版本。
- 函数应用使用新密码更新 SQL Server。
注释
步骤 3 和步骤 4 之间可能存在延迟。 在此期间,Key Vault 中的机密将无法向 SQL Server 进行身份验证。 如果任一步骤失败,事件网格会重试两个小时。
先决条件
- Azure 订阅 - 免费创建订阅。
- Azure Key Vault
- SQL Server
如果没有现有的 Key Vault 和 SQL Server,可以使用以下部署链接:
- 在“资源组”下,选择“新建”。 为组命名,我们将在本教程中使用 akvrotation 。
- 在 “SQL 管理员登录名”下,键入 SQL 管理员登录名。
- 选择“查看 + 创建”。
- 选择 创建
现在,你将拥有 Key Vault 和 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 和 Azure Function 位于同一资源组中。
接下来,创建具有系统托管标识的函数应用,以及其他必需的组件,并部署 SQL Server 密码轮换函数
函数应用需要以下组件:
- Azure 应用服务计划
- 带有SQL密码轮换功能以及事件触发器和HTTP触发器的Function App
- 进行函数应用触发器管理时所需的存储帐户
- 函数应用标识用于访问 Key Vault 中机密的访问策略
- “SecretNearExpiry”事件的事件网格事件订阅
选择 Azure 模板部署链接:
在 资源组 列表中,选择 akvrotation。
在“SQL Server 名称”中,键入密码需进行轮替的 SQL Server 名称
在 Key Vault 名称中,键入密钥保管库名称
在 函数应用名称中,键入函数应用名称
在 机密名称中,键入将存储密码的机密名称
在“存储库 URL”中,键入函数代码 GitHub 位置 (https://github.com/Azure-Samples/KeyVault-Rotation-SQLPassword-Csharp.git)
选择“查看 + 创建”。
选择 创建。
完成上述步骤后,你将拥有存储帐户、服务器场和函数应用。 可以通过运行以下命令在 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
有关如何创建函数应用并使用托管标识访问 Key Vault 的信息,请参阅 从 Azure 门户创建函数应用、 如何使用应用服务和 Azure Functions 的托管标识,以及 使用 Azure 门户分配 Key Vault 访问策略。
旋转函数
在先前步骤中部署的函数使用事件通过更新密钥保管库和 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 上找到完整的代码。
将机密添加到 Key Vault
设置访问策略以向用户授予 管理机密 权限:
az keyvault set-policy --upn <email-address-of-user> --name akvrotation-kv --secret-permissions set delete get list
创建包含 SQL Server 资源 ID、SQL Server 登录名和机密有效期(以天为单位)的新机密。 提供 SQL 数据库中的机密名称、初始密码(在我们的示例中为“Simple123”),并包括明天设置的到期日期。
$tomorrowDate = (get-date).AddDays(+1).ToString("yyy-MM-ddThh:mm:ssZ")
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
事件,这反过来会触发函数轮换机密。
测试和验证
若要验证机密是否已轮换,请转到 Key Vault>机密:
打开 sqlPassword 机密并查看原始版本和旋转版本:
创建 Web 应用
若要验证 SQL 凭据,请创建 Web 应用。 此 Web 应用将从 Key Vault 获取机密,从机密中提取 SQL 数据库信息和凭据,并测试与 SQL Server 的连接。
Web 应用需要以下组件:
- 一个使用系统托管标识的 Web 应用
- 通过 Web 应用托管标识访问 Key Vault 中的机密的访问策略
选择 Azure 模板部署链接:
选择 akvrotation 资源组。
在“SQL Server 名称”中,键入密码需进行轮替的 SQL Server 名称
在 Key Vault 名称中,键入密钥保管库名称
在 机密名称中,键入存储密码的机密名称
在 存储库 URL 中,键入 Web 应用代码 GitHub 位置 (https://github.com/Azure-Samples/KeyVault-Rotation-SQLPassword-Csharp-WebApp.git)
选择“查看 + 创建”。
选择 创建。
打开 Web 应用
转到已部署的应用程序 URL:
“https://akvrotation-app.azurewebsites.net/”
当应用程序在浏览器中打开时,你将看到 “生成的机密值 ”和“ 数据库连接 ”值 true。