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

在部署过程中,需要将安全值(例如密码)作为参数传递时,可从 Azure Key Vault 检索值。 通过引用参数文件中的密钥保管库和密钥来检索值。 值永远不会公开,因为仅引用其密钥保管库 ID。 密钥保管库与部署到的资源组不需要位于同一订阅中。

启用密钥访问权限

要在部署模板期间访问 Key Vault,必须满足两个重要的条件:

  1. Key Vault 属性 enabledForTemplateDeployment 必须为 true
  2. 部署模板的用户必须有权访问该机密。 用户必须具有 Key Vault 的 Microsoft.KeyVault/vaults/deploy/action 权限。 所有者参与者角色均授予该访问权限。

部署密钥保管库和机密

若要创建密钥保管库和机密,请使用 Azure CLI 或 PowerShell。 请注意,已为模板部署启用密钥保管库。

对于 Azure CLI,请使用:

vaultname={your-unique-vault-name}
password={password-value}

az group create --name examplegroup --location 'China North'
az keyvault create \
  --name $vaultname \
  --resource-group examplegroup \
  --location 'China North' \
  --enabled-for-template-deployment true
az keyvault secret set --vault-name $vaultname --name examplesecret --value $password

对于 PowerShell,请使用:

$vaultname = "{your-unique-vault-name}"
$password = "{password-value}"

New-AzureRmResourceGroup -Name examplegroup -Location "China North"
New-AzureRmKeyVault `
  -VaultName $vaultname `
  -ResourceGroupName examplegroup `
  -Location "China North" `
  -EnabledForTemplateDeployment
$secretvalue = ConvertTo-SecureString $password -AsPlainText -Force
Set-AzureKeyVaultSecret -VaultName $vaultname -Name "examplesecret" -SecretValue $secretvalue

通过静态 ID 引用机密

接收密钥保管库机密的模板与任何其他模板一样。 这是因为在参数文件(而不是在模板)中引用 key vault。 下图显示了参数文件如何引用机密并将该值传递到模板。

静态 ID

例如,以下模板部署包括管理员密码的 SQL 数据库。 密码参数设置为安全字符串。 但是,此模板未指定该值的来源。

{
  "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "adminLogin": {
      "type": "string"
    },
    "adminPassword": {
      "type": "securestring"
    },
    "sqlServerName": {
      "type": "string"
    }
  },
  "resources": [
    {
      "name": "[parameters('sqlServerName')]",
      "type": "Microsoft.Sql/servers",
      "apiVersion": "2015-05-01-preview",
      "location": "[resourceGroup().location]",
      "tags": {},
      "properties": {
        "administratorLogin": "[parameters('adminLogin')]",
        "administratorLoginPassword": "[parameters('adminPassword')]",
        "version": "12.0"
      }
    }
  ],
  "outputs": {
  }
}

现在,为上述模板创建参数文件。 在参数文件中,指定与模板中的参数名称匹配的参数。 对于参数值,请从密钥保管库中引用机密。 可以通过传递密钥保管库的资源标识符和机密的名称来引用机密。 在以下参数文件中,Key Vault 机密必须已存在,而且为其资源 ID 提供了静态值。 在本地复制此文件,并设置订阅 ID、保管库名称和 SQL server 名称。

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "adminLogin": {
            "value": "exampleadmin"
        },
        "adminPassword": {
            "reference": {
              "keyVault": {
                "id": "/subscriptions/<subscription-id>/resourceGroups/examplegroup/providers/Microsoft.KeyVault/vaults/<vault-name>"
              },
              "secretName": "examplesecret"
            }
        },
        "sqlServerName": {
            "value": "<your-server-name>"
        }
    }
}

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

"secretName": "examplesecret",
"secretVersion": "cd91b2b7e10e492ebb870a6ee0591b68"

现在,部署模板并传入参数文件。 可以使用 GitHub 中的示例模板,但必须使用本地参数文件并将值设置为自己的环境。

Note

必须修改从 GitHub 存储库 sqlserver.json 下载的模板,以适应 Azure 中国云环境。 例如,替换某些终结点(将“blob.core.windows.net”替换为“blob.core.chinacloudapi.cn”,将“cloudapp.azure.com”替换为“chinacloudapp.cn”);更改某些不受支持的 VM 映像;更改某些不受支持的 VM 大小、SKU 以及资源提供程序的 API 版本。

对于 Azure CLI,请使用:

az group create --name datagroup --location "China North"
az group deployment create \
    --name exampledeployment \
    --resource-group datagroup \
    --template-file /path/to/sqlserver.json \
    --parameters @sqlserver.parameters.json

对于 PowerShell,请使用:

