概要
BicepでFunctionsを作成した。
Functionsでデータベースの接続文字列を環境変数に格納したが、secureにデプロイするためKey Vaultを使いたい。
KeyVaultのシークレット作成
infra/bin/.env
# ;が含まれているので "" で囲む
DATABASE_URL="sqlserver://hoge.database.windows.net:1433;database=fuga;user=piyo;password=piyopiyo;encrypt=true"
RESOURCE_GROUP_NAME='async-ttrpg-hogehoge'
KEY_VAULT_NAME='AsyncTrpgKeyVault'
KEY_VAULT_SECRET_NAME='AsyncTrpgDatabaseURL'
infra/bin/addKeyVault.sh
#!/bin/bash
# ディレクトリパス取得
BIN_DIR=$(cd $(dirname $0) && pwd)
BICEP_DIR=$(cd $BIN_DIR/../biceps && pwd)
# 環境変数読み込み
source $BIN_DIR/.env
LOCATION=japaneast
keyVaultName=$KEY_VAULT_NAME
keyVaultSecretName=$KEY_VAULT_SECRET_NAME
subscriptions=$(az account show | jq -r '.id')
userObjectId=$(az ad signed-in-user show | jq -r '.id')
if az keyvault list --query "[?contains(name, '$keyVaultName')].name" -o tsv | grep -q "$keyVaultName"; then
echo "Key Vault '$keyVaultName' が既に存在します。"
exit 0
fi
az keyvault create --name $keyVaultName --location $LOCATION --enabled-for-template-deployment true --resource-group $RESOURCE_GROUP_NAME
# Key Vaultが作成されるまで待機
echo "Waiting for Key Vault to be available..."
while true; do
kv=$(az keyvault show --name $keyVaultName --resource-group $RESOURCE_GROUP_NAME --query "properties.provisioningState" -o tsv)
if [ "$kv" == "Succeeded" ]; then
echo "Key Vault is available."
break
fi
echo "Key Vault is not yet available. Waiting..."
sleep 5
done
az role assignment create --role "Key Vault Secrets Officer" --assignee $userObjectId --scope /subscriptions/$subscriptions/resourceGroups/$RESOURCE_GROUP_NAME/providers/Microsoft.KeyVault/vaults/$keyVaultName
az keyvault secret set --vault-name $keyVaultName --name $keyVaultSecretName --value $DATABASE_URL --output none
設定不足によるエラー
key vaultの作成後、利用できるまでの間にシークレットを使おうとするとエラーとなる。
Resource provider 'Microsoft.KeyVault' used by this operation is not registered. We are registering for you.
If role assignments, deny assignments or role definitions were changed recently, please observe propagation time.
Cannot set policies to a vault with '--enable-rbac-authorization' specified
Azure Functions作成
infra/biceps/main.parameters.json
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"functionsRuntime": {
"value": {
"runtime": "node",
"linuxFxVersion": "Node|20",
"kind": "functionapp,linux",
"extensionVersion": "~4"
}
}
}
}
main/biceps/main.bicep
param location string = resourceGroup().location
param keyVaultName string
@description('The runtime version of the Azure Functions app.')
param functionsRuntime object
var storageAccountName = '${uniqueString(resourceGroup().id)}azfunctions'
resource keyVault 'Microsoft.KeyVault/vaults@2023-07-01' existing = {
name: keyVaultName
}
module myFunctionsStorage 'core/storage/storage-account.bicep' = {
name: 'myFunctionsStorage'
params: {
location: location
storageAccountName: storageAccountName
}
}
module myFunctions 'core/host/functions.bicep' = {
name: 'myFunctions'
params: {
location: location
+ databaseUrl: keyVault.getSecret('AsyncTrpgDatabaseURL')
storageAccountName: storageAccountName
kind: functionsRuntime.kind
linuxFxVersion: functionsRuntime.linuxFxVersion
extensionVersion: functionsRuntime.extensionVersion
}
}
output appServiceAppHostName string = myFunctions.outputs.appServiceAppHostName
infra/core/host/functions.bicep
param storageAccountName string
param location string
param kind string
param linuxFxVersion string
param extensionVersion string
+ @secure()
param databaseUrl string
var functionAppName = '${uniqueString(resourceGroup().id)}azfunctionsapp'
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' existing = {
name: storageAccountName
}
resource functionApp 'Microsoft.Web/sites@2022-09-01' = {
name: functionAppName
location: location
kind: kind
properties: {
reserved: true
siteConfig: {
linuxFxVersion: linuxFxVersion
appSettings: [
{
name: 'AzureWebJobsStorage'
value: 'DefaultEndpointsProtocol=https;AccountName=${storageAccountName};EndpointSuffix=${environment().suffixes.storage};AccountKey=${storageAccount.listKeys().keys[0].value}'
}
{
name: 'WEBSITE_CONTENTSHARE'
value: toLower(functionAppName)
}
{
name: 'FUNCTIONS_EXTENSION_VERSION'
value: extensionVersion
}
{
name: 'FUNCTIONS_WORKER_RUNTIME'
value: 'node'
}
{
name: 'DATABASE_URL'
value: databaseUrl
}
]
}
}
}
output appServiceAppHostName string = functionApp.properties.defaultHostName
実行
infra/bin/createFunction.bash
#!/bin/bash
# ディレクトリパス取得
BIN_DIR=$(cd $(dirname $0) && pwd)
BICEP_DIR=$(cd $BIN_DIR/../biceps && pwd)
# 環境変数読み込み
source $BIN_DIR/.env
LOCATION=japaneast
cd $BICEP_DIR && az deployment group create \
--name functionsDeployment \
--template-file main.bicep \
--parameters main.parameters.json \
--parameters \
keyVaultName=$KEY_VAULT_NAME \
-g $RESOURCE_GROUP_NAME
参考
Bicep デプロイ時に Azure Key Vault を使用して、セキュリティで保護されたパラメーター値を渡す
演習:パラメーターを使用して再利用可能な Bicep テンプレートを構築する