Skip to content

Prepare Identity and Access

This page covers the Entra ID and Azure objects that must exist before the first deployment: the platform team's groups, the administrative unit, the PIM flow, the RBAC roles, the management group, and the deployment identities with their service connections. The model behind them is in Identity and access model.

In many implementations the customer creates the first part (groups, administrative unit, management group, PIM) from a written request, and the platform team verifies it with the prerequisite checks. In a self-managed implementation your own identity team usually does it. The steps are the same either way.

What you create

Object Purpose Created by
Platform engineers group All people who work on the platform. Not role-assignable. Customer identity team
Platform maintainers group The group that holds the permanent role assignments. It has no active members: access comes from PIM. Role-assignable. Customer identity team
Administrative unit Scopes the Entra ID groups that the spoke pipeline creates Customer identity team
Platform management group Root of the platform hierarchy Customer, or the platform team
PIM configuration Makes the engineers group an eligible member of the maintainers group, with approval Customer identity team
RBAC and directory roles Give the maintainers group the rights to deploy Customer identity team
Deployment service principals The identities the pipelines use, per platform environment Platform team
Service connections or federated credentials Let Azure DevOps or GitHub sign in as those service principals Platform team

Example names

The names below follow the convention of one implementation (prefix ASG_ for Azure security groups, an administrative unit named after the platform). They are examples. Use the naming standard of the customer.

1. Groups

Create two security groups in Microsoft Entra ID (Groups, New group):

Group Example name Membership type Microsoft Entra roles can be assigned to the group Members
Platform engineers ASG_Platform_Engineers Assigned No The people of the platform team
Platform maintainers ASG_CloudPlatform_Maintainers Assigned Yes (confirm the pop-up) None. Membership comes from PIM.

The setting Microsoft Entra roles can be assigned to the group can only be chosen when the group is created.

2. Management group

If the customer has not created it, create the platform management group (Management groups, Create):

Field Value
Management group ID A short ID without spaces, for example <customer>-platform. Cannot be changed later.
Display name A readable name

This ID becomes management_group_organization_id (mapping). Place the platform subscriptions under it (Prerequisites).

3. Administrative unit

Create an administrative unit (Microsoft Entra ID, Administrative units, Add):

Field Value
Name For example AU_CloudPlatform
Description What it is used for
Restricted management administrative unit No

Copy its object ID. It becomes SpokeCommon.tenantinfo.AdministrativeUnitId in mcp.json. The spoke pipeline creates the spoke groups in this unit (New spoke).

4. RBAC and directory roles for the maintainers group

Assign these to the maintainers group, so nobody holds them permanently.

On the platform management group

  1. Open Management groups, the platform management group, Access control (IAM).
  2. Add, Add role assignment. Choose the role Owner (under Privileged administrator roles).
  3. As member, choose the maintainers group.
  4. On the Conditions tab, choose Allow user to assign all roles (highly privileged). The deployment creates role assignments, so Owner without this condition is not enough.
  5. Review + assign.

On the administrative unit

Open the administrative unit, Roles and administrators. Assign each of these roles to the maintainers group:

  • Groups Administrator
  • User Administrator

For each: assignment type Active, permanent, and a justification that says the group has no active members and that membership is given through PIM flows for just-in-time and just-enough access.

In the directory

Open Microsoft Entra ID, Roles and administrators, Application Developer, and assign it to the maintainers group in the same way (active, permanent, same justification). It allows the team to create the deployment service principals.

5. PIM flow

The engineers group becomes an eligible member of the maintainers group. Engineers activate the membership when they need to work.

  1. Open Microsoft Entra Privileged Identity Management, Groups, Discover groups.
  2. Search for the maintainers group, select it, and choose Manage groups. Confirm the pop-up and wait for it to finish.
  3. Open the maintainers group, Assignments, Add assignments. Role: Member. Member: the engineers group. Keep the default settings, which make the assignment eligible for a year. Renew it before it expires.
  4. Open Settings, the Member role, Edit. Select Require approval to activate and choose the approvers. Choose approvers that fit the operating model:
    • In the managed model, the approvers are usually members of the platform team itself (a second engineer approves) or a customer group, as agreed in the contract.
    • In the self-managed model, use a group of the customer's security or cloud platform owners, or a second engineer of the team.

Engineers then activate the group assignment in PIM (My roles, Groups, Activate) before they work. This is also the first check in the prerequisite checks.

6. Deployment service principals

Create one service principal per platform environment (canary and prod). The pipelines use it to sign in to Azure. mcp.json refers to it as Azure.TerraformState.Hub.ServicePrincipalId (and .Spoke. for spokes). You may use one service principal for hub and spokes or separate ones. Separate ones let you give the spoke identity its directory permissions without giving them to the hub identity.