New-AzureRmResourceGroup -Name datagroup -Location "China North"
New-AzureRmResourceGroupDeployment `
  -Name exampledeployment `
  -ResourceGroupName datagroup `
  -TemplateFile /path/to/sqlserver.json `
  -TemplateParameterFile sqlserver.parameters.json

通过动态 ID 引用机密

上一部分介绍了如何通过参数传递密钥保管库机密的静态资源 ID。 但是,在某些情况下,需要引用随当前部署而变的密钥保管库机密。 或者,你可能只想将参数值传递给模板,而不是在参数文件中创建引用参数。 在任何一种情况下,均可使用链接模板为密钥保管库机密动态生成资源 ID。

不能在参数文件中动态生成资源 ID,因为参数文件中不允许使用模板表达式。

在父模板中添加链接模板,然后传入包含动态生成的资源 ID 的参数。 下图显示链接模板中的参数如何引用机密。

动态 ID

以下模板动态创建 Key Vault ID 并将其作为参数传递。

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "location": {
            "type": "string",
            "defaultValue": "[resourceGroup().location]",
            "metadata": {
                "description": "The location where the resources will be deployed."
            }
        },
        "vaultName": {
            "type": "string",
            "metadata": {
                "description": "The name of the keyvault that contains the secret."
            }
        },
        "secretName": {
            "type": "string",
            "metadata": {
                "description": "The name of the secret."
            }
        },
        "vaultResourceGroupName": {
            "type": "string",
            "metadata": {
                "description": "The name of the resource group that contains the keyvault."
            }
        },
        "vaultSubscription": {
            "type": "string",
            "defaultValue": "[subscription().subscriptionId]",
            "metadata": {
                "description": "The name of the subscription that contains the keyvault."
            }
        },
        "_artifactsLocation": {
            "type": "string",
            "metadata": {
                "description": "The base URI where artifacts required by this template are located. When the template is deployed using the accompanying scripts, a private location in the subscription will be used and this value will be automatically generated."
            },
            "defaultValue": "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/201-key-vault-use-dynamic-id/"
        },
        "_artifactsLocationSasToken": {
            "type": "securestring",
            "metadata": {
                "description": "The sasToken required to access _artifactsLocation.  When the template is deployed using the accompanying scripts, a sasToken will be automatically generated."
            },
            "defaultValue": ""
        }
    },
    "resources": [
        {
            "apiVersion": "2018-05-01",
            "name": "dynamicSecret",
            "type": "Microsoft.Resources/deployments",
            "properties": {
                "mode": "Incremental",
                "templateLink": {
                    "contentVersion": "1.0.0.0",
                    "uri": "[uri(parameters('_artifactsLocation'), concat('./nested/sqlserver.json', parameters('_artifactsLocationSasToken')))]"
                },
                "parameters": {
                    "location": {
                        "value": "[parameters('location')]"
                    },
                    "adminLogin": {
                        "value": "ghuser"
                    },
                    "adminPassword": {
                        "reference": {
                            "keyVault": {
                                "id": "[resourceId(parameters('vaultSubscription'), parameters('vaultResourceGroupName'), 'Microsoft.KeyVault/vaults', parameters('vaultName'))]"
                            },
                            "secretName": "[parameters('secretName')]"
                        }
                    }
                }
            }
        }
    ],
    "outputs": {
        "sqlFQDN": {
            "type": "string",
            "value": "[reference('dynamicSecret').outputs.sqlFQDN.value]"
        }
    }
}

部署前面的模板,并为参数提供值。 可以使用 GitHub 中的示例模板,但必须提供环境的参数值。

Note

必须修改从 GitHub 存储库 azuredeploy.json 下载的模板,以适应 Azure 中国云环境。 例如,替换某些终结点(将“blob.core.windows.net”替换为“blob.core.chinacloudapi.cn”,将“cloudapp.azure.com”替换为“chinacloudapp.cn”);更改某些不受支持的 VM 映像;更改某些不受支持的 VM 大小、SKU 以及资源提供程序的 API 版本。

对于 Azure CLI,请使用:

az group create --name datagroup --location "China North"
az group deployment create \
    --name exampledeployment \
    --resource-group datagroup \
    --template-file /path/to/azuredeploy.json \
    --parameters vaultName=<your-vault> vaultResourceGroupName=examplegroup secretName=examplesecret

对于 PowerShell,请使用:

New-AzureRmResourceGroup -Name datagroup -Location "China North"
New-AzureRmResourceGroupDeployment `
  -Name exampledeployment `
  -ResourceGroupName datagroup `
  -TemplateFile /path/to/azuredeploy.json `
  -vaultName <your-vault> -vaultResourceGroupName examplegroup -secretName examplesecret

后续步骤