azureazure-pipelinesazure-bicep

"InvalidOperationString" Error bicep while creating Resource Group through Azure CLI in pipeline


I am getting following error.

{"status":"Failed","error":{"code":"DeploymentFailed","target":"/subscriptions/{subscription_id}/providers/Microsoft.Resources/deployments/assign_role_to_subscription","message":"At least one resource deployment operation failed. Please list deployment operations for details. Please see https://aka.ms/arm-deployment-operations for usage details.","details":
[{"code":"InvalidOperationString",
"message":"Invalid operation string {subscription_name} provided in request"}]}}

I am running below bicep file:

import * as common from 'exports.bicep'
targetScope='subscription'

//  Parameters
param resourceGroupName string = 'rg-ascend-us'
param resourceGroupLocation string = 'eastus2'
param environmentName string = 'Development'

var peregrineGroupPrincipalId = '{group_principal_id}'
var readerRoleDefinitionId = 'acdd72a7-3385-48ef-bd42-f606fba81ae7'
var subscriptionName = 'Cosmos Dev'

//  Get existing subscription
@description('')
resource subscriptionResource 'Microsoft.Subscription/subscriptionOperations@2017-11-01-preview' existing = {
  scope: tenant()
  name: subscriptionName
}

//  Get the reader role.
@description('This is the built-in Reader role. See acdd72a7-3385-48ef-bd42-f606fba81ae7')
resource readerRoleDefinition 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = {
  scope: subscription()
  name: readerRoleDefinitionId
}

//  Assign group 'sg-apac-peregrine' to the subscription and set the role.
resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
  scope: subscriptionResource
  name: guid(subscription().id, peregrineGroupPrincipalId, readerRoleDefinition.id)
  properties:{
    roleDefinitionId: readerRoleDefinition.id
    principalId: peregrineGroupPrincipalId
    principalType: 'Group'
  }
}

resource resourceGroup 'Microsoft.Resources/resourceGroups@2024-03-01' = {
  name: resourceGroupName
  location: resourceGroupLocation
  tags: common.getTags(environmentName)
}

The bicep file is executed through Azure Devops Pipeline job using an azure CLI command.

- task: AzureCLI@2
  inputs:
    azureSubscription: 'Azure Cosmos Dev Subscription Connection'
    scriptType: bash
    scriptLocation: inlineScript
    useGlobalConfig: false
    inlineScript: |
      az deployment sub create --location eastus2 --template-file $(System.DefaultWorkingDirectory)/.iac/bicep/assign_role_to_subscription.bicep

The CLI command is

az deployment sub create --location eastus2 --template-file {path_to_bicep_file}

The service connection is associated with subscription to which I am trying to deploy. The error message isn't very helpful in showing exactly what is happening. Any insights would be appreciated.


Solution

  • I can reproduce the same issue both in Local env and Azure Pipelines when using the same Bicep sample.

    enter image description here

    The issue is related to the following code snippet:

    @description('')
    resource subscriptionResource 'Microsoft.Subscription/subscriptionOperations@2017-11-01-preview' existing = {
      scope: tenant()
      name: subscriptionName
    }
    

    The reason for this issue could be that Microsoft.Subscription/subscriptionOperations needs to set the tenant scope, but the azure cli command and target scope both point to the subscription scope. And the resource type doesn't supports defining scope.

    For more detailed info, you can refer to this doc: Microsoft.Subscription/subscriptionOperations

    When we use Azure CLI task in Azure DevOps Pipeline, it will set the subscription before executing the Azure CLI command.

    enter image description here

    So by default it will point to the subscription associated with the service connection. We don't need to declare it in bicep file.

    You can remove the subscriptionResource code snippet in bicep file and run the azure cli task again.

    Here is updated sample:

    exports.bicep:

    @export()
    func getTags(environmentName string) object => {
      Product: 'product_name'
      Team: 'team_name'
      ServiceName: 'adapter'
      Environment: environmentName
    }
    

    Main bicep:

    import * as common from 'exports.bicep'
    targetScope='subscription'
    
    //  Parameters
    param resourceGroupName string = 'rg-ascend-us'
    param resourceGroupLocation string = 'eastus2'
    param environmentName string = 'Development'
    
    var peregrineGroupPrincipalId = '{group_principal_id}'
    var readerRoleDefinitionId = 'acdd72a7-3385-48ef-bd42-f606fba81ae7'
    
    
    //  Get the reader role.
    @description('This is the built-in Reader role. See acdd72a7-3385-48ef-bd42-f606fba81ae7')
    resource readerRoleDefinition 'Microsoft.Authorization/roleDefinitions@2022-04-01' existing = {
      scope: subscription()
      name: readerRoleDefinitionId
    }
    
    //  Assign group 'sg-apac-peregrine' to the subscription and set the role.
    resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
    
      name: guid(subscription().id, peregrineGroupPrincipalId, readerRoleDefinition.id)
      properties:{
        roleDefinitionId: readerRoleDefinition.id
        principalId: peregrineGroupPrincipalId
        principalType: 'Group'
      }
    }
    
    resource resourceGroup 'Microsoft.Resources/resourceGroups@2024-03-01' = {
      name: resourceGroupName
      location: resourceGroupLocation
      tags: common.getTags(environmentName)
    }