1
votes

I want to deploy AKS cluster with User Assigned Identity. I have created the User assigned managed Identity before the cluster creation and pass this as a parameter. However, When I use the same in the ARM template, below is the observation:

  1. If the 'Identity" is 'SystemAssigned' -> The deployment will be successful
  2. If the 'Identity is 'UserAssigned' and provide the Resource ID for UserAssignedIdentity, the deployment fails telling that the 'servicePrincipalProfile' is not provided.
  3. If the 'Identity is 'UserAssigned' and 'servicePrincipalProfile' is provided ->Deployment is successful, but when I query the cluster for its Identity, the UserAssignedIdentity details are blank.

ARM Template reference: https://docs.microsoft.com/en-us/azure/templates/microsoft.containerservice/managedclusters#ManagedClusterServicePrincipalProfile

Template part that i am updating:

"identity": {
        "principalId": null,
        "tenantId": null,
        "type": "UserAssigned",
        "userAssignedIdentities": {
          "[parameters('userAssignedIdentitiesResourceID')]": {
            "clientId": "[parameters('userAssignedIdentitiesClientID')]",
            "principalId": "[parameters('userAssignedIdentitiesPrincipalID')]"
          }
        }
      }

Update: I tried setting the User MSI via REST API after creating the AKS cluster (with SystemAssignedIdentity), but, it is not getting updated. I can still see the cluster identity as 'SystemAssignedIdentity'.

(Note, 'Invoke-CoeRestMethod' is a custom wrapper function that calls the Invoke-RestMethod. Wrapper func used to cache the bearer token etc.,)

$Body = @"
                {"location": "west europe",
                    "identity": {
        "principalId": null,
        "tenantId": null,
        "type": "UserAssigned",
        "userAssignedIdentities": {
          "/subscriptions/7e7f55d3-f30a-4bfd-a6be-1c59594b8592/resourcegroups/ITQIG-eu-rsv-manjug-dev/providers/Microsoft.ManagedIdentity/userAssignedIdentities/manjugtestmsi": {}
        }
      }
                      
                           }
"@

$Uri = ("https://management.azure.com/subscriptions/7e7f55d3-f30a-4bfd-a6be-1c59594b8592/resourceGroups/ITQIG-eu-rsv-manjug-dev/providers/Microsoft.ContainerService/managedClusters/ITQIG-eu-manjug-aks-dev?api-version=2020-09-01")
Invoke-CoeRestMethod -Method Put -Uri $Uri -Body $Body

