Search code examples
azureazure-resource-managerazure-bicepazure-rbac

Bicep role assignment to storage account in different resource group


I have a devops pipeline that run a "resource group" scoped deployment via "az deployment group create". There is no permission to run deployments at subscription level.

My bicep deploys a function app into resource group A. Resource group B contains an existing storage account. I'd like my bicep to create a role assignment on the existing storage account of blob data reader for the new function app.

I've created a dedicated module to apply the role assignment, as seen below:

param environment string = 'dev'
param funcAppPrincipalId string
param stroageAcRG string

var storageAcName = 'storcats${environment}001'

var storageBlobDataReaderRole = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')

resource storageAccount 'Microsoft.Storage/storageAccounts@2021-04-01' existing = {
  name: storageAcName
  scope: resourceGroup(stroageAcRG)
}

resource roleAssignment 'Microsoft.Authorization/roleAssignments@2020-08-01-preview' = {
  name: guid(storageAccount.id, funcAppPrincipalId, storageBlobDataReaderRole)
  scope: storageAccount
  properties: {
    principalId: funcAppPrincipalId
    roleDefinitionId: storageBlobDataReaderRole
  }
}

My problem is, this gives a compile error on the line "scope: storageAccount":

"A resource's scope must match the scope of the Bicep file for it to be deployable. You must use modules to deploy resources to a different scope.",


Solution

  • Thanks to @4c74356b41 for pointing me to a helpful doc on learn.microsoft.com.

    The trick is to use the "scope" keyword when calling the module from main.bicep.

    My main.bicep now contains the following:

    module roleAsForCats 'roleAssignmentForCatsBlob.bicep' = {
      name: 'roleAsForCats'
      scope: resourceGroup('rg-cats-${environment}-001')
      params: {
        funcAppPrincipalId: functionApp.outputs.appServicePrincipalId 
        environment: environment
      }
    }
    

    and the content of the module is:

    param environment string = 'dev'
    param funcAppPrincipalId string
    
    var storageAcName = 'storcats${environment}001'
    var storageBlobDataReaderRole = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '2a2b9908-6ea1-4ae2-8e65-a410df84e7d1')
    
    resource storageAccount 'Microsoft.Storage/storageAccounts@2021-04-01' existing = {
      name: storageAcName
    }
    
    resource roleAssignment 'Microsoft.Authorization/roleAssignments@2020-08-01-preview' = {
      name: guid(storageAccount.id, funcAppPrincipalId, storageBlobDataReaderRole)
      scope: storageAccount
      properties: {
        principalId: funcAppPrincipalId
        roleDefinitionId: storageBlobDataReaderRole
      }
    }