Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
向Azure服务进行身份验证的最佳方式是使用托管标识,但某些方案需要访问密钥、密码或其他机密。 定期轮换这些机密,以减少泄露凭据的影响。
本教程介绍如何为使用一组身份验证凭据的数据库和服务自动执行定期机密轮换。 有关不同资产类型中的自动轮换概述,请参阅了解 Azure 密钥保管库 中的自动轮换。
具体而言,本教程使用由Azure 事件网格通知触发的函数轮换存储在Azure 密钥保管库中的SQL Server密码:
- 在机密到期日期之前的三十天,密钥保管库将“即将过期”事件发布到事件网格。
- 事件网格会检查事件订阅,并使用 HTTP POST 调用已订阅该事件的函数应用终结点。
- 函数应用接收机密信息,生成新的随机密码,并在密钥保管库中使用新密码为机密创建新版本。
- 函数应用使用新密码更新SQL Server。
注意
步骤 3 和步骤 4 之间可能存在延迟。 在该窗口中,密钥保管库中的机密无法向SQL Server进行身份验证。 如果任何步骤失败,事件网格将重试两个小时。
先决条件
- Azure订阅 - 免费创建一个订阅。
- Azure 密钥保管库。
- SQL Server。
如果还没有密钥保管库和SQL Server实例,请使用以下部署链接:
- 在 “资源组”下,选择“ 新建”,并为组命名。 本教程使用 akvrotation。
- 在 SQL 管理员登录名下,输入 SQL 管理员登录名。
- 选择“审核 + 创建”。
- 选择“创建”。
现在有一个密钥保管库和一个SQL Server实例。 在Azure CLI中验证此设置:
az resource list -o table -g akvrotation
结果类似于以下输出:
Name ResourceGroup Location Type Status
----------------------- -------------------- ---------- --------------------------------- --------
akvrotation-kv akvrotation chinaeast2 Microsoft.KeyVault/vaults
akvrotation-sql akvrotation chinaeast2 Microsoft.Sql/servers
akvrotation-sql/master akvrotation chinaeast2 Microsoft.Sql/servers/databases
akvrotation-sql2 akvrotation chinaeast2 Microsoft.Sql/servers
akvrotation-sql2/master akvrotation chinaeast2 Microsoft.Sql/servers/databases
创建和部署SQL Server密码轮换函数
重要
此模板要求 Key Vault、SQL Server 实例和函数应用位于同一资源组中。
接下来,创建具有系统分配的托管标识和其他必需组件的函数应用,并部署SQL Server密码轮换函数。
该函数应用需要以下组件:
- 一个 Azure 应用服务 计划。
- 包含具有 Event Grid 触发器和 HTTP 触发器的 SQL 密码轮换函数的函数应用。
- 用于函数应用触发器管理的存储帐户。
- 一种 Azure 角色分配,允许函数应用的标识访问密钥保管库中的机密信息。
- 针对
事件的事件网格订阅。
选择Azure模板部署链接:
在“资源组”列表中选择“akvrotation”。
在SQL Server名称中,输入要轮换其密码的SQL Server实例的名称。
在密钥保管库名称中,输入密钥保管库名称。
在 函数应用名称中,输入函数应用名称。
在 机密名称中,输入存储密码的机密名称。
在 仓库 URL 中,输入该函数代码的 GitHub 位置:
https://github.com/Azure-Samples/KeyVault-Rotation-SQLPassword-Csharp.git选择“审核 + 创建”。
选择“创建”。
注意
此 ARM 模板使用应用服务源代码管理(Kudu)部署,以从 GitHub 拉取函数代码。 对于生产环境工作负载,我们建议改用基于包的部署方式,例如 func azure functionapp publish 或配合 WEBSITE_RUN_FROM_PACKAGE 使用的 zip deploy。
完成上述步骤后,你有一个存储帐户、服务器场和一个函数应用。 在Azure CLI中验证此设置:
az resource list -o table -g akvrotation
结果类似于以下输出:
Name ResourceGroup Location Type Status
----------------------- -------------------- ---------- --------------------------------- --------
akvrotation-kv akvrotation chinaeast2 Microsoft.KeyVault/vaults
akvrotation-sql akvrotation chinaeast2 Microsoft.Sql/servers
akvrotation-sql/master akvrotation chinaeast2 Microsoft.Sql/servers/databases
cfogyydrufs5wazfunctions akvrotation chinaeast2 Microsoft.Storage/storageAccounts
akvrotation-fnapp akvrotation chinaeast2 Microsoft.Web/serverFarms
akvrotation-fnapp akvrotation chinaeast2 Microsoft.Web/sites
akvrotation-fnapp akvrotation chinaeast2 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.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 上找到完整的代码。
将机密添加到密钥保管库
为自己分配密钥保管库 机密负责人角色,以便能够在保管库中管理机密:
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:
打开“sqlPassword”机密并查看原始版本和轮换后的版本:
创建 Web 应用
若要验证 SQL 凭据,请创建一个 Web 应用。 Web 应用从密钥保管库检索机密,从机密中提取 SQL 数据库信息和凭据,并测试与SQL Server的连接。
该 Web 应用需要以下组件:
- 具有系统分配的托管标识的 Web 应用。
- 一种角色分配,允许 Web 应用的托管标识读取密钥保管库中的机密。
选择Azure模板部署链接:
选择“akvrotation”资源组。
在SQL Server 名称字段中,输入其密码已轮换的 SQL Server 名称。
在密钥保管库名称中,输入密钥保管库名称。
在 机密名称中,输入存储密码的机密名称。
在 仓库 URL 中,输入 Web 应用代码的 GitHub 位置:
https://github.com/Azure-Samples/KeyVault-Rotation-SQLPassword-Csharp-WebApp.git选择“审核 + 创建”。
选择“创建”。
打开 Web 应用
转到部署的应用程序 URL:
https://akvrotation-app.azurewebsites.net/
当应用程序在浏览器中打开时,你会看到“生成的机密值”,并会看到“数据库已连接”的值为“true”。
了解详细信息
- 使用两组凭据进行资源轮换
- 理解 Azure 密钥保管库 中的自动轮换
- 使用 Azure 事件网格 监控 密钥保管库
Azure 事件网格 的 Azure 密钥保管库 事件架构