Template used for AKS deployment:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.1",
  "variables": {
    "copy": [
      {
        "name": "create-mi-dict",
        "count": 1,
        "input": {
          "[resourceId('7e7f55d3-f30a-4bf-a6be-1c594b8592', 'ITQIG-eu-rsv-manjug-dev','Microsoft.ManagedIdentity/userAssignedIdentities', 'manjugtestmsi')]": {}
        }
      }
    ]
  },
  "parameters": {
    "clusterName": {
      "type": "string",
      "defaultValue": "aks101cluster",
      "metadata": {
        "description": "The name of the Managed Cluster resource."
      }
    },
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]",
      "metadata": {
        "description": "The location of the Managed Cluster resource."
      }
    },
    "userAssignedIdentitiesResourceID": {
      "type": "string",
      "metadata": {
        "description": "Resource ID of the User Assigned Identity."
      }
    },
    "userAssignedIdentitiesClientID": {
      "type": "string",
      "metadata": {
        "description": "Client ID of the User Assigned Identity."
      }
    },
    "userAssignedIdentitiesPrincipalID": {
      "type": "string",
      "metadata": {
        "description": "Principal ID of the User Assigned Identity."
      }
    },
    "dnsPrefix": {
      "type": "string",
      "defaultValue": "aks-coe-eu-manjug-dev-dns",
      "metadata": {
        "description": "Optional DNS prefix to use with hosted Kubernetes API server FQDN."
      }
    },
    "osDiskSizeGB": {
      "type": "int",
      "defaultValue": 0,
      "minValue": 0,
      "maxValue": 1023,
      "metadata": {
        "description": "Disk size (in GB) to provision for each of the agent pool nodes. This value ranges from 0 to 1023. Specifying 0 will apply the default disk size for that agentVMSize."
      }
    },
    "agentCount": {
      "type": "int",
      "defaultValue": 1,
      "minValue": 1,
      "maxValue": 50,
      "metadata": {
        "description": "The number of nodes for the cluster."
      }
    },
    "agentVMSize": {
      "type": "string",
      "defaultValue": "Standard_DS2_v2",
      "metadata": {
        "description": "The size of the Virtual Machine."
      }
    },
    "linuxAdminUsername": {
      "type": "string",
      "metadata": {
        "description": "User name for the Linux Virtual Machines."
      }
    },
    "sshRSAPublicKey": {
      "type": "string",
      "metadata": {
        "description": "Configure all linux machines with the SSH RSA public key string. Your key should include three parts, for example 'ssh-rsa AAAAB...snip...UcyupgH azureuser@linuxvm'"
      }
    },
    "osType": {
      "type": "string",
      "defaultValue": "Linux",
      "allowedValues": [
        "Linux"
      ],
      "metadata": {
        "description": "The type of operating system."
      }
    }
  },

  "resources": [
    {
      "type": "Microsoft.ContainerService/managedClusters",
      "apiVersion": "2020-03-01",
      "name": "[parameters('clusterName')]",
      "location": "[parameters('location')]",
      "properties": {
        "dnsPrefix": "[parameters('dnsPrefix')]",
        "agentPoolProfiles": [
          {
            "name": "agentpool",
            "maxPods": 110,
            "osDiskSizeGB": "[parameters('osDiskSizeGB')]",
            "type": "VirtualMachineScaleSets",
            "mode": "System",
            "count": "[parameters('agentCount')]",
            "vmSize": "[parameters('agentVMSize')]",
            "osType": "[parameters('osType')]",
            "storageProfile": "ManagedDisks",
            "availabilityZones": [
              "1",
              "2",
              "3"
            ]
          }
        ],
        "networkProfile": {
          "networkPlugin": "kubenet",
          "loadBalancerSku": "Standard"
        },
        "addonProfiles": {
          "KubeDashboard": {
            "enabled": false
          },
          "azurepolicy": {
            "enabled": true,
            "config": {
              "version": "v2"
            }
          },
          "httpApplicationRouting": {
            "enabled": true
          }
        },
        "linuxProfile": {
          "adminUsername": "[parameters('linuxAdminUsername')]",
          "ssh": {
            "publicKeys": [
              {
                "keyData": "[parameters('sshRSAPublicKey')]"
              }
            ]
          }
        },
        "enableRBAC": true,
        "aadProfile": {
          "managed": true,
          "enableAzureRBAC": true,
          "adminGroupObjectIDs": [
            "1f2a3b42-d409-4e5a-a530-cb899f033293"
          ]
        },
        "apiServerAccessProfile": {
          "enablePrivateCluster": false
        }
      },
      "identity": {
        "type": "UserAssigned",
        "userAssignedIdentities": "[first(variables('create-mi-dict'))]"
      }
    }
  ]
}
1
Try to change"principalId" to "objectId"?Nancy Xiong
I tried by entirely skipping the 'clientid' and 'principalid', but still not works. Tried skipping because MS docs specifies just to provide the User MSI Resource ID. docs.microsoft.com/en-us/azure/templates/…Manjunath Rao

1 Answers

2
votes

EDIT:

as of 12th July 2021 this is possible to do "normally":

"identity": {
    "type": "UserAssigned",
    "userAssignedIdentities": {
        "[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'xxx'))]": {}
    }
}
}

as far as I can tell that is correct (almost), but you cannot use parameters for property names in arm templates, so you'd have to pre-render the template.

"identity": {
    "type": "UserAssigned",
    "userAssignedIdentities": {
        "/subscriptions/xxx/resourcegroups/yyyy/providers/Microsoft.ManagedIdentity/userAssignedIdentities/zzz": {}
    }
}

now that i think about it, you might get away with a copy function hack. I dont think there's any other way around it.

Example:

{
    "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "variables": {
        "copy": [
            {
                "name": "create-mi-dict",
                "count": 1,
                "input": {
                    "[resourceId('58aac3e3-e3c7-41e4-8539-5fd1893c46e9', 'rg-name','Microsoft.ManagedIdentity/userAssignedIdentities', 'mi-name')]": {}
                }
            }
        ]
    },
    "resources": [],
    "outputs": {
        "output1": {
            "type": "object",
            "value": "[first(variables('create-mi-dict'))]"
        }
    }
}

Edit: you can use it like so:

"identity": {
    "type": "UserAssigned",
    "userAssignedIdentities": "[first(variables('create-mi-dict'))]"
}