Posts Enforcing Azure Lighthouse at Management Group Level
Post
Cancel

Enforcing Azure Lighthouse at Management Group Level

Enforcing Azure Lighthouse at Management Group Level AzureIs.Fun

If you manage Azure environments for customers, you already know why Azure Lighthouse exists. It allows you to manage customer resources from your own tenant, using your own identities, without guest accounts, without constant tenant switching, and without breaking RBAC boundaries. Once Lighthouse is in place, daily operations become a lot more predictable and a lot less painful.

Most teams start by onboarding Lighthouse per subscription. That works fine at the beginning, but it quickly falls apart once customers start adding subscriptions, reorganizing management groups, or rolling out landing zones at scale. This is where onboarding Lighthouse at management group scope becomes the only approach that truly scales.

When Lighthouse is enforced at the management group level, every existing subscription and every future subscription under that management group is automatically delegated. There is no manual onboarding step and no risk of missing newly created subscriptions. From a governance perspective, this also means a single policy, a single scope, and consistent behavior across the entire environment.

One important thing to know up front: this cannot be done from the Azure portal. There is no UI option to onboard Azure Lighthouse at management group scope. For now, seems like Microsoft intentionally requires this to be implemented using Azure Policy with a DeployIfNotExists policy definition.

The official Microsoft guidance explains this model in detail and is worth reading alongside this article: https://learn.microsoft.com/en-us/azure/lighthouse/how-to/onboard-management-group

Automation

I went a step ahead, and fully automated the process. We are still going to use the Azure Policy, but in automated fashion.

What the script actually does

To make things transparent, here’s exactly what the script automates for you:

  1. Connects to Azure and validates the current context
  2. Validates the target management group and recursively discovers all subscriptions under it
  3. Ensures the Microsoft.ManagedServices resource provider is registered in every subscription
  4. Deploys the Azure Policy ARM template at the management group scope
  5. Locates the newly created policy definition based on the display name from the parameters file
  6. Assigns the policy to the management group with a system-assigned managed identity
  7. Grants permissions to the managed identity so remediation can succeed
  8. Starts Azure Policy remediation to onboard Lighthouse for all existing subscriptions
  9. Monitors remediation progress and reports success or failure

This turns what is normally a multi-step, manual process into a single repeatable command.

Follow allong to learn what you need to update to make it work for you.

Azure Policy with parameters

The Azure Policy definition itself is fairly straightforward. The most important part is the parameters file, because that’s where you define who from your tenant gets access to the customer environment and with what permissions.

I’m using the following files in this setup, which I’ll reference throughout the article:

  • Policy definition
    https://github.com/vukasinterzic/PowerShell/blob/master/Azure%20Lighthouse%20on%20MG/deployLighthouseIfNotExistManagementGroup.json

  • Parameters file
    https://github.com/vukasinterzic/PowerShell/blob/master/Azure%20Lighthouse%20on%20MG/deployLighthouseIfNotExistsManagementGroup.parameters.json

Key parameters you must get right

The managedByTenantId parameter must contain the managing partner tenant ID, not the customer tenant ID. This value tells Azure which tenant is allowed to manage the delegated resources.

The managedByAuthorizations section defines which users or groups from your tenant will get access in the customer tenant, and which roles they will receive. In the example parameters file, you’ll see entries like AzureIsFun_Contributor and AzureIsFun_Reader. These are security groups (or users) that exist in your tenant. The principalId must be the object ID of that group or user from your tenant. When Lighthouse is deployed, Azure automatically creates the corresponding role assignments in the customer tenant for those identities.

The roleDefinitionId values are the built-in Azure role IDs. For example, Contributor and Reader are represented by fixed GUIDs. You can find and validate all built-in role IDs here: https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles

This approach allows you to grant very precise permissions to your operations teams, without creating users in the customer tenant and without over-privileging access.

Automating deployment and remediation with PowerShell

Deploying the policy, assigning it at management group scope, and running remediation can all be done manually—but it’s slow and error-prone. That’s why I wrapped the entire process in a PowerShell script.

The script used in this article is available here:

  • Deployment script
    https://github.com/vukasinterzic/PowerShell/blob/master/Azure%20Lighthouse%20on%20MG/Deploy-AzureLighthouseOnMG.ps1

Permissions

For simplicity and reliability, the script grants the Owner role to the policy assignment’s managed identity at the management group scope. This guarantees that remediation works across all subscriptions.

That said, Owner is not recommended for long-term use if not necessary. In a production setup, you should replace this with a more restrictive role or a custom role that allows policy remediation and managed services registration, without full control over the management group.

Conclusion

If you’re managing Azure environments at scale, onboarding Azure Lighthouse at the management group level is not optional, it’s foundational. It ensures new subscriptions are automatically covered, keeps governance intact, and removes a whole class of operational mistakes.

Yes, it requires Azure Policy. Yes, it’s a bit more work upfront. But once it’s in place, Lighthouse just works, and you stop worrying about access drift across subscriptions.

Include the policy, parameters file, and script in your toolkit, test it in a non-production management group, and you’ll never want to onboard Lighthouse one subscription at a time again.


Thanks for reading!

Vukasin Terzic

Updated Jan 14, 2026 2026-01-14T21:34:18+01:00
This post is licensed under CC BY 4.0