若要对Azure服务进行身份验证的最佳方法是使用 托管标识,但在某些情况下,情况并非如此。 在此类情况下,将使用访问密钥或机密。 应定期轮换访问密钥或机密。
本教程介绍如何定期自动轮换使用一组身份验证凭据的数据库和服务的机密。 有关不同资产类型的自动轮转概念和优势的综合概述,请参阅 了解 Azure Key Vault 中的自动轮转。
具体而言,本教程使用由Azure Event Grid通知触发的函数轮换存储在Azure Key Vault中的SQL Server密码:
- 在机密到期日期之前的三十天,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 chinaeast Microsoft.KeyVault/vaults
akvrotation-sql akvrotation chinaeast Microsoft.Sql/servers
akvrotation-sql/master akvrotation chinaeast Microsoft.Sql/servers/databases
akvrotation-sql2 akvrotation chinaeast Microsoft.Sql/servers
akvrotation-sql2/master akvrotation chinaeast Microsoft.Sql/servers/databases
创建和部署 SQL Server 密码轮换函数
重要
此模板要求密钥保管库、SQL Server 和 Azure 函数位于同一资源组中。
接下来,创建一个使用系统托管标识的函数应用以及其他所需组件,并部署 SQL Server 密码轮换函数
该函数应用需要以下组件:
- Azure App Service 计划
- 一个包含具有事件触发器和 http 触发器的 SQL 密码轮换函数的函数应用
- 进行函数应用触发器管理时所需的存储帐户
- Function App 标识访问Key Vault中的机密的访问策略
- “SecretNearExpiry”事件订阅的事件网格
选择Azure模板部署链接:
在“资源组”列表中选择“akvrotation”。
在 SQL Server Name 中,输入 SQL Server 名称及其要轮换的密码。
在 Key Vault Name中,键入key vault名称
在“函数应用名称”中,键入函数应用名称
在“机密名称”中,键入将在其中存储密码的机密名称
在 Repo 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 chinaeast Microsoft.KeyVault/vaults
akvrotation-sql akvrotation chinaeast Microsoft.Sql/servers
akvrotation-sql/master akvrotation chinaeast Microsoft.Sql/servers/databases
cfogyydrufs5wazfunctions akvrotation chinaeast Microsoft.Storage/storageAccounts
akvrotation-fnapp akvrotation chinaeast Microsoft.Web/serverFarms
akvrotation-fnapp akvrotation chinaeast Microsoft.Web/sites
akvrotation-fnapp akvrotation chinaeast Microsoft.insights/components
有关如何创建函数应用并使用托管标识访问 Key Vault 的信息,请参阅 从 Azure 门户创建函数应用、如何使用托管标识用于应用服务和 Azure Functions,以及使用 Azure 门户分配 Key Vault 访问策略。
旋转函数
在上一步中部署的函数使用事件通过更新 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.cn";
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("yyyy-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>Secrets:
打开“sqlPassword”机密并查看原始版本和轮换后的版本:
创建 Web 应用
若要验证 SQL 凭据,请创建一个 Web 应用。 此 Web 应用将从Key Vault获取机密,从机密中提取 SQL 数据库信息和凭据,并测试与SQL Server的连接。
该 Web 应用需要以下组件:
- 一个具有由系统管理身份的 Web 应用
- 访问策略,用于通过 Web 应用托管标识访问Key Vault中的机密
选择Azure模板部署链接:
选择“akvrotation”资源组。
在 SQL Server Name 中,输入 SQL Server 名称及其要轮换的密码。
在 Key Vault Name中,键入key vault名称
在“机密名称”中,键入将在其中存储密码的机密名称
在 Repo Url 中,键入 web 应用代码GitHub位置(https://github.com/Azure-Samples/KeyVault-Rotation-SQLPassword-Csharp-WebApp.git)
选择“审核 + 创建”。
选择“创建”。
打开 Web 应用
转到部署的应用程序 URL:
https://akvrotation-app.azurewebsites.net/
当应用程序在浏览器中打开时,你会看到“生成的机密值”,并会看到“数据库已连接”的值为“true”。
了解详细信息
- 使用两组凭据进行资源轮换
- 理解 Azure Key Vault 中的自动轮换
- 使用 Azure Event Grid 监控 Key Vault
Azure Event Grid 的 Azure Key Vault 事件架构