Search code examples
azureazure-resource-managerazure-rm-template

Using ARM templates to create multiple federated credentials for UMIs


I have a list of UMIs that I am creating with the Microsoft.ManagedIdentity/userAssignedIdentities ARM template resource. Let's say I have ten of these in my list.

For each UMI, I want to create federated credentials to allow tokens from several OIDC providers.

I planned to use resource iteration, but it doesn't appear I can nest the fed creds child resource when using an iterator.

So my question is: How do I either a) create federated credentials that allow tokens from multiple OIDC providers or b) write an ARM template that can do a nested for loop? i.e. "for each UMI create x fed creds"

Here's the template I started with

{
  "$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]"
          }
        }
      ]
    }
  ]
}

Here's the error that gave me

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

Here's the template I am stuck with now

{
  "$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'))]"
      }
    }
  ]
}

Solution

  • Using the dependsOn property, you can provision many new federated identity credentials consecutively.

    I tried below code to create three new federated identity credentials progressively on a user-assigned managed identity.

    {
      "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
      "contentVersion": "1.0.0.0",
      "parameters": {
        "userAssignedIdentities_parent": {
          "defaultValue": "parent_uami",
          "type": "String"
        }
      },
      "variables": {},
      "resources": [
        {
          "type": "Microsoft.ManagedIdentity/userAssignedIdentities",
          "apiVersion": "2022-01-31-preview",
          "name": "[parameters('userAssignedIdentities_parent')]",
          "location": "eastus"
        },
        {
          "type": "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials",
          "apiVersion": "2022-01-31-preview",
          "name": "[concat(parameters('userAssignedIdentities_parent'), '/fic01')]",
          "dependsOn": [
            "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('userAssignedIdentities_parent'))]"
          ],
          "properties": {
            "issuer": "https://kubernetes-oauth.azure.com",
            "subject": "fic01",
            "audiences": [
              "api://AzureADTokenExchange"
            ]
          }
        },
        {
          "type": "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials",
          "apiVersion": "2022-01-31-preview",
          "name": "[concat(parameters('userAssignedIdentities_parent'), '/fic02')]",
          "dependsOn": [
            "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('userAssignedIdentities_parent'))]",
            "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials', parameters('userAssignedIdentities_parent'), 'fic01')]"
          ],
          "properties": {
            "issuer": "https://kubernetes-oauth.azure.com",
            "subject": "fic02",
            "audiences": [
              "api://AzureADTokenExchange"
            ]
          }
        },
        {
          "type": "Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials",
          "apiVersion": "2022-01-31-preview",
          "name": "[concat(parameters('userAssignedIdentities_parent'), '/fic03')]",
          "dependsOn": [
            "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', parameters('userAssignedIdentities_parent'))]",
            "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials', parameters('userAssignedIdentities_parent'), 'fic02')]"
          ],
          "properties": {
            "issuer": "https://kubernetes-oauth.azure.com",
            "subject": "fic03",
            "audiences": [
              "api://AzureADTokenExchange"
            ]
          }
        }
      ]
    }
    

    Deployment succeeded:

    enter image description here

    enter image description here