Bicep デプロイ時に Azure Key Vault を使用して、セキュリティで保護されたパラメーター値を渡す

お使いの Bicep ファイルやパラメーター ファイルにセキュリティで保護された値 (パスワードなど) を直接入れる代わりに、デプロイ時に、Azure Key Vault から値を取得できます。 モジュールsecure:true 修飾子を持つ string パラメーターを必要とする場合は、getSecret 関数を使用してキー コンテナーのシークレットを取得できます。 参照するのは Key Vault ID だけであるため、値が公開されることはありません。

重要

この記事では、機密の値をテンプレート パラメーターとして渡す方法に焦点を当てます。 シークレットがパラメーターとして渡されるとき、キー コンテナーは別のサブスクリプションに存在するか、デプロイ先のリソース グループに存在することがあります。

この記事では、仮想マシンのプロパティを、キー コンテナー内の証明書の URL に設定する方法については説明しません。 そのシナリオのクイックスタート テンプレートについては、Azure Key Vault から証明書を仮想マシンにインストールする方法に関する記事を参照してください。

キー コンテナーとシークレットをデプロイする

Bicep のデプロイ時にキー コンテナーにアクセスするには、キー コンテナーの enabledForTemplateDeploymenttrue に設定します。

既にキー コンテナーがある場合は、テンプレートのデプロイが許可されていることを確認してください。

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

キー コンテナーの作成とシークレットの追加の詳細については、次を参照してください。

シークレットへのアクセスを許可する

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/00000000-0000-0000-0000-000000000000"
      ]
    }
    

    "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>
    

    このサンプルでは、リソース グループ レベルでカスタム ロールを割り当てます。

Managed Applications の Bicep ファイルでキー コンテナーを使用する場合は、アプライアンス リソース プロバイダー サービス プリンシパルにアクセス許可を付与する必要があります。 詳細については、「Access Key Vault secret when deploying Azure Managed Applications」(Azure Managed Applications のデプロイ時に Key Vault シークレットにアクセスする) を参照してください。

Bicep ファイルでシークレットを取得する

Bicep ファイルの getSecret 関数を使用して、キー コンテナーのシークレットを取得できます。 getSecret 関数は Microsoft.KeyVault/vaults リソースにのみ適用されることに注意してください。 さらに、モジュールの params セクション内での使用に制限され、@secure() デコレーターを指定したパラメーターでのみ使用できます。

az.getSecret() 関数という別の関数を Bicep パラメーター ファイルで使用して、キー コンテナーのシークレットを取得できます。 詳細については、「パラメーター ファイルのシークレットを取得する」を参照してください。

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 サーバーがデプロイされます。 パスワード パラメーターは、セキュリティで保護された文字列に設定されます。 しかし、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"

次のステップ