You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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循环,因此需要将联合凭据作为顶级资源,通过双重迭代计算来实现批量创建:

  1. 计算总循环次数:UMI数量 × OIDC提供商数量
  2. 使用div和mod函数拆分当前索引,分别对应UMI的索引和OIDC提供商的索引
  3. 正确设置联合凭据的名称格式:[UMI名称]/[联合凭据名称]
  4. 配置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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 18:54:57