我正在尝试在我的资源中加入一些额外的安全功能,例如使用客户管理的 key 进行加密。对于服务总线,这要求服务总线创建托管标识并授予对 Key Vault 的访问权限。但是,直到服务总线存在之后,托管身份才会被知晓。
在我的 ARM 模板中,我需要在不加密的情况下初始化服务总线,以获得托管身份,授予该身份对 key 保管库的访问权限,然后使用加密更新服务总线。然而,这个部署过程是不可重复的。在后续重新部署中,它将失败,因为加密一旦被授予就无法从服务总线中删除。即使它确实有效,我也会执行不必要的步骤来删除加密并将其添加回每个部署中。似乎描述资源预期最终状态的 IAC 模板不能用于维护和引导新环境。
API 管理也存在同样的问题,我想添加自定义域,但它们需要 Key Vault 访问权限。这意味着当重复初始化步骤时,我无法在不删除自定义域的情况下重新部署我的 ARM 模板(或者为“初始化”与“实际部署”保留一组单独的模板。
有没有更好的解决方案?我研究了用户分配的身份,这似乎可以解决问题,但 ARM 模板不支持它们。我检查了是否有办法通过检查资源是否已存在来使“init”步骤成为有条件的,并且 ARM 模板也不支持这一点。
最佳答案
如果您想维护单个ARM模板,可以使用nested deployments定义资源,然后再次引用它来更新它。
在以下示例中,我使用系统分配的托管标识、Key Vault 和 RSA key 创建服务总线。在依赖于生成的 key 的同一 ARM 模板内的嵌套部署中,我随后更新服务总线以启用加密。全部位于同一模板中的一个优点是 resourceId
和 reference
可以使用缩写语法(即仅资源名称)。
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"name": {
"type": "string",
"defaultValue": "[resourceGroup().name]"
},
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]"
},
"tenantId": {
"type": "string",
"defaultValue": "[subscription().tenantId]"
}
},
"variables": {
"kv_name": "[concat(parameters('name'), 'kv')]",
"kv_version": "2019-09-01",
"sb_name": "[concat(parameters('name'), 'sb')]",
"sb_version": "2018-01-01-preview",
"sb_keyname": "sbkey"
},
"resources": [
{
"type": "Microsoft.ServiceBus/namespaces",
"apiVersion": "[variables('sb_version')]",
"name": "[variables('sb_name')]",
"location": "[parameters('location')]",
"sku": {
"name": "Premium",
"tier": "Premium",
"capacity": 1
},
"identity": {
"type": "SystemAssigned"
},
"properties": {
"zoneRedundant": false
}
},
{
"type": "Microsoft.KeyVault/vaults",
"apiVersion": "[variables('kv_version')]",
"name": "[variables('kv_name')]",
"location": "[parameters('location')]",
"dependsOn": [
"[variables('sb_name')]"
],
"properties": {
"sku": {
"family": "A",
"name": "Standard"
},
"tenantId": "[parameters('tenantId')]",
"accessPolicies": [
{
"tenantId": "[reference(variables('sb_name'), variables('sb_version'), 'Full').identity.tenantId]",
"objectId": "[reference(variables('sb_name'), variables('sb_version'), 'Full').identity.principalId]",
"permissions": {
"keys": [
"get",
"wrapKey",
"unwrapKey"
]
}
}
],
// Both must be enabled to encrypt Service Bus at rest.
"enableSoftDelete": true,
"enablePurgeProtection": true
}
},
{
"type": "Microsoft.KeyVault/vaults/keys",
"apiVersion": "[variables('kv_version')]",
"name": "[concat(variables('kv_name'), '/', variables('sb_keyname'))]",
"location": "[parameters('location')]",
"dependsOn": [
"[variables('kv_name')]"
],
"properties": {
"kty": "RSA",
"keySize": 2048,
"keyOps": [
"wrapKey",
"unwrapKey"
],
"attributes": {
"enabled": true
}
}
},
{
"type": "Microsoft.Resources/deployments",
"apiVersion": "2020-10-01",
"name": "sb_deployment",
"dependsOn": [
"[resourceId('Microsoft.KeyVault/vaults/keys', variables('kv_name'), variables('sb_keyname'))]"
],
"properties": {
"mode": "Incremental",
"template": {
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"resources": [
{
"type": "Microsoft.ServiceBus/namespaces",
"apiVersion": "[variables('sb_version')]",
"name": "[variables('sb_name')]",
"location": "[parameters('location')]",
"sku": {
"name": "Premium",
"tier": "Premium",
"capacity": 1
},
"identity": {
"type": "SystemAssigned"
},
"properties": {
"zoneRedundant": false,
"encryption": {
"keySource": "Microsoft.KeyVault",
"keyVaultProperties": [
{
// Ideally should specify a specific version, but no ARM template function to get this currently.
"keyVaultUri": "[reference(variables('kv_name')).vaultUri]",
"keyName": "[variables('sb_keyname')]"
}
]
}
}
}
]
}
}
}
]
}
使用Azure CLI来部署它:
az group create -g rg-example -l westus2
az deployment group create -g rg-example -f template.json --parameters name=example
关于azure-devops - 如何创建利用 Key Vault 的幂等、可重新部署的 ARM 模板?循环依赖存在问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66803847/