Azure / azure-cli

Azure Command-Line Interface
MIT License
4k stars 2.98k forks source link

az account alias create - ERROR: (Forbidden) You do not have sufficient permissions on the specified invoice section to create an Azure subscription #26470

Open jason-calton opened 1 year ago

jason-calton commented 1 year ago

az feedback auto-generates most of the information requested below, as of CLI version 2.0.62

Related command

az account alias create

Describe the bug

This is running in a github action, logged in as an sp using oidc auth.
SP is global administrator, billing account owner. billing profile owner, invoice section owner. My account is MCA (Microsoft Customer Agreement)

To Reproduce

Run in a github action, logged in as an sp using oidc auth.
SP is global administrator, billing account owner. billing profile owner, invoice section owner. Account is MCA (Microsoft Customer Agreement)

GitHub action yaml:

name: Subscription

on: 
  workflow_dispatch:
    inputs:
      subscription_name:
        description: "subscription name"     
        required: true

permissions:
  id-token: write
  contents: read

jobs:

  Create-Subscription:
    name: Create Subscription
    runs-on: ubuntu-latest
    steps:
      - name: "Az CLI login"
        uses: azure/login@v1
        with:
          client-id: "${{ secrets.AZURE_DEPLOYER_CLIENT_ID }}"
          tenant-id: "${{ secrets.AZURE_TENANT_ID }}"
          allow-no-subscriptions: true

      - name: Create Billing Invoice Section
        run: |
          billing_accounts=$( az billing account list )
          echo "billing_accounts: "
          echo "$billing_accounts"
          echo ""
          echo ""

          billing_account_name=$( jq -r  '.[0].name' <<< "${billing_accounts}" ) 
          echo "billing_account_name: "
          echo "$billing_account_name"
          echo ""
          echo ""

          billing_profiles=$( az billing profile list --expand "invoiceSections" --account-name $billing_account_name )
          echo "billing_profiles: "
          echo "$billing_profiles"
          echo ""
          echo ""

          billing_profile_name=$( jq -r  '.[0].name' <<< "${billing_profiles}" ) 
          echo "billing_profile_name: "
          echo "$billing_profile_name"
          echo ""
          echo ""

          invoice_sections=$( az billing invoice section list --account-name "$billing_account_name" --profile-name "$billing_profile_name" )
          invoice_section=$( jq -r --arg name "${{ github.event.inputs.subscription_name }}"  '.[] | select(.name==$name)' <<< "${invoice_sections}" ) 
          if [[ "$invoice_section" == "null" || "$invoice_section" == "" ]]; then
            echo "creating invoice_section..."
            echo ""
            invoice_section=$( az billing invoice section create --account-name "$billing_account_name" --profile-name "$billing_profile_name" --invoice-section-name ${{ github.event.inputs.subscription_name }} --display-name "${{ github.event.inputs.subscription_name }} Invoice Section" )
          else
            echo "invoice_section: "
          fi
          echo "$invoice_section"
          echo ""
          echo ""

          invoice_section_id=$( jq -r  '.id' <<< "${invoice_section}" ) 
          echo "invoice_section_id: "
          echo "$invoice_section_id"
          echo "invoice_section_id=$invoice_section_id" >> $GITHUB_ENV 
          echo ""
          echo ""

          billing_permissions_for_invoice_section=$( az billing permission list --account-name "$billing_account_name" --profile-name "$billing_profile_name" --invoice-section-name "${{ github.event.inputs.subscription_name }}" ) 
          echo "billing_permissions_for_invoice_section: "
          echo "$billing_permissions_for_invoice_section"
          echo ""
          echo ""

      - name: Create Subscription
        run: |
          echo "Create Subscription" 

          #### https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/programmatically-create-subscription-microsoft-customer-agreement?tabs=rest
          #### https://github.com/MicrosoftDocs/azure-docs/blob/main/articles/cost-management-billing/manage/programmatically-create-subscription-microsoft-customer-agreement.md

          echo "install extension: account"
          az extension add --name account
          echo ""
          echo ""

          echo "install extension: alias"
          az extension add --name alias
          echo ""
          echo ""

          sub=$( az account alias create --name "${{ github.event.inputs.subscription_name }}" --display-name "${{ github.event.inputs.subscription_name }}" --workload "DevTest" --billing-scope "${{ env.invoice_section_id }}" )
          echo "sub: "
          echo "$sub"
          echo "sub=$sub" >> $GITHUB_ENV 
          echo ""
          echo ""

