在 Bicep 部署过程中使用 Azure Key Vault 传递安全参数值

在部署过程中,可以从 Azure 密钥保管库中检索安全值,而不是直接在 Bicep 文件或参数文件中放置安全值(如密码)。 当模块需要具有 secure:true 修饰符的 string 参数时,可以使用 getSecret 函数来获取密钥保管库机密。 值永远不会公开,因为仅引用其密钥保管库 ID。

重要

本文重点介绍如何将敏感值作为模板参数传递。 机密作为参数传递时,密钥保管库与部署到的资源组不需要位于同一订阅中。

本文并不涉及如何将虚拟机属性设置为密钥保管库中证书的 URL。 有关该方案的快速入门模板,请参阅在虚拟机上安装来自 Azure Key Vault 的证书

部署密钥保管库和机密

若要在 Bicep 部署过程中访问密钥保管库,请将密钥保管库上的 enabledForTemplateDeployment 设置为 true

如果你已有密钥保管库,请确保它允许进行模板部署。

az keyvault update  --name ExampleVault --enabled-for-template-deployment true

若要创建新的密钥保管库并添加机密,请使用:

az group create --name ExampleGroup --location chinaeast
az keyvault create \
  --name ExampleVault \
  --resource-group ExampleGroup \
  --location chinaeast \
  --enabled-for-template-deployment true
az keyvault secret set --vault-name ExampleVault --name "ExamplePassword" --value "hVFkk965BuUv"

作为密钥保管库的所有者,你可以自动获得创建机密的权限。 如果使用机密的用户不是密钥保管库的所有者,请使用以下命令授予访问权限:

az keyvault set-policy \
  --upn <user-principal-name> \
  --name ExampleVault \
  --secret-permissions set delete get list

若要详细了解如何创建密钥保管库和添加机密,请参阅:

授予对机密的访问权限

部署 Bicep 文件的用户必须在资源组和密钥保管库范围内具有 Microsoft.KeyVault/vaults/deploy/action 权限。 所有者参与者角色均授予该访问权限。 如果是你创建了密钥保管库,那么你就是所有者且具有相关权限。

以下过程展示了如何创建具有最小权限的角色,以及如何分配用户。

  1. 创建自定义角色定义 JSON 文件:

    {
      "Name": "Key Vault Bicep deployment operator",
      "IsCustom": true,
      "Description": "Lets you deploy a Bicep file with the access to the secrets in the Key Vault.",
      "Actions": [
        "Microsoft.KeyVault/vaults/deploy/action"
      ],
      "NotActions": [],
      "DataActions": [],
      "NotDataActions": [],
      "AssignableScopes": [
        "/subscriptions/aaaa0a0a-bb1b-cc2c-dd3d-eeeeee4e4e4e"
      ]
    }
    

    将“00000000-0000-0000-0000-000000000000”替换为订阅 ID。

  2. 使用 JSON 文件创建新角色:

    az role definition create --role-definition "<path-to-role-file>"
    az role assignment create \
      --role "Key Vault Bicep deployment operator" \
      --scope /subscriptions/<Subscription-id>/resourceGroups/<resource-group-name> \
      --assignee <user-principal-name>
    

    此示例在资源组级别为用户分配自定义角色。

将密钥保管库与 Bicep 文件配合用于托管应用程序时,必须向设备资源提供程序服务主体授予访问权限。 有关详细信息,请参阅部署 Azure 托管应用程序时访问 Key Vault 机密

检索 Bicep 文件中的机密

可以使用 Bicep 文件中的 getSecret 函数来获取密钥保管库机密。 请注意,getSecret 函数仅适用于 Microsoft.KeyVault/vaults 资源。 此外,它仅限于在模块的 params 部分中使用,并且只能与有 @secure() 修饰器的参数一起使用。

可以在 Bicep 参数文件中使用名为 az.getSecret() 函数的另一个函数来检索密钥保管库机密。 有关详细信息,请参阅“检索参数文件中的机密”。

因为 getSecret 函数只能在模块的 params 节中使用。 让我们在 main.bicep 文件的目录中创建一个 sql.bicep,内容如下:

param sqlServerName string
param location string = resourceGroup().location
param adminLogin string

@secure()
param adminPassword string

resource sqlServer 'Microsoft.Sql/servers@2023-08-01-preview' = {
  name: sqlServerName
  location: location
  properties: {
    administratorLogin: adminLogin
    administratorLoginPassword: adminPassword
    version: '12.0'
  }
}

请注意,在前面的 Bicep 文件中,adminPassword 参数具有 @secure() 修饰器。

以下 Bicep 文件使用 sql.bicep 作为模块。 Bicep 文件引用现有的密钥保管库,并调用 getSecret 函数来检索密钥保管库机密,然后将值作为参数传递到模块中。

param sqlServerName string
param adminLogin string

param subscriptionId string
param kvResourceGroup string
param kvName string

resource kv 'Microsoft.KeyVault/vaults@2023-07-01' existing = {
  name: kvName
  scope: resourceGroup(subscriptionId, kvResourceGroup )
}

module sql './sql.bicep' = {
  name: 'deploySQL'
  params: {
    sqlServerName: sqlServerName
    adminLogin: adminLogin
    adminPassword: kv.getSecret('vmAdminPassword')
  }
}

检索参数文件中的机密

如果不想使用模块,可以在参数文件中检索密钥保管库机密。 但是,此方法因使用的是 JSON 参数文件还是 Bicep 参数文件而异。

以下 Bicep 文件部署包含管理员密码的 SQL Server。 密码参数设置为安全字符串。 但是,Bicep 未指定该值的来源。

param sqlServerName string
param location string = resourceGroup().location
param adminLogin string

@secure()
param adminPassword string

resource sqlServer 'Microsoft.Sql/servers@2023-08-01-preview' = {
  name: sqlServerName
  location: location
  properties: {
    administratorLogin: adminLogin
    administratorLoginPassword: adminPassword
    version: '12.0'
  }
}

现在,为前面的 Bicep 文件创建参数文件。

Bicep 参数文件

az.getSecret 函数可用于 .bicepparam 文件中检索密钥保管库中的机密值。

using './main.bicep'

param sqlServerName = '<your-server-name>'
param adminLogin = '<your-admin-login>'
param adminPassword = az.getSecret('<subscription-id>', '<rg-name>', '<key-vault-name>', '<secret-name>', '<secret-version>')

JSON 参数文件

在 JSON 参数文件中,指定与 Bicep 文件中的参数名称相匹配的参数。 对于参数值,请从 key vault 中引用机密。 可以通过传递密钥保管库的资源标识符和机密的名称来引用机密:

在以下参数文件中,密钥保管库机密必须已存在,而且为其资源 ID 提供了静态值。

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "adminLogin": {
      "value": "<your-admin-login>"
    },
    "adminPassword": {
      "reference": {
        "keyVault": {
          "id": "/subscriptions/<subscription-id>/resourceGroups/<rg-name>/providers/Microsoft.KeyVault/vaults/<key-vault-name>"
        },
        "secretName": "ExamplePassword"
      }
    },
    "sqlServerName": {
      "value": "<your-server-name>"
    }
  }
}

如果需要使用当前版本以外的机密版本,请包括 secretVersion 属性。

"secretName": "ExamplePassword",
"secretVersion": "cd91b2b7e10e492ebb870a6ee0591b68"

后续步骤