Azure Bicep - Referencing a variable that cannot be calculated at the start
Asked Answered
I

2

6

I need to:

  • create a data factory
  • create a storage account
  • create a function app
  • add a role assignment for the data factory to the storage account
  • add a role assignment for the function app to the storage account

The data factory is created in a separate module from the "main" bicep. This is to prevent the "main" template being so large it is difficult to work with - one of the main benefits of bicep over arm templates. Same goes for creation of the function app.

For the role assignment I have:

resource roleAssignment 'Microsoft.Authorization/roleAssignments@2020-08-01-preview' = {
  name: guid(storageAccount.id, contributorRoleId, adfDeploy.outputs.dfId)

VSCode then presents the following "problem":

This expression is being used in an assignment to the "name" property of the "Microsoft.Authorization/roleAssignments" type, which requires a value that can be calculated at the start of the deployment. Properties of adfDeploy which can be calculated at the start include "name".

I can't compose the storageAccount Id from a string (subscription/rg/resource etc.) because the subscription id is also determined at runtime since the same main bicep is called for deployment to multiple subscriptions.

Is there any way to achieve what's needed without pulling back the creation of the data factory and function apps to the "main" bicep?

Intricate answered 4/8, 2022 at 8:33 Comment(2)
you could always encapsulate the role asisgnment in its own module. resouceId() anyway should do the trick to get the id of the storage account.Mcclellan
+1 to Thomas - you need to put the roleAssignments into the module. The params for that module should be (at a minimum) the values you need for the name of the roleAssignment. The way you have the roleAssignment name property above guid(scope, role, prinicpal) is the way you need to have it but will need it in a module due to the error you're seeing.Fortify
M
5

You could create a generic module for storage role assignment:

// storage-account-role-assignment.bicep
param storageAccountName string
param principalId string
param roleId string

// Get a reference to the storage account
resource storageAccount 'Microsoft.Storage/storageAccounts@2019-06-01' existing = {
  name: storageAccountName
}

// Grant permissions to the storage account
resource storageAccountAppRoleAssignment 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' =  {
  name: guid(storageAccount.id, roleId, principalId)
  scope: storageAccount
  properties: {
    roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', roleId)
    principalId: principalId
  }
}

Then invoke this module from where you are creating data factory or function app:

// function-app.bicep
...
resource functionApp 'Microsoft.Web/sites@2021-03-01' = {
  name: functionAppName
  kind: 'functionapp'
  identity: {
    type: 'SystemAssigned'
  }
  ...
}

// Create role assignment
module roleAssignment 'storage-account-role-assignment.bicep' = {
  name: 'function-storage-account-role-assignment'
  scope: resourceGroup()
  params:{
    storageAccountName: storageAccountName
    roleId: '<role-id>'
    principalId: functionApp.identity.principalId
  }
}

// data-factory.bicep
...
resource dataFactory 'Microsoft.DataFactory/factories@2018-06-01' = {
  name: name
  identity: {
    type: 'SystemAssigned'
  }
  ...
}

// Create role assignment
module roleAssignment 'storage-account-role-assignment.bicep' = {
  name: 'data-facory-storage-account-role-assignment'
  scope: resourceGroup()
  params:{
    storageAccountName: storageAccountName
    roleId: '<role-id>'
    principalId: dataFactory.identity.principalId
  }
}
Mcclellan answered 4/8, 2022 at 20:26 Comment(0)
R
0

I contacted support. This is a capacity issue in EastUS2. I moved it to CentralUS and it's working.

Replace answered 18/10, 2024 at 19:8 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.