6

In my current project I'm working with pre-created App Registration Service Principals in Azure AD. I'm using an ARM template to create a StorageV2 account plus some blob containers, then create a roleAssignment giving Storage Blob Contributor rights to one of the Service Principals. The relevant section of the ARM template is at the end of this post.

What I've found is that if I take the ObjectId of a regular AD user, such as myself or my colleague, and set that as PrincipalId, the script runs correctly. However, I can't get this to work with a Service Principal.

If I use the Service Principal's ObjectId, then I get the following error:

Deployment failed. Correlation ID: 40e0c146-165a-47c0-b022-ac04781d8194. {
  "error": {
    "code": "PrincipalTypeNotSupported",
    "message": "Principals of type Application cannot validly be used in role assignments."
  }
}

Having spotted some suggestions for Azure Powershell users that I should use Application (Client) Id instead, I tried that, but get the following error (Guids redacted):

Deployment failed. Correlation ID: 5c725a51-230a-4d85-bb61-b2f4cdf849ff. {
  "error": {
    "code": "PrincipalNotFound",
    "message": "Principal 9f****30 does not exist in the directory db****75."
  }
}

So the ObjectId it can find but not use, and the ClientId it can't find.

I have found that if I use Azure Powershell and use the New-AzureRmRoleAssignment command, I can reproduce the PrincipalTypeNotSupported error by providing the Service Principal's ObjectId to the -ObjectId switch. However, that command also has a -ServicePrincipalName switch as an alternative, and if I give that the Service Principal's ClientId, it works!

Is there any equivalent of -ServicePrincipalName for the ARM templates, and if not, is there any other way to achieve this? I can use Azure Powershell as a workaround, but it's messier than I'd like.

If this is a feature gap, where's the best place to report it?

Relevant section of ARM template follows:

"resources": [
    {
        "name": "[variables('storageAccountName')]",
        "type": "Microsoft.Storage/storageAccounts",
        "location": "[resourceGroup().location]",
        "apiVersion": "2018-07-01",
        "sku": {
            "name": "[parameters('storageAccountSku')]"
        },
        "dependsOn": [],
        "tags": {
            "displayName": "Storage Account"
        },
        "kind": "StorageV2",
        "properties": {
            "accessTier": "Hot",
            "supportsHttpsTrafficOnly": true,
            "networkAcls": {
                "bypass": "AzureServices",
                "virtualNetworkRules": [],
                "ipRules": [],
                "defaultAction": "Deny"
            }
        },
        "resources": [
            {
                "type": "blobServices/containers",
                "name": "[concat('default/', variables('myBlobContainerName'))]",
                "apiVersion": "2018-07-01",
                "dependsOn": [
                    "[variables('storageAccountName')]"
                ],
                "resources": [
                    {
                        "type": "Microsoft.Authorization/roleAssignments",
                        "name": "[variables('myRoleAssignmentGuid')]",
                        "apiVersion": "2018-07-01",
                        "properties": {
                            "roleDefinitionId": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/ba92f5b4-2d11-453d-a403-e96b0029c9fe')]",
                            "principalId": "[variables('myPrincipalId')]"
                        },
                        "dependsOn": [
                            "[concat('Microsoft.Storage/storageAccounts/', variables('storageAccountName'), '/blobServices/default/containers/', variables('myBlobContainerName'))]"
                        ]
                    }
                ]
            }
        ]
    }
]
Stringfellow
  • 2,788
  • 2
  • 21
  • 36
Alexlotl
  • 151
  • 1
  • 9
  • you can try using service principal guid instead of application guid. – 4c74356b41 Jun 12 '19 at 15:52
  • 1
    @4c74356b41 Which GUID is that? The App Registrations screen in the portal shows three for each SP - `Application (client) ID` (tried it, doesn't work), `Directory (tenant) ID` (not relevant) and `Object ID` (tried it, doesn't work). I found the documentation particularly unhelpful here, just asing for "Principal ID", which is a phrase that doesn't seem to be used anywhere else. – Alexlotl Jun 12 '19 at 15:57
  • application should have a service principal you'd need to find that guid. you can do that on the portal, it would say something like `managed application in local directory`. – 4c74356b41 Jun 12 '19 at 16:08
  • @4c74356b41 It's not clear what you mean here. These are pre-existing, application specific Service Principals created under Azure Active Directory -> App Registrations. Applications then use a `AzureServicesAuthConnectionString` setting to identify themselves to other services. We're not using Managed Identities, either System or User. As per my last comment, the service principals under App Registrations have three guids, none of which are suitable for creating a roleAssignment via ARM template. None of these is called Service Principal ID/GUID. – Alexlotl Jun 13 '19 at 11:26
  • like i said, application have service principals and you need to use these to assign permissions using arm template. powershell allows you to use application guid because it's smart enough to find the service principal assigned to the app and use that guid – 4c74356b41 Jun 13 '19 at 11:28

1 Answers1

9

Finally solved this one thanks in part to the pointers from @4c74356b41.

When an Application Registration object is created, an identically named object is also created under Enterprise Applications. This has the same ApplicationId, but a different ObjectId, and it's the ObjectId of this Enterprise Application object that our ARM script needs.

You can find this object in the portal by going to the Application Registration entry, then clicking on the link after Managed application in...

Screenshot of App Registration with Link Screenshot of App Registration with Link

Once you're on the corresponding Enterprise Application object, you can get the ObjectId from Properties, and use this the value for principalId in the ARM template.

At the time of writing, the Microsoft Documentation is a bit vague on this, with the terms Application and Service Principal seemingly overloaded. This article says that when you register an application you get an Application object and a Service Principal object, but doesn't use the phrase Enterprise Application once, or refer to App Registration objects per se, so it's unclear which is which.

I'm assuming Application == Application Registration and Service Principal == Enterprise Application. This SO post would seem to suggest this is the case, as would the solution above.

John
  • 1,837
  • 1
  • 8
  • 12
Alexlotl
  • 151
  • 1
  • 9
  • As an addition to this, you can get the correct id if you use the azure cli by running `az ad sa list --display-name my-application-name` and looking for the objectId. – tzrlk Jun 25 '19 at 03:10