Management Group scoped Service Connection gives AuthorizationFailed

When a resource id is not the id you need.

TL;DR: a management group id is the short identifier, not the fully qualified identifier.

If you’re writing corporate software, you shouldn’t right-click publish. There’s even a site dedicated to it. To delivery quality enterprise-worthy software, your deployments should be done by CI/CD pipelines to have automated, repetitive releases. Taking it a step further, neither your codebase or deployment pipelines should contain passwords. You can use the concept of ‘Service Connections’ when trying to deploy using Azure DevOps.

I’ve used plenty of service connections in Azure DevOps in the past, quite often created by corporate IT (since they rightfully don’t want to share credentials by mail, chat, …), and often you don’t get the required rights to create these app registratiosn yourself at a client. Luckily, I was able to create more than a handful myself in the past, all scoped to subscription and most of the times trimmed down with rights on a single or few resource groups (following the least-privilege principle), so I knew my way around.

Today I needed my service connection to scope to management group level, as I wanted to deploy Bicep templates accross multiple subscriptions as baseline for a new cloud migration project. Just out of vacation and being interrupted by a technician to come check my internet connection, I must have been distracted somewhat as I experienced a small facepalm moment. Looking at the wizard to create the service connection, you need a management group id.

Service Connection wizard

Subscriptions have guids as ids, but the id of a management group can be any string. Since I needed multiple service connections for different management groups, I used Azure CLI with my admin account to list all management groups (names and ids are replaced).

PS> C:\Users\Bart> az account management-group list
[
  {
    "displayName": "Tenant Root Group",
    "id": "/providers/Microsoft.Management/managementGroups/77755ff4-492f-4002-9992-1e2b404e266c",
    "name": "77755ff4-492f-4002-9992-1e2b404e266c",
    "tenantId": "77755ff4-492f-4002-9992-1e2b404e266c",
    "type": "/providers/Microsoft.Management/managementGroups"
  },
  {
    "displayName": "MG Production",
    "id": "/providers/Microsoft.Management/managementGroups/mg-production",
    "name": "mg-production",
    "tenantId": "77755ff4-492f-4002-9992-1e2b404e266c",
    "type": "/providers/Microsoft.Management/managementGroups"
  },
  {
      ...
  }
]

I quickly copied the id field from the result (which is in the format of a typical Azure resource id), filled in all other properties, hit ‘Verify’ and received following error.

Failed to query service connection API:
'https://management.azure.com/providers/Microsoft.Management/managementGroups/providers/Microsoft.Management/managementGroups/mg-production?api-version=2018-01-01-preview'.
Status Code: 'Forbidden', Response from server: '{"error":{"code":"AuthorizationFailed","message":"The client '82f6918e-0a1b-45eb-9c29-3be46bb8cfd3'
with object id '82f6918e-0a1b-45eb-9c29-3be46bb8cfd3' does not have authorization to perform action
'Microsoft.Management/managementGroups/Microsoft.Management/mg-production/read' over scope 
'/providers/Microsoft.Management/managementGroups/providers/Microsoft.Management/managementGroups'
or the scope is invalid. If access was recently granted, please refresh your credentials."}}'

Since I had just created the service principal and assigned the right RBAC permissions, I first thought I needed to wait a few more minutes. I quickly verified the object id with following command as the object id is different from the application id you just used to register the service connection.

az rest --method POST --url 'https://graph.microsoft.com/v1.0/directoryObjects/getByIds' 
  --headers 'Content-Type=application/json' --body '{ \"ids\":[\"82f6918e-0a1b-45eb-9c29-3be46bb8cfd3\"]}'

As the technician was replacing the cable between NIU and modem, RBAC permissions had plenty of time to propagate … but there error was still there afterwards. Then it came to me that the last part of the above id, the value of the name property, is also known as ‘management group id’, as clearly mentioned in Create a management group. Simply fill in that id (above mg-production) and you’re good to go.

Licensed under CC BY-NC-SA 4.0; code samples licensed under MIT.
comments powered by Disqus
Built with Hugo - Based on Theme Stack designed by Jimmy