Activate PIM first

Creating service principals and role assignments needs the rights from the maintainers group. Activate your PIM assignment before you start.

Sign in to the customer's tenant, then create the service principals and give them Owner on the platform management group:

az login --tenant <tenant-id>

$customerShortName = "<short-name>"      # at most 6 characters
$managementGroupId = "<management-group-id>"

foreach ($env in "CANARY", "PROD") {
    $name = "SPN_${customerShortName}_LZ_${env}"
    $sp   = az ad sp create-for-rbac --name $name | ConvertFrom-Json
    az role assignment create --assignee $sp.appId --role "Owner" `
        --scope "/providers/Microsoft.Management/managementGroups/$managementGroupId"
    "$name  client id: $($sp.appId)  tenant: $($sp.tenant)"
    # $sp.password holds the client secret. Store it in your vault now. It is shown only once.
}

The name pattern SPN_<short-name>_LZ_<ENV> is an example from earlier runbooks; use your own standard.

Store the secret safely

az ad sp create-for-rbac creates a client secret and prints it once. Put it in the secret store that your team uses (as a secret value, never in plain text, chat or the repository). Better: use federated credentials and skip the secret (GitHub variant, and workload identity federation for Azure DevOps service connections). The update-spn pipeline in the code repository stores and rotates a deployment secret in the hub Key Vault (Responsibilities).

Permissions of the spoke identity

The identity that deploys spokes needs more than Azure RBAC, because the spoke canvas creates Entra ID groups, service principals and PIM settings. In the runbooks for the GitHub variant these were:

Where Permission
Microsoft Graph, application permissions AdministrativeUnit.ReadWrite.All, Application.ReadWrite.All, DelegatedPermissionGrant.ReadWrite.All, Group.Read.All, GroupMember.Read.All, PrivilegedAccess.ReadWrite.AzureADGroup, PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup, RoleManagement.ReadWrite.Directory, RoleManagementPolicy.ReadWrite.AzureADGroup, RoleManagementPolicy.ReadWrite.Directory, User.Read.All
Administrative unit Groups Administrator
State storage account Storage Blob Data Contributor
Platform management group Enough to move subscriptions and create role assignments. The deployment identity's Owner assignment covers this.

If you deploy spokes with two spoke identities (canary and production), give each the Owner role on the landing zone management group of its own environment, and the Groups Administrator role on the administrative unit. More in Prepare the spoke pipeline.

Granting the Graph permissions needs admin consent from someone with the right directory role. Ask the customer's administrator, or use your PIM-activated role if you hold it. The authoritative list for your version is in the documentation of the spoke canvas in the code repository you pin (How to use spoke deployment, section Prerequisites, Pipeline, Service principal). Check the list against it before you request consent.

7. Service connections (Azure DevOps)

For each deployment service principal create an Azure Resource Manager service connection in the Azure DevOps project (Project settings, Service connections, New service connection):

Field Value
Identity type App registration or managed identity (manual)
Credential Secret, or workload identity federation if you set up federated credentials
Scope level Subscription: the management subscription of that platform environment
Subscription ID and name The management subscription of canary, or of prod
Application (client) ID The client ID of the service principal
Directory (tenant) ID The customer's tenant ID
Client secret The secret, when you use one
Service connection name The name that pipelines/variables.yaml expects, for example <env>.serviceConnectionNameHub (Pipelines)

Choose Verify, then Save. Use separate service connections for canary and prod. This is part of the security baseline.

Service connections at management group scope, as used by the separate spoke canvas pipeline, are described in Prepare the spoke pipeline.

If the code repository lives on a different host than the customer's Azure DevOps (for example in the managed model, where it is synced from a GitHub Enterprise instance), you also need a service connection of that host for the mcp-code repository resource. See Repositories.

For the agent pool, the service connection of the infrastructure pipeline needs Contributor or Owner on the subscription that holds the job runners, and the pool service needs rights in Azure DevOps. See Pipelines and agents.

Checklist

  • [ ] Two groups exist; the maintainers group is role-assignable and has no members
  • [ ] Platform management group exists; subscriptions are placed under it
  • [ ] Administrative unit exists; its object ID is noted
  • [ ] Maintainers group: Owner (with all-roles condition) on the management group; Groups Administrator and User Administrator on the administrative unit; Application Developer in the directory
  • [ ] PIM: engineers group is eligible for the maintainers group, with approval
  • [ ] Deployment service principals exist per platform environment, with secrets stored or federated credentials set
  • [ ] Spoke identity: Graph permissions with admin consent, administrative unit role, state storage role
  • [ ] Service connections exist, verified, separate for canary and prod
  • [ ] If spokes create Azure DevOps or GitHub resources: Prepare spoke integrations is done