在部署期間使用 Azure Key Vault 以傳遞安全的參數值

您可以在部署期間從 Azure Key Vault 中取得值,而不是將安全的值 (像是) 直接放在範本或參數檔案中的密碼。 您可以藉由參考金鑰保存庫和參數檔案中的密碼來擷取值。 您只參考其金鑰保存庫識別碼,因此該值絕不會公開。

重要

本文著重于如何以範本參數的形式傳遞機密值。 將秘密作為參數傳遞時,金鑰保存庫可以存在於與您要部署的資源群組不同的訂用帳戶中。

本文不會說明如何將虛擬機器屬性設定為金鑰保存庫中的憑證 URL。 如需該案例的快速入門範本,請參閱在 虛擬機器上安裝 Azure Key Vault 的憑證

部署金鑰保存庫和祕密

若要在範本部署期間存取金鑰保存庫,請 enabledForTemplateDeployment 在金鑰保存庫上將設定為 true

如果您已經有金鑰保存庫,請確定它允許範本部署。

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

若要建立新的金鑰保存庫並新增秘密,請使用:

az group create --name ExampleGroup --location centralus
az keyvault create \
  --name ExampleVault \
  --resource-group ExampleGroup \
  --location centralus \
  --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

如果使用者正在部署可抓取密碼的範本,則不需要存取原則。 只有當使用者需要直接使用秘密時,才將使用者新增至存取原則。 部署許可權是在下一節中定義的。

如需建立金鑰保存庫和新增秘密的詳細資訊,請參閱:

授與部署對秘密的存取權

部署範本的使用者必須擁有 Microsoft.KeyVault/vaults/deploy/action 資源群組和金鑰保存庫範圍的許可權。 藉由檢查此存取權,Azure Resource Manager 藉由傳遞金鑰保存庫的資源識別碼,來防止未核准的使用者存取秘密。 您可以將部署存取權授與使用者,而不需授與秘密的寫入權限。

擁有者參與者角色皆可授與此權限。 如果您已建立金鑰保存庫,您就是擁有者,而且具有許可權。

若為其他使用者,請授與 Microsoft.KeyVault/vaults/deploy/action 許可權。 下列程式說明如何建立具有最低許可權的角色,並將其指派給使用者。

  1. 建立自訂角色定義 JSON 檔案:

    {
      "Name": "Key Vault resource manager template deployment operator",
      "IsCustom": true,
      "Description": "Lets you deploy a resource manager template with the access to the secrets in the Key Vault.",
      "Actions": [
        "Microsoft.KeyVault/vaults/deploy/action"
      ],
      "NotActions": [],
      "DataActions": [],
      "NotDataActions": [],
      "AssignableScopes": [
        "/subscriptions/00000000-0000-0000-0000-000000000000"
      ]
    }
    

    以訂用帳戶識別碼取代 "00000000-0000-0000-0000-000000000000"。

  2. 使用 JSON 檔案建立新的角色:

    az role definition create --role-definition "<path-to-role-file>"
    az role assignment create \
      --role "Key Vault resource manager template deployment operator" \
      --assignee <user-principal-name> \
      --resource-group ExampleGroup
    

    這些範例會將自訂角色指派給資源群組層級上的使用者。

使用具有 受控應用程式範本的金鑰保存庫時,您必須授與對 設備資源提供者 服務主體的存取權。 如需詳細資訊,請參閱在部署 Azure 受控應用程式時存取金鑰保存庫密碼 (英文)。

使用靜態識別碼參考祕密

透過這個方法,您可參考參數檔案中的金鑰保存庫,而非範本。 下圖顯示參數檔案如何參考祕密,並將該值傳遞至範本。

Resource Manager 金鑰保存庫整合靜態識別碼圖表

教學課程:整合 Resource Manager 範本部署中的 Azure Key Vault 使用這個方法。

下列範本會部署包含系統管理員密碼的 SQL 伺服器。 密碼參數會設定為安全字串。 但是,此範本並不會指定該值的來源。

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

現在,請為前述範本建立參數檔案。 在參數檔案中,指定符合範本中參數名稱的參數。 針對參數值,參考來自金鑰保存庫的密碼。 您可以藉由傳遞金鑰保存庫的資源識別碼和密碼的名稱來參考密碼:

在下列參數檔案中,金鑰保存庫祕密必須已經存在,而且您要針對其資源識別碼提供靜態值。

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

如果您需要使用目前版本以外的秘密版本,請包含 secretVersion 屬性。

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

部署範本並在參數檔案中傳遞:

az group create --name SqlGroup --location westus2
az deployment group create \
  --resource-group SqlGroup \
  --template-uri <template-file-URI> \
  --parameters <parameter-file>

使用動態識別碼參考祕密

上一節已說明如何從參數傳遞金鑰保存庫秘密的靜態資源識別碼。 在某些情況下,您需要參考根據目前部署而有所不同的金鑰保存庫密碼。 或者,您可能想要將參數值傳遞至範本,而不是在參數檔案中建立參考參數。 解決方案是使用連結的範本,以動態方式產生金鑰保存庫秘密的資源識別碼。

由於參數檔中不允許使用範本運算式,因此您無法在參數檔中以動態方式產生資源識別碼。

在您的父範本中,您可以新增嵌套的範本,並傳入包含動態產生之資源識別碼的參數。 下圖顯示連結的範本中的參數如何參考祕密。

動態識別碼

下列範本會動態建立金鑰保存庫識別碼,並將它當作參數傳遞。

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-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."
        }
      }
  },
  "resources": [
    {
      "type": "Microsoft.Resources/deployments",
      "apiVersion": "2020-10-01",
      "name": "dynamicSecret",
      "properties": {
        "mode": "Incremental",
        "expressionEvaluationOptions": {
          "scope": "inner"
        },
        "template": {
          "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
          "contentVersion": "1.0.0.0",
          "parameters": {
            "adminLogin": {
              "type": "string"
            },
            "adminPassword": {
              "type": "securestring"
            },
            "location": {
              "type": "string"
            }
          },
          "variables": {
            "sqlServerName": "[concat('sql-', uniqueString(resourceGroup().id, 'sql'))]"
          },
          "resources": [
            {
              "type": "Microsoft.Sql/servers",
              "apiVersion": "2018-06-01-preview",
              "name": "[variables('sqlServerName')]",
              "location": "[parameters('location')]",
              "properties": {
                "administratorLogin": "[parameters('adminLogin')]",
                "administratorLoginPassword": "[parameters('adminPassword')]"
              }
            }
          ],
          "outputs": {
            "sqlFQDN": {
              "type": "string",
              "value": "[reference(variables('sqlServerName')).fullyQualifiedDomainName]"
            }
          }
        },
        "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": {
  }
}

下一步