🔑

Azure Key Vault を Bicep から参照する

2022/07/22に公開

TL;DR

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

パスワードとか PSK とかを Bicep に書きたくない

当たり前ですが、パスワードとか VPN の PSK (Pre-Shared Key) を Bicep ファイルに平文で書くのはあまりセキュアではないですね。
デプロイ時に手で入力するのでもいいのですが、ややめんどいです。

Bicep には Azure Key Vault 参照の機能がある

Bicep ファイルに直接そういった文字列を書かなくても、Azure Key Vault に格納しておいて、それを参照してくれる機能があります。(ARM template にもともとある機能)

Azure Key Vault 側の設定

まずは適当に Azure Key Vault を作って、Secret として adminPassword とかを入れておきます。
次に、"Azure Resource Manager for template deployment (日本語では「Azure Resource Manager (テンプレートの展開用)」)" というオプションを Azure Key Vault でオンにしておきます。
これにより、ARM (ユーザが ARM template や Bicep ファイルを投げ込んだ後、ARM bot 的なものが裏で動いてデプロイするのをイメージしてみる) から Secret を参照できるようになります。

Azure Key Vault permit ARM

また、それだけでは任意のユーザが ARM template や Bicep ファイルを投げれば参照できてしまうことになるので、デプロイを指示したユーザ自身に権限があるかも RBAC の範囲で確認がされます。

Bicep ファイル側の書き方

まずは existing キーワードを使って Azure Key Vault の中間オブジェクトみたいなのを作ります。
その際、もし Resource Group が別の場合 (以下の例がそうですが) scope: を指定することで別 Resource Group の Azure Key Vault もちゃんと参照できます。
そのうえで、例えば自作の Windows Server 2019 VM を作成する module に対し adminPassword を渡すわけですが、ここで kv.getSecret('Secret の名前') とやれば、指定した Secret に書かれたパスワードなどの文字列をここに入れてくれます。

param kvName string = 'xxxxxxxxxxxx'
param secretName string = 'xxxxxxxxxxxx'

resource kv 'Microsoft.KeyVault/vaults@2021-10-01' existing = {
  name: kvName
  scope: resourceGroup('xxxxxxxxxxxx')
}

var vm01Name = 'vm-loc01'
module vm_loc01 '../lib/ws2019.bicep' = {
  name: vm01Name
  params: {
    location: location01
    adminUsername: 'ikko'
    adminPassword: kv.getSecret(secretName)
    subnetId: vnet01::defaultsubnet.id
    vmName: vm01Name
  }
}

これで何度も何度も az deployment group create するときに、なんどもパスワードを手で入力しなくてもよくなります。


以下参考 URL など。

Bicep の getSecret 関数


以下の Bicep ファイルが Windows Server 2019 VM を作ってくれる自作 module (2022年07月 モデル) です。

  • Windows Server 2019 の smalldisk
  • ディスクは StandardSSD
  • 00:00 に自動シャットダウン
param location string = 'eastasia'
param subnetId string
param vmName string
param adminUsername string = 'xxxxxxxx'
@secure()
param adminPassword string

var vmNameSuffix = replace(vmName, 'vm-', '')

resource nic 'Microsoft.Network/networkInterfaces@2022-01-01' = {
  name: 'nic-${vmNameSuffix}'
  location: location
  properties: {
    ipConfigurations: [
      {
        name: 'ipconfig1'
        properties: {
          subnet: {
            id: subnetId
          }
          privateIPAllocationMethod: 'Dynamic'
        }
      }
    ]
  }
}

resource vm 'Microsoft.Compute/virtualMachines@2022-03-01' = {
  name: vmName
  location: location
  properties: {
    hardwareProfile: {
      vmSize: 'Standard_B2ms'
    }
    storageProfile: {
      osDisk: {
        createOption: 'FromImage'
        managedDisk: {
          storageAccountType: 'StandardSSD_LRS'
        }
        deleteOption: 'Delete'
      }
      imageReference: {
        publisher: 'MicrosoftWindowsServer'
        offer: 'WindowsServer'
        sku: '2019-datacenter-smalldisk-g2'
        version: 'latest'
      }
    }
    networkProfile: {
      networkInterfaces: [
        {
          id: nic.id
          properties: {
            deleteOption: 'Delete'
          }
        }
      ]
    }
    osProfile: {
      computerName: vmName
      adminUsername: adminUsername
      adminPassword: adminPassword
    }
    diagnosticsProfile: {
      bootDiagnostics: {
        enabled: true
      }
    }
  }
}

resource shutdown 'Microsoft.DevTestLab/schedules@2018-09-15' = {
  name: 'shutdown-computevm-${vmName}'
  location: location
  properties: {
    status: 'Enabled'
    taskType: 'ComputeVmShutdownTask'
    dailyRecurrence: {
      time: '00:00'
    }
    timeZoneId: 'Tokyo Standard Time'
    targetResourceId: vm.id
    notificationSettings: {
      status: 'Disabled'
    }
  }
}
Microsoft (有志)

Discussion