Coder Perfect

In the bicep template, how do you specify identity-based data access?

Problem

I have the following as a bicep template, and I’d like to use an identity-based connection. How can I design the template appropriately?

https://docs.microsoft.com/en-us/azure/azure-functions/functions-reference#connecting-to-host-storage-with-an-identity

I used the guidance here https://docs.microsoft.com/en-us/azure/azure-resource-manager/bicep/quickstart-create-bicep-use-visual-studio-code?tabs=PowerShell , for deployment.

New-AzResourceGroup -Name exampleRG -Location eastus

New-AzResourceGroupDeployment -ResourceGroupName exampleRG -TemplateFile ./main.bicep -storageName "{your-unique-name}" 

However, when I try to address the template file, I receive the following error: Code=InvalidTemplateDeployment; Message=The template deployment ‘bicepeg’ is not legitimate according to the validation method.

var baseName = uniqueString('identityRepro', subscription().id)
var location = 'uksouth'

resource stg 'Microsoft.Storage/storageAccounts@2019-06-01' = {
  name: baseName
  location: location 
  sku: {
    name: 'Standard_LRS'
  }
  kind: 'StorageV2'
}

resource asp 'Microsoft.Web/serverfarms@2019-08-01' = {
  name: baseName
  location: location
  sku: {
    name: 'Y1'
    tier: 'Dynamic'
  }
}

resource ai 'Microsoft.Insights/components@2015-05-01' = {
  name: baseName
  location: location
  kind: 'web'
  properties: {
    Application_Type: 'web'
  }
}

resource fa 'Microsoft.Web/sites@2019-08-01' = {
  name: baseName
  location: location
  identity: {
    type: 'SystemAssigned'
  }
  properties: {
    serverFarmId: asp.id
  }
  kind: 'functionapp'

  resource appSettings 'config@2018-11-01' = {
    name: 'appsettings'
    properties: {
      'AzureWebJobsStorage__accountName': stg.name
      'FUNCTIONS_WORKER_RUNTIME': 'powershell'
      'FUNCTIONS_WORKER_RUNTIME_VERSION': '~7'
      'APPINSIGHTS_INSTRUMENTATIONKEY': ai.properties.InstrumentationKey
    }
  }
}

resource blobContrib 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = {
  name: guid(fa.name, stg.name, 'ba92f.........d-a403-e96b0029c9fe')
  properties: {
    principalId: fa.identity.principalId
    roleDefinitionId: resourceId('Microsoft.Authorization/roleDefinitions', 'ba92f.......-a403-e96b0029c9fe')
    principalType: 'ServicePrincipal'
  }
  scope: stg
}

Asked by Anusri_Varier

Solution #1

I believe your issue is with the role’s id. Not in resource groups, but at the subscription level, roles are specified. Use subscriptionResourceId instead of resourceId in your code.

Update: as you mentioned on the github issue, you also had an issue with the way the name was generated. The seed – the parameters you provide to the function – is used to construct a pseudo-random string (a hash) by the uniqueString function. You will get the same outcome if you use the exact same values.

For me, the code below works.

var baseName = uniqueString(resourceGroup().id)
var location = 'uksouth'

resource stg 'Microsoft.Storage/storageAccounts@2019-06-01' = {
  name: baseName
  location: location 
  sku: {
    name: 'Standard_LRS'
  }
  kind: 'StorageV2'
}

resource asp 'Microsoft.Web/serverfarms@2019-08-01' = {
  name: baseName
  location: location
  sku: {
    name: 'Y1'
    tier: 'Dynamic'
  }
}

resource ai 'Microsoft.Insights/components@2015-05-01' = {
  name: baseName
  location: location
  kind: 'web'
  properties: {
    Application_Type: 'web'
  }
}

resource fa 'Microsoft.Web/sites@2019-08-01' = {
  name: baseName
  location: location
  identity: {
    type: 'SystemAssigned'
  }
  properties: {
    serverFarmId: asp.id
  }
  kind: 'functionapp'

  resource appSettings 'config@2018-11-01' = {
    name: 'appsettings'
    properties: {
      'AzureWebJobsStorage__accountName': stg.name
      'FUNCTIONS_WORKER_RUNTIME': 'powershell'
      'FUNCTIONS_WORKER_RUNTIME_VERSION': '~7'
      'APPINSIGHTS_INSTRUMENTATIONKEY': ai.properties.InstrumentationKey
    }
  }
}

resource blobContrib 'Microsoft.Authorization/roleAssignments@2020-04-01-preview' = {
  name: guid(fa.name, stg.name, 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')
  properties: {
    principalId: fa.identity.principalId
    roleDefinitionId: subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'ba92f5b4-2d11-453d-a403-e96b0029c9fe')
    principalType: 'ServicePrincipal'
  }
  scope: stg
}

Use resourceGroup in your code (). Because it contains the unique guid of your subscription and the name of a resource group, both of which must be unique within the subscription, your hash should be unique as well. only offering subscriptions (). For all deployments to that subscription and resource group in it, id will generate the same string.

Answered by Miq

Post is based on https://stackoverflow.com/questions/68114804/how-to-define-identity-based-data-access-in-the-bicep-template