Background Information
I have the following arm template that assigns a RBAC to a managed ID;
{
"$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": [
"Owner",
"Contributor",
"Reader",
"StorageQueueDataContributor",
"StorageTableDataContributor"
],
"metadata": {
"description": "Built-in role to assign"
}
},
"roleNameGuid": {
"type": "string",
"defaultValue": "[newGuid()]",
"metadata": {
"description": "A new GUID used to identify the role assignment"
}
}
},
"variables": {
"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')]",
"StorageQueueDataContributor": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/','974c5e8b-45b9-4653-ba55-5f855dd0fb88')]",
"StorageTableDataContributor": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/','0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3')]"
},
"resources": [
{
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2018-09-01-preview",
"name": "[parameters('roleNameGuid')]",
"properties": {
"roleDefinitionId": "[variables(parameters('builtInRoleType'))]",
"principalId": "[parameters('principalId')]"
}
}
]
}
and I'm calling it from a powershell script like this:
az deployment group create `
--resource-group $RESOURCE_GROUP `
--template-file "./rbac-role.json" `
--parameters principalId=$objectid builtInRoleType=StorageTableDataContributor roleNameGuid=0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3
So far so good. But now I'd like to be able to assign mutiple RBAC roles instead of just one. I tried to call it twice, once per role type but that fails with an error:
{"status":"Failed","error":{"code":"DeploymentFailed","message":"At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/DeployOperations for usage details.","details":[{"code":"BadRequest","message":"{\r\n \"error\": {\r\n \"code\": \"RoleAssignmentUpdateNotPermitted\",\r\n \"message\": \"Tenant ID, application ID, principal ID, and scope are not allowed to be updated.\"\r\n }\r\n}"}]}}
What I've Tried So far
I've tried to pass arrays as parameters. In reading the docs, it seems that ARM Template parameters can accept arrays.
So I've updated my powershell code to look like this:
$RoleTypeArray = #(
'StorageQueueDataContributor'
'StorageTableDataContributor'
)
$RoleGuidArray = #(
'974c5e8b-45b9-4653-ba55-5f855dd0fb88'
'0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3'
)
az deployment group create `
--resource-group $RESOURCE_GROUP `
--template-file "./rbac-role.json" `
--parameters principalId=$objectid builtInRoleType=$RoleTypeArray roleNameGuid=$RoleGuidArray
And the template like this:
{
"$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": "array",
"defaultValue": [
"Owner",
"Contributor",
"Reader",
"StorageQueueDataContributor",
"StorageTableDataContributor"
],
"metadata": {
"description": "Built-in role to assign"
}
},
"roleNameGuid": {
"type": "array",
"defaultValue": [
"8e3af657-a8ff-443c-a75c-2fe8c4bcb635",
"b24988ac-6180-42a0-ab88-20f7382dd24c",
"acdd72a7-3385-48ef-bd42-f606fba81ae7",
"974c5e8b-45b9-4653-ba55-5f855dd0fb88",
"0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3"
],
"metadata": {
"description": "A new GUID used to identify the role assignment"
}
}
},
"variables": {
"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')]",
"StorageQueueDataContributor": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/','974c5e8b-45b9-4653-ba55-5f855dd0fb88')]",
"StorageTableDataContributor": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/','0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3')]"
},
"resources": [
{
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2018-09-01-preview",
"name": "[parameters('roleNameGuid')[0]]",
"properties": {
"roleDefinitionId": "[variables(parameters('builtInRoleType')[0])]",
"principalId": "[parameters('principalId')]"
}
}
]
}
For now, I've just hardcoded the index to 0 but if this is the right tree to bark up, I'll have to figure out how to loop? Or I can create the same section twice in the JSON ARM template file maybe - once for each of the two roles?
For now, the error I'm getting is:
Failed to parse JSON: StorageQueueDataContributor StorageTableDataContributor
Error detail: Expecting value: line 1 column 1 (char 0)
It's not clear to me at what point its dying.
Adding some debug statements but any tips would be appreciated.
EDIT 1
I've modified my ARM Template to look like this:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"principalId": {
"type": "string",
"metadata": {
"description": "The principal to assign the role to"
}
},
"builtInRoleType": {
"type": "array",
"defaultValue": [
"Owner",
"Contributor",
"Reader",
"StorageQueueDataContributor",
"StorageTableDataContributor"
],
"metadata": {
"description": "Built-in role to assign"
}
}
},
"variables": {
"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')]",
"StorageQueueDataContributor": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/','974c5e8b-45b9-4653-ba55-5f855dd0fb88')]",
"StorageTableDataContributor": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/','0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3')]"
},
"resources": [
{
"copy": {
"name": "roleAssignment",
"count": "[length(parameters('builtInRoleType'))]"
},
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2018-09-01-preview",
"name": "[guid(subscription().subscriptionId, resourceGroup().name, parameters('builtInRoleType')[copyIndex()], parameters('principalId'))]",
"properties": {
"roleDefinitionId": "[parameters('builtInRoleType')[copyIndex()]]",
"principalId": "[parameters('principalId')]"
}
}
]
}
This is how I'm calling it:
az deployment group create `
--resource-group $RESOURCE_GROUP_NAME `
--template-file "./rbac-role.json" `
--parameters `
principalId=$objectid `
builtInRoleType="['StorageQueueDataContributor', 'StorageTableDataContributor']"
But the error I'm getting is
{
"status": "Failed",
"error": {
"code": "BadRequestFormat",
"message": "The request was incorrectly formatted."
}
}
I think it could be related to the roleDefinitionID.
This is the second time I'm testing the refactored code. The first time through though, the roleDefinitionID still looked like this:
"roleDefinitionId": "[variables(parameters('builtInRoleType')[0])]",
"principalId": "[parameters('principalId')]"
And I ended up with the StorageQueueDataContributor role being assigned twice.
Multiple things here.
The role assignment name has to be unique. Once an assignment has been created you can't change it so you can't use the same guid otherwise it looks like you're trying to update the role assignment which is not allowed.
You can't use powershell array as input parameter. Using az cli, a valid array parameter would look like that:
az deployment group create `
--resource-group $RESOURCE_GROUP `
--template-file "./rbac-role.json" `
--parameters `
principalId=$objectid `
builtInRoleType="['StorageQueueDataContributor', 'StorageTableDataContributor']" `
roleNameGuid="['974c5e8b-45b9-4653-ba55-5f855dd0fb88', '0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3']"
To remove the need of generating unique role name, you could use the guid() function:
Creates a value in the format of a globally unique identifier based on the values provided as parameters.
So this will generate a unique string but you can run the same template multiple time, it will always be the same unique string:
"name": "[guid(subscription().subscriptionId, resourceGroup().name, parameters('builtInRoleType')[0]], parameters('principalId'))]",
If you want to create multiple assignment at the same time, you could use the copy() function:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"principalId": {
"type": "string"
},
"builtInRoleType": {
"type": "array",
"allowedValues":[
"Owner",
"Contributor",
"Reader",
"StorageQueueDataContributor",
"StorageTableDataContributor"
]
}
},
"variables": {
"Owner": "8e3af657-a8ff-443c-a75c-2fe8c4bcb635",
"Contributor": "'b24988ac-6180-42a0-ab88-20f7382dd24c",
"Reader": "acdd72a7-3385-48ef-bd42-f606fba81ae7",
"StorageQueueDataContributor": "974c5e8b-45b9-4653-ba55-5f855dd0fb88",
"StorageTableDataContributor": "0a9a7e1f-b9d0-4cc4-a60d-0319b160aaa3"
},
"resources": [
{
"copy": {
"name": "roleAssignment",
"count": "[length(parameters('builtInRoleType'))]"
},
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2020-04-01-preview",
"name": "[guid(subscription().subscriptionId, resourceGroup().name, parameters('builtInRoleType')[copyIndex()], parameters('principalId'))]",
"properties": {
"roleDefinitionId": "[subscriptionResourceId('Microsoft.Authorization/roleAssignments', variables(parameters('builtInRoleType')[copyIndex()]))]",
"principalId": "[parameters('principalId')]"
}
}
]
}
then you could just invoke the template like that:
az deployment group create `
--resource-group $RESOURCE_GROUP `
--template-file "./rbac-role.json" `
--parameters `
principalId=$objectid `
builtInRoleType="['StorageQueueDataContributor', 'StorageTableDataContributor']"
Related
I'm trying to execute a script in my template using Microsoft.Resources/deploymentScripts, but also I'm trying to declare de user assigned identity in the same template
{
"type": "Microsoft.ManagedIdentity/userAssignedIdentities",
"name": "scriptIdentity",
"apiVersion": "2018-11-30",
"location": "[resourceGroup().location]"
},
{
"type": "Microsoft.Resources/deploymentScripts",
"apiVersion": "2019-10-01-preview",
"name": "updateAppServiceConfigMountPointScript",
"dependsOn": [
"[resourceId('Microsoft.Web/sites/config', parameters('appservice_name'), 'web')]",
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'scriptIdentity')]",
"[resourceId('Microsoft.Storage/storageAccounts/blobServices', parameters('storageAccounts_name'), 'default')]"
],
"location": "[resourceGroup().location]",
"kind": "AzurePowerShell",
"identity": {
"type": "userAssigned",
"userAssignedIdentities": {
"principalId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'scriptIdentity'), '2019-08-01', 'full').identity.principalId]",
"clientId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'scriptIdentity'), '2019-08-01', 'full').identity.clientId]"
}
},
"properties": {
"environmentVariables": [
{
"name": "account_name",
"value": "[parameters('storageAccounts_name')]"
},
{
"name": "app_name",
"value": "[parameters('appservice_name')]"
},
{
"name": "resource_group_name",
"value": "[resourceGroup().name]"
}
],
"scriptContent": "$access_key = ((az storage account keys list --account-name $account_name) | ConvertFrom-JSON).value[0]; az webapp config storage-account add --name \\\"$app_name\\\" --resource-group \\\"$resource_group_name\\\" --custom-id \\\"frontend\\\" --storage-type \\\"AzureBlob\\\" --account-name \\\"stelckstorageaccount\\\" --share-name \\\"frontend\\\" --mount-path \\\"/home/site/wwwroot/frontend\\\" --access-key \\\"$access_key\\\"",
"timeout": "PT1M",
"cleanupPreference": "OnSuccess"
}
The template fails in this part:
"userAssignedIdentities": {
"principalId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'scriptIdentity'), '2019-08-01', 'full').identity.principalId]",
"clientId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'scriptIdentity'), '2019-08-01', 'full').identity.clientId]"
}
With the following error:
Deployment template validation failed: 'The template resource 'updateAppServiceConfigMountPointScript' at line '930' and column '9' is not valid: The template function 'reference' is not expected at this location. Please see https://aka.ms/arm-template-expressions for usage details.. Please see https://aka.ms/arm-template-expressions for usage details.'. (Code: InvalidTemplate)
How can I reference the assigned identity in the deploymentscript without the reference function?
RELATED: 'Microsoft.Web/sites/config' azureStorageAccounts fails due to 500 InternalError
Use the resourceId of the identity, e.g.
"userAssignedIdentities": {
"[resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', 'scriptIdentity')]": {}
}
See https://github.com/Azure/azure-quickstart-templates/blob/master/201-deployment-script-ssh-key-gen/azuredeploy.json for a full sample.
I had the same issue in a Bicep template, and struggled to figure out how to implement bmoore-msft's answer. While it's not an answer to the original question, I'll post it here in case others like me stumble across this page.
The trick was to use string interpolation to get the identity id on the left side of the colon
identity: {
type: 'UserAssigned'
userAssignedIdentities: {
'${scriptIdentity.id}': {}
}
}
So, I am trying to do the following with an ARM template:
Create a new User-assigned Managed Identity (my-managed-identity) in Resource Group my-rg
Assign my-managed-identity the Reader role for my-rg
Assign the role Managed Identity Operator to an AKS Service Principal (my-aks-sp) in my-managed-id
Here is my ARM template to do so:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"aksServicePrincipalObjectId": {
"type": "string",
"metadata": {
"description": "The Object Id for the AKS Cluster Service Principal"
}
},
},
"variables": {
"managedIdentityName": "my-managed-identity",
"readerRole": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]",
"managedIdOperatorRole": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', 'f1a07417-d97a-45cb-824c-7a7467783830')]"
},
"resources": [
{
"type": "Microsoft.ManagedIdentity/userAssignedIdentities",
"name": "[variables('managedIdentityName')]",
"apiVersion": "2018-11-30",
"location": "[resourceGroup().location]",
"resources": [
{
"type": "Microsoft.ManagedIdentity/userAssignedIdentities/providers/roleAssignments",
"name": "[concat(variables('managedIdentityName'), '/Microsoft.Authorization/', guid(parameters('aksServicePrincipalObjectId')))]",
"apiVersion": "2018-09-01-preview",
"location": "[resourceGroup().location]",
"dependsOn": [
"[concat('Microsoft.ManagedIdentity/userAssignedIdentities/', variables('managedIdentityName'))]"
],
"properties": {
"roleDefinitionId": "[variables('managedIdOperatorRole')]",
"principalId": "[parameters('aksServicePrincipalObjectId')]"
}
}
]
},
{
"type": "Microsoft.Authorization/roleAssignments",
"name": "[guid(variables('managedIdentityName'))]",
"apiVersion": "2018-09-01-preview",
"dependsOn": [
"[concat('Microsoft.ManagedIdentity/userAssignedIdentities/', variables('managedIdentityName'))]"
],
"properties": {
"roleDefinitionId": "[variables('readerRole')]",
"principalId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('managedIdentityName')),'2018-11-30').principalId]"
}
}
]
}
The weird thing is that sometimes this deployment doesn't work. I will more often than not get the error:
New-AzResourceGroupDeployment : 2:56:07 PM - Resource Microsoft.Authorization/roleAssignments 'd62bb9a1-bf0b-5a92-aca1-74beab087ee9' failed with message '{
"error": {
"code": "PrincipalNotFound",
"message": "Principal fad453d06bd042148411606b74525ed2 does not exist in the directory 936529098-bafa-4c91-b54f-f012cc11eeec."
}
}
Am I missing something here?
This documentation from Microsoft solved my problem.
Here is my complete template:
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"aksServicePrincipalObjectId": {
"type": "string",
"metadata": {
"description": "The Object Id for the AKS Cluster Service Principal"
}
},
},
"variables": {
"managedIdentityName": "my-managed-identity",
"readerRole": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', 'acdd72a7-3385-48ef-bd42-f606fba81ae7')]",
"managedIdOperatorRole": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', 'f1a07417-d97a-45cb-824c-7a7467783830')]"
},
"resources": [
{
"type": "Microsoft.ManagedIdentity/userAssignedIdentities",
"name": "[variables('managedIdentityName')]",
"apiVersion": "2018-11-30",
"location": "[resourceGroup().location]",
"resources": [
{
"type": "Microsoft.ManagedIdentity/userAssignedIdentities/providers/roleAssignments",
"name": "[concat(variables('managedIdentityName'), '/Microsoft.Authorization/', guid(parameters('aksServicePrincipalObjectId')))]",
"apiVersion": "2018-09-01-preview",
"location": "[resourceGroup().location]",
"dependsOn": [
"[concat('Microsoft.ManagedIdentity/userAssignedIdentities/', variables('managedIdentityName'))]"
],
"properties": {
"roleDefinitionId": "[variables('managedIdOperatorRole')]",
"principalId": "[parameters('aksServicePrincipalObjectId')]",
"principalType": "ServicePrincipal" // This solved my issue
}
}
]
},
{
"type": "Microsoft.Authorization/roleAssignments",
"name": "[guid(variables('managedIdentityName'))]",
"apiVersion": "2018-09-01-preview",
"dependsOn": [
"[concat('Microsoft.ManagedIdentity/userAssignedIdentities/', variables('managedIdentityName'))]"
],
"properties": {
"roleDefinitionId": "[variables('readerRole')]",
"principalId": "[reference(resourceId('Microsoft.ManagedIdentity/userAssignedIdentities', variables('managedIdentityName')),'2018-11-30').principalId]",
"scope": "[resourceGroup().id]" //This is what I added to get it to work!
}
}
]
}
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?
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
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
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')]"
}
}
]
I am facing following error "The request to create role assignment 'c*****************5' is not valid. Role assignment scope '/subscriptions/c**********************5/resourceGroups/MyResourceGroup/providers/Microsoft.Storage/storageAccounts/mystorageaccountname' must match the scope specified on the URI"
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"principalId": {
"type": "string",
"defaultValue": "My AD app ID",
"metadata": {
"description": "The principal to assign the role to"
}
},
"builtInRoleType": {
"type": "string",
"defaultValue": "Reader",
"allowedValues": [
"Owner",
"Contributor",
"Reader"
],
"metadata": {
"description": "Built-in role to assign"
}
},
"roleNameGuid": {
"type": "string",
"defaultValue": "random guid (i am getting this guid using following PS command "[System.Guid]::NewGuid().toString()")",
"metadata": {
"description": "A new GUID used to identify the role assignment"
}
}
},
"variables": {
"Owner": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', 'this is my ownerid')]",
"Contributor": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', 'this is my contributor id')]",
"Reader": "[concat('/subscriptions/', subscription().subscriptionId, '/providers/Microsoft.Authorization/roleDefinitions/', 'this is my reader id')]",
"scope": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/MyResourceGroup/providers/Microsoft.Storage/storageAccounts/', 'this is my storage account name')]"
},
"resources": [
{
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2014-10-01-preview",
"name": "[parameters('roleNameGuid')]",
"properties": {
"roleDefinitionId": "[variables(parameters('builtInRoleType'))]",
"principalId": "[parameters('principalId')]",
"scope": "[variables('scope')]"
}
}
]
}
This is a common problem for assigning a role assignment at a scope higher than the scope of the deployment. In your case the deployment is at the Resource Group level and you are trying to assign the scope at the Subscription level (which is higher level than Resource Group).
Solution: You will need to use Nested Template deployment.
To view a sample, check this documentation link and search for section "Assign Role at Scope" in this documentation: Create resources at Subscription level
I have tried
{
"apiVersion": "2016-07-01",
"name": "[concat(resourceGroup().name,'/Microsoft.Authorization/',variables('principalId'))]",
"type": "Microsoft.Authorization/roleAssignments",
"properties": {
"roleDefinitionId": "[variables('owner')]",
"principalId": "[parameters('msi').principalId]",
"scope": "[concat('/subscriptions/',subscription().subscriptionId,'/resourceGroups/',resourceGroup().name)]"
}
},
but it gives the following error
Deployment template validation failed: 'The template resource
'sf-gateway/Microsoft.Authorization/5e60879d-b9c0-4e11-9548-9d92ed244eef' for type 'Microsoft.Authorization/roleAssignments' at line '1' and
column '3432' 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.'. (Code: InvalidTemplate)
I dont fully understand whats needed to be changed.
I want to give the principal ownership over the resourcegroup
I want to give the principal ownership over the resourcegroup
You could get the template demo code from this link. If you create the template with VS you could get it directly from the template. It works correctly for me.
azuredeploy.json
{
"$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": [
"Owner",
"Contributor",
"Reader"
],
"metadata": {
"description": "Built-in role to assign"
}
},
"roleNameGuid": {
"type": "string",
"metadata": {
"description": "A new GUID used to identify the role"
}
}
},
"variables": {
"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')]",
"scope": "[resourceGroup().id]"
},
"resources": [
{
"type": "Microsoft.Authorization/roleAssignments",
"apiVersion": "2017-05-01",
"name": "[parameters('roleNameGuid')]",
"properties": {
"roleDefinitionId": "[variables(parameters('builtInRoleType'))]",
"principalId": "[parameters('principalId')]",
"scope": "[variables('scope')]"
}
}
]
}
azuredeploy.parameters.json
{
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"principalId": {
"value": "principalId"
},
"builtInRoleType": {
"value": "Owner"
},
"roleNameGuid": {
"value": "Guid name"
}
}
}
Test Result:
The error is happening because the name has more segments, i.e. components demarcated with a slash, than the type, as explained in more detail here: Resolve errors for invalid template.
There's a related discussion here; if you can get the GUID for the resource and pass that in for name, it will have fewer segments than the type.