Expected behavior

Subscription and alias created successfully.

Environment summary

Run in a github action, logged in as an sp using oidc auth.
SP is global administrator, billing account owner. billing profile owner, invoice section owner. Account is MCA (Microsoft Customer Agreement)

running "az billing permission list" for the created invoice section shows the below, but I could not find any information about what roles or permissions each of these values represent: [ { "actions": [ "30000000-aaaa-bbbb-cccc-200000000000", "30000000-aaaa-bbbb-cccc-200000000017", "30000000-aaaa-bbbb-cccc-200000000018", "30000000-aaaa-bbbb-cccc-200000000001", "30000000-aaaa-bbbb-cccc-200000000003", "30000000-aaaa-bbbb-cccc-200000000004", "30000000-aaaa-bbbb-cccc-200000000005", "30000000-aaaa-bbbb-cccc-200000000006", "30000000-aaaa-bbbb-cccc-200000000007", "30000000-aaaa-bbbb-cccc-200000000008", "30000000-aaaa-bbbb-cccc-200000000009", "30000000-aaaa-bbbb-cccc-200000000010", "30000000-aaaa-bbbb-cccc-200000000011", "30000000-aaaa-bbbb-cccc-200000000012", "30000000-aaaa-bbbb-cccc-200000000013", "30000000-aaaa-bbbb-cccc-200000000015", "30000000-aaaa-bbbb-cccc-200000000016" ], "notActions": null } ]

Additional context

yonzhan commented 1 year ago

Thank you for opening this issue, we will look into it.

zhoxing-ms commented 1 year ago

ERROR: (Forbidden) You do not have sufficient permissions on the specified invoice section to create an Azure subscription. Refer(http://aka.ms/mca-section-invoice) to set the right permissions and try again

Since this error message was returned by REST service, so this should be a service issue or customer usage issue. Because this is not a CLI issue, I forwarded this issue to CXP team

ghost commented 1 year ago

Thank you for your feedback. This has been routed to the support team for assistance.

jason-calton commented 1 year ago

@jiasli I was able to get the following rest api call to work once, then subsequent tries have been returning "too many requests". Is this particular endpoint throttled more heavily?

        $subscription = $( 
          az rest `
            --method PUT `
            --uri "https://management.azure.com/providers/Microsoft.Subscription/aliases/${{ env.subscription_name }}?api-version=2021-10-01" `
            --headers "Content-Type=application/json" `
            --body "{ `
              \`"properties\`": `
              { `
                \`"billingScope\`": \`"${{ env.billing_invoice_section_id }}\`", `
                \`"displayName\`": \`"${{ env.subscription_name }}\`", `
                \`"workload\`": \`"Production\`" `
              } `
            }" `
          | ConvertFrom-Json
        )
brianwthomas commented 1 year ago

I'm having a similar issue.

I'm full Global Admin and have set myself to have access to all the billing information. I can create a subscription via the portal, but when I use bicep file to do this it fails.

targetScope = 'tenant'
resource subscriptionAlias 'Microsoft.Subscription/aliases@2021-10-01' = {
  name: 'TestSub
  scope: tenant()
  properties: {
    workload: 'DevTest'
    displayName: 'This is a test subscription
    billingScope: '/MyBillingStuffHere'
  }

}

sudo az deployment tenant create --location eastus --template-file ./main.bicep {"status":"Failed","error":{"code":"DeploymentFailed","target":"/providers/Microsoft.Resources/deployments/main","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":"Forbidden","message":"You do not have sufficient permissions on the specified invoice section to create an Azure subscription. Refer(http://aka.ms/mca-section-invoice) to set the right permissions and try again"}]}}

