6

I'm trying to assign the role "Storage Blob Data Contributor (Preview)" to a specific storage container via arm template. But I just can't figure out the correct syntax.

This is what I have:

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "principalId": {
            "type": "string",
            "metadata": {
                "description": "The principal to assign the role to"
            }
        },
        "builtInRoleType": {
            "type": "string",
            "allowedValues": [
                "Contributor",
                "Reader",
                "StorageBlobDataContributor"
            ],
            "metadata": {
                "description": "Built-in role to assign"
            }
        }
    },
    "variables": {
        "apiVersion": "2017-05-01",
        "Owner": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635')]",
        "Contributor": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', 'b24988ac-6180-42a0-ab88-20f7382dd24c')]",
        "Reader": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]",
        "StorageBlobDataContributor": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')]",
        "TestVariable": "[concat('STORAGEACCOUNTNAME','/Microsoft.Authorization/',guid(subscription().subscriptionId))]"
    },
    "resources": [
        {
            "type": "Microsoft.Storage/storageAccounts/providers/roleAssignments",
            "apiVersion": "[variables('apiVersion')]",
            "name": "[variables('TestVariable')]",
            "properties": {
                "roleDefinitionId": "[variables('Reader')]",
                "principalId": "[parameters('principalId')]"
            }
        },
        {
            "type": "Microsoft.Storage/storageAccounts/STORAGEACCOUNTNAME/blobServices/containers/blobCONTAINERNAME/providers/Microsoft.Authorization/roleAssignments",
            "apiVersion": "[variables('apiVersion')]",
            "name": "STORAGEACCOUNTNAME/blobServices/containers/default/blobCONTAINERNAME/Microsoft.Authorization/NEW-GUID",
            "properties": {
                "roleDefinitionId": "[variables('StorageBlobDataContributor')]",
                "principalId": "[parameters('principalId')]"
            }
        }
    ],
    "outputs": {}
}

I can attach the reader role to the storage account itself succesfully. But for the container I get the following error:

    new-AzResourceGroupDeployment : 09:21:24 - Error: Code=InvalidTemplate; Message=Deployment template validation failed: 'The template resource
'STORAGEACCOUNTNAME/blobServices/containers/CONTAINERNAME/Microsoft.Authorization/GUID' for type
'Microsoft.Storage/storageAccounts/STORAGEACCOUNTNAME/blobServices/default/containers/CONTAINERNAME/providers/Microsoft.Authorization/roleAssignments' at line '44' and column '9' has incorrect
segment lengths. A nested resource type must have identical number of segments as its resource name. A root resource type must have segment length one greater than its resource name. Please see
https://aka.ms/arm-template/#resources for usage details.'.

I have tried so many ways trying to attach the role, that I out of idea's. Can someone help me?

Erik
  • 121
  • 1
  • 6

3 Answers3

6

you need to construct something like this:

resourceId/Microsoft.Authorization/roleAssignments/NEW-GUID

and resourceId is normally being constructed as

type: provider/namespace
name: name

provider/namespace/name

for example, for subnet it would be (notice it takes 1 segment from each line in turn, except for the first one, first one is always 2 segments):

type: microsoft.network/virtualnetworks/subnets
name: vnetName/subnetName

microsoft.network/virtualnetworks/vnetName/subnets/subnetName

if that is even possible it would look like something like this:

"type": "Microsoft.Storage/storageAccounts/blobServices/containers/providers/roleAssignments",
"name": "STORAGEACCOUNTNAME/default/CONTAINERNAME/Microsoft.Authorization/NEW-GUID"

Microsoft.Storage/storageAccounts/STORAGEACCOUNTNAME/containers/CONTAINERNAME/providers/Microsoft.Authorization/roleAssignments/NEW-GUID
4c74356b41
  • 69,186
  • 6
  • 100
  • 141
5

Made some little adjustments:

"type": "Microsoft.Storage/storageAccounts/blobServices/containers/providers/roleAssignments",
"name": "STORAGEACCOUNTNAME/default/CONTAINERNAME/Microsoft.Authorization/NEW-GUID"

This way I can assign roles on the container itself. Thanks 4c74356b41 for pointing me in the right direction

Erik
  • 121
  • 1
  • 6
3

Using Erik's answer above (which I've up-voted of course, thx Erik!), I was able to solve the similar issue for RBAC permissions on a Queue of a Storage Account using ARM templates.

Here is an example ARM template for adding Sender role to a single Queue of a Storage Account...

<..snip..>
"parameters": {
    "PrincipalId": {
        "type": "string",
        "minLength": 36,
        "maxLength": 36
    }
},
"variables": {
    "SubscriptionId": "[concat('/subscriptions/', subscription().subscriptionId)]",
    "RoleDefinitions": "[concat(variables('SubscriptionId'), '/providers/Microsoft.Authorization/roleDefinitions/')]",
    "QueueSenderRole": "c6a89b2d-59bc-44d0-9896-0f6e12d7b80a"
},
"resources": [        
    {
        "type": "Microsoft.Storage/storageAccounts/queueServices/queues/providers/roleAssignments",
        "name": "mystorageaccount/default/myqueue/Microsoft.Authorization/00000000-1234-0000-5678-000000000000", // NB example only; pick an idempotent but unique value
        "apiVersion": "2018-09-01-preview",
        "properties": {
            "roleDefinitionId": "[concat(variables('RoleDefinitions'), variables('QueueSenderRole'))]",
            "principalId": "[parameters('PrincipalId')]"
        }
    }
]
Peter
  • 971
  • 11
  • 12
  • Thanks a bunch Peter, this worked like a charm. However I noticed that if I re-run the deployment I get an error that I can't "update" the role assignment. Naturally I'm not trying to "update" it. If it is an incremental ARM deployment it should be tolerant of resources which already exist and gracefully continue. Not with role assignments I guess. Did you run across this issue; if so, how did you deal with it? – JohnKoz Feb 14 '21 at 20:41
  • Hi John, I think I did, yes. I think the key is getting the name right so that it is the same value for the same role assignment. So in my real-world version, I build the name using ARM functions concat and guid : ` "name": "[concat('mystorageaccount','/default/','myqueue','/Microsoft.Authorization/',guid( ))]", // NB example only; pick an idempotent but unique value ` Those unique pieces for me were storage account, queue name (what permission is being granted to), the role id, and also principal id. – Peter Feb 15 '21 at 08:31
  • Thanks Peter. Strange, i kept my guid (and entire name) the same and it still gave me the update error. Ok, let me retrace my steps again. By the way, seems there is a new syntax using "Scope", have you tried using that? – JohnKoz Feb 15 '21 at 23:25