如何用ARM模板为多个UMI创建联合凭据?
ARM模板实现批量创建用户分配托管标识及对应多OIDC联合凭据
我通过ARM模板的Microsoft.ManagedIdentity/userAssignedIdentities资源创建了一组UMI(用户分配托管标识),假设有10个这类标识。需要为每个UMI创建联合凭据,以允许来自多个OIDC提供商的令牌。
原本计划使用资源迭代功能,但发现迭代器无法嵌套联合凭据子资源,因此需要解决以下任一问题:
- a) 创建支持多个OIDC提供商令牌的联合凭据;
- b) 编写可实现嵌套循环的ARM模板,即“为每个UMI创建x个联合凭据”。
最初的模板及错误
最初尝试的模板:
{ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "managedIdNames": { "type": "array" } }, "resources": [ { "type": "Microsoft.ManagedIdentity/userAssignedIdentities", "copy": { "name": "managedIdentityIterator", "count": "[length(parameters('managedIdNames'))]" }, "apiVersion": "2023-01-31", "name": "[parameters('managedIdNames')[copyIndex()].name]", "location": "[resourceGroup().location]", "resources": [ { "type": "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials", "copy": { "name": "fedCredsIterator", "count": "[length(parameters('oidcProviders'))]" }, "apiVersion": "2023-01-31", "name": "string", "properties": { "audiences": [ "api://AzureADTokenExchange" ], "issuer": "[parameters('oidcProviders')[copyIndex()].url]", "subject": "system:serviceaccount:[parameters('k8sNamespace')]:[parameters('managedIdNames')[copyIndex()].name]" } } ] } ] }
返回错误:
Code: InvalidSchema Message: The template is invalid. Error: 'The template resource 'string' at line '22' column '19' is not valid. Copying nested resources is not supported. Please see https://aka.ms/arm-multiple-instances for usage details.' 2023-10-23 14:10:02,593 - MainProcess - ERROR - (azurehelper:upload_all_templates_ts:1677) - Template upload failed - Exception raised in a thread
当前卡住的模板
{ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "managedIdNames": { "type": "array" } }, "resources": [ { "type": "Microsoft.ManagedIdentity/userAssignedIdentities", "name": "[parameters('managedIdNames')[copyIndex()].name]", "apiVersion": "2023-01-31", "location": "[resourceGroup().location]", "copy": { "name": "managedIdentityIterator", "count": "[length(parameters('managedIdNames'))]" } }, { "type": "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials", "name": "[format('???/fedCreds{0}', copyIndex())]", "apiVersion": "2023-01-31", "properties": { "audiences": [ "api://AzureADTokenExchange" ], "issuer": "[parameters('oidcProviders')[copyIndex()].url]", "subject": "system:serviceaccount:[parameters('k8sNamespace')]:[parameters('managedIdNames')[???].name]" }, "dependsOn": [ "???" ], "copy": { "name": "fedCredsIterator", "count": "[length(parameters('oidcProviders'))]" } } ] }
解决方案
关于问题a:单个联合凭据无法支持多个OIDC提供商
每个联合凭据资源只能关联一个OIDC issuer,这是Azure的设计限制。因此必须为每个OIDC提供商单独创建对应的联合凭据,无法通过单个凭据实现多提供商支持。
关于问题b:实现“为每个UMI创建x个联合凭据”的ARM模板
ARM模板不支持在嵌套子资源中使用copy循环,因此需要将联合凭据作为顶级资源,通过双重迭代计算来实现批量创建:
- 计算总循环次数:
UMI数量 × OIDC提供商数量 - 使用
div和mod函数拆分当前索引,分别对应UMI的索引和OIDC提供商的索引 - 正确设置联合凭据的名称格式:
[UMI名称]/[联合凭据名称] - 配置
dependsOn确保UMI创建完成后再生成联合凭据
完整模板示例:
{ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "managedIdNames": { "type": "array", "metadata": { "description": "数组,包含每个UMI的名称对象,格式如[{\"name\": \"umi-1\"}, {\"name\": \"umi-2\"}]" } }, "oidcProviders": { "type": "array", "metadata": { "description": "数组,包含每个OIDC提供商的信息,格式如[{\"url\": \"https://provider1.example.com\", \"credName\": \"fed-cred-provider1\"}, {\"url\": \"https://provider2.example.com\", \"credName\": \"fed-cred-provider2\"}]" } }, "k8sNamespace": { "type": "string", "metadata": { "description": "K8s命名空间,用于生成subject值" } } }, "variables": { "totalIterations": "[mul(length(parameters('managedIdNames')), length(parameters('oidcProviders')))]" }, "resources": [ // 批量创建UMI { "type": "Microsoft.ManagedIdentity/userAssignedIdentities", "apiVersion": "2023-01-31", "name": "[parameters('managedIdNames')[copyIndex()].name]", "location": "[resourceGroup().location]", "copy": { "name": "managedIdentityIterator", "count": "[length(parameters('managedIdNames'))]" } }, // 批量创建联合凭据:每个UMI对应所有OIDC提供商 { "type": "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials", "apiVersion": "2023-01-31", "name": "[concat(parameters('managedIdNames')[div(copyIndex(), length(parameters('oidcProviders')))].name, '/', parameters('oidcProviders')[mod(copyIndex(), length(parameters('oidcProviders')))].credName)]", "properties": { "audiences": [ "api://AzureADTokenExchange" ], "issuer": "[parameters('oidcProviders')[mod(copyIndex(), length(parameters('oidcProviders')))].url]", "subject": "[concat('system:serviceaccount:', parameters('k8sNamespace'), ':', parameters('managedIdNames')[div(copyIndex(), length(parameters('oidcProviders')))].name)]" }, "dependsOn": [ "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('managedIdNames')[div(copyIndex(), length(parameters('oidcProviders')))].name)]" ], "copy": { "name": "federatedCredentialsIterator", "count": "[variables('totalIterations')]" } } ] }
关键逻辑说明
variables('totalIterations'):计算需要创建的联合凭据总数量,即UMI个数乘以OIDC提供商个数div(copyIndex(), length(parameters('oidcProviders'))):通过整数除法,从当前循环索引中得到对应的UMI的索引mod(copyIndex(), length(parameters('oidcProviders'))):通过取余运算,得到当前UMI对应的OIDC提供商的索引dependsOn:通过resourceId动态关联对应的UMI资源,确保创建顺序正确
内容的提问来源于stack exchange,提问作者matthiasdenu
相关产品推荐
相关产品推荐