What's interesting is if I change the targetScope to be managementGroup and deploy to a management group this works.

ghost commented 1 year ago

Thanks for the feedback! We are routing this to the appropriate team for follow-up. cc @josephkwchan, @jennyhunter-msft.

Issue Details
> ### `az feedback` auto-generates most of the information requested below, as of CLI version 2.0.62 **Related command** az account alias create **Describe the bug** This is running in a github action, logged in as an sp using oidc auth. SP is global administrator, billing account owner. billing profile owner, invoice section owner. My account is MCA (Microsoft Customer Agreement) - First I call "az billing invoice section create" which successfully creates the invoice section. - Next, I call: az extension add --name account az extension add --name alias az account alias create --name "${{ github.event.inputs.subscription_name }}" --display-name "${{ github.event.inputs.subscription_name }}" --workload "DevTest" --billing-scope "${{ env.invoice_section_id }}" ) - The "az account alias create" call results in this error: ERROR: (Forbidden) You do not have sufficient permissions on the specified invoice section to create an Azure subscription. Refer(http://aka.ms/mca-section-invoice) to set the right permissions and try again **To Reproduce** Run in a github action, logged in as an sp using oidc auth. SP is global administrator, billing account owner. billing profile owner, invoice section owner. Account is MCA (Microsoft Customer Agreement) GitHub action yaml: name: Subscription on: workflow_dispatch: inputs: subscription_name: description: "subscription name" required: true permissions: id-token: write contents: read jobs: Create-Subscription: name: Create Subscription runs-on: ubuntu-latest steps: - name: "Az CLI login" uses: azure/login@v1 with: client-id: "${{ secrets.AZURE_DEPLOYER_CLIENT_ID }}" tenant-id: "${{ secrets.AZURE_TENANT_ID }}" allow-no-subscriptions: true - name: Create Billing Invoice Section run: | billing_accounts=$( az billing account list ) echo "billing_accounts: " echo "$billing_accounts" echo "" echo "" billing_account_name=$( jq -r '.[0].name' <<< "${billing_accounts}" ) echo "billing_account_name: " echo "$billing_account_name" echo "" echo "" billing_profiles=$( az billing profile list --expand "invoiceSections" --account-name $billing_account_name ) echo "billing_profiles: " echo "$billing_profiles" echo "" echo "" billing_profile_name=$( jq -r '.[0].name' <<< "${billing_profiles}" ) echo "billing_profile_name: " echo "$billing_profile_name" echo "" echo "" invoice_sections=$( az billing invoice section list --account-name "$billing_account_name" --profile-name "$billing_profile_name" ) invoice_section=$( jq -r --arg name "${{ github.event.inputs.subscription_name }}" '.[] | select(.name==$name)' <<< "${invoice_sections}" ) if [[ "$invoice_section" == "null" || "$invoice_section" == "" ]]; then echo "creating invoice_section..." echo "" invoice_section=$( az billing invoice section create --account-name "$billing_account_name" --profile-name "$billing_profile_name" --invoice-section-name ${{ github.event.inputs.subscription_name }} --display-name "${{ github.event.inputs.subscription_name }} Invoice Section" ) else echo "invoice_section: " fi echo "$invoice_section" echo "" echo "" invoice_section_id=$( jq -r '.id' <<< "${invoice_section}" ) echo "invoice_section_id: " echo "$invoice_section_id" echo "invoice_section_id=$invoice_section_id" >> $GITHUB_ENV echo "" echo "" billing_permissions_for_invoice_section=$( az billing permission list --account-name "$billing_account_name" --profile-name "$billing_profile_name" --invoice-section-name "${{ github.event.inputs.subscription_name }}" ) echo "billing_permissions_for_invoice_section: " echo "$billing_permissions_for_invoice_section" echo "" echo "" - name: Create Subscription run: | echo "Create Subscription" #### https://learn.microsoft.com/en-us/azure/cost-management-billing/manage/programmatically-create-subscription-microsoft-customer-agreement?tabs=rest #### https://github.com/MicrosoftDocs/azure-docs/blob/main/articles/cost-management-billing/manage/programmatically-create-subscription-microsoft-customer-agreement.md echo "install extension: account" az extension add --name account echo "" echo "" echo "install extension: alias" az extension add --name alias echo "" echo "" sub=$( az account alias create --name "${{ github.event.inputs.subscription_name }}" --display-name "${{ github.event.inputs.subscription_name }}" --workload "DevTest" --billing-scope "${{ env.invoice_section_id }}" ) echo "sub: " echo "$sub" echo "sub=$sub" >> $GITHUB_ENV echo "" echo "" **Expected behavior** Subscription and alias created successfully. **Environment summary** Run in a github action, logged in as an sp using oidc auth. SP is global administrator, billing account owner. billing profile owner, invoice section owner. Account is MCA (Microsoft Customer Agreement) running "az billing permission list" for the created invoice section shows the below, but I could not find any information about what roles or permissions each of these values represent: [ { "actions": [ "30000000-aaaa-bbbb-cccc-200000000000", "30000000-aaaa-bbbb-cccc-200000000017", "30000000-aaaa-bbbb-cccc-200000000018", "30000000-aaaa-bbbb-cccc-200000000001", "30000000-aaaa-bbbb-cccc-200000000003", "30000000-aaaa-bbbb-cccc-200000000004", "30000000-aaaa-bbbb-cccc-200000000005", "30000000-aaaa-bbbb-cccc-200000000006", "30000000-aaaa-bbbb-cccc-200000000007", "30000000-aaaa-bbbb-cccc-200000000008", "30000000-aaaa-bbbb-cccc-200000000009", "30000000-aaaa-bbbb-cccc-200000000010", "30000000-aaaa-bbbb-cccc-200000000011", "30000000-aaaa-bbbb-cccc-200000000012", "30000000-aaaa-bbbb-cccc-200000000013", "30000000-aaaa-bbbb-cccc-200000000015", "30000000-aaaa-bbbb-cccc-200000000016" ], "notActions": null } ] **Additional context**
Author: jason-calton
Assignees: jiasli, zhoxing-ms
Labels: `Service Attention`, `question`, `ARM`, `customer-reported`, `Installation`, `Auto-Assign`, `Azure CLI Team`
Milestone: Backlog
letmetechyou commented 1 year ago

Is there an update on this. I run into this same error in terraform and i have all the permissions needed

mheers commented 1 year ago

Also using the official azure-sdk-for-go it works only once and then fails with TooManyRequests. I created a demo repo: https://github.com/mheers/azure-subscription-go-example

The important thing I learned here, that it was mandatory to use Production as Workload.

EricManseau commented 11 months ago

Have been able to sort this one out while talking with support.

In my case I was using Bicep in DevOps pipeline. This was my setup:

When creating the subscription, you need to make sure the following:

for me it was the plan option 002 that was not available and I was trying to create development subscription.

This can be retrieve with this simple command: Get-AzBillingAccount -Name xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxxxxxxxx -ListEntitiesToCreateSubscription

which provide you with this value EnabledAzurePlans : {0002, 0001}

So the error is not complete, instead of a simple Authorization Access error, an additional message like Azure Plan not available for the billing profile would have make it 👍

Romiko commented 5 months ago

Thanks, helped me heaps @EricManseau

FYI, you can also use: az billing account list-invoice-section --billing-account-name xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxxxxxxxx