Hop til hovedindhold

Custom Entra ID Role — EnergyConnect Infrastructure Deployer

Overview​

Each EnergyConnect environment uses an Azure DevOps service connection (SC) to deploy infrastructure. These service connections are backed by Entra ID app registrations with federated credentials.

Rather than granting broad built-in roles (such as Directory Writers or Application Administrator) or tenant-wide Graph API permissions (such as Group.ReadWrite.All), each SC gets the least privilege needed:

  1. A custom Entra ID role — EnergyConnect Infrastructure Deployer — that can only create (as owner) and read Entra objects.
  2. The Graph application permission Application.ReadWrite.OwnedBy — updates, credential rotation and app role assignments, limited to app registrations / service principals the SC owns.
  3. Ownership of the Entra objects its environment deploys. Updates of groups rely on ownership alone.

Result: an SC can only change the apps, service principal and groups of its own environment — not other environments, other customers or anything else in the tenant.

Design Principles​

  • Create as owner, update by ownership. All create permissions are createAsOwner, so the SC automatically owns what it creates. There are no tenant-wide update permissions in the role.
  • One role per tenant. The role is defined once per Entra ID tenant and assigned to each environment's SC at directory scope (required for create permissions).
  • Only one Graph app permission. Application.ReadWrite.OwnedBy is the only Graph application permission; it is scoped to owned objects. AppRoleAssignment.ReadWrite.All, Group.ReadWrite.All etc. are not granted.

What the Deployment Does​

The infrastructure deployment (Bicep with extension microsoftGraphV1) performs these Entra ID operations:

OperationBicep resource typeAllowed by
Create / update app registrations (Client.Auth, AdvancedVEE)Microsoft.Graph/applicationsapplications/createAsOwner + Application.ReadWrite.OwnedBy
Create / update the Client.Auth service principalMicrosoft.Graph/servicePrincipalsservicePrincipals/createAsOwner + Application.ReadWrite.OwnedBy
Create / update the 9 environment groups (ec-{env}-{customer}-*)Microsoft.Graph/groupsgroups.security/createAsOwner + ownership
Create the 3 shared customer groups (ec-{customer}-kunde-*) — first environment onlyMicrosoft.Graph/groupsgroups.security/createAsOwner
Assign app roles to groups (on the owned Client.Auth service principal)Microsoft.Graph/appRoleAssignedToOwnership + Application.ReadWrite.OwnedBy
Rotate the OIDC client secret (pipeline)Graph addPasswordApplication.ReadWrite.OwnedBy

Permissions​

Custom role​

PermissionWhy
applications/createAsOwnerCreate app registrations (Client.Auth, AdvancedVEE). The SC becomes owner.
applications/standard/readRead app registrations (Graph extension resolves apps by uniqueName).
servicePrincipals/createAsOwnerCreate the enterprise app (service principal). The SC becomes owner.
servicePrincipals/standard/readRead service principals, including appRoles for appRoleAssignedTo.
groups.security/createAsOwnerCreate security groups only (not M365 groups). The SC becomes owner.
groups/standard/readRead groups (groups.security/standard/read does not exist).

Deliberately not included (all are tenant-wide): applications/*/update, applications/credentials/update, servicePrincipals/basic/update, groups.security/basic/update, groups.security/members/update, groups.security/owners/update, servicePrincipals/appRoleAssignedTo/update (not needed: owning the Client.Auth service principal is enough to assign its app roles — verified on fm qa, October 2026). With members/update an SC could add itself to any security group in the tenant.

Graph application permission​

PermissionWhy
Application.ReadWrite.OwnedByUpdate owned app registrations / service principals, assign their app roles to groups and create/rotate their client secrets. Also declared under API permissions on the SC's app registration so it is visible as a consented requirement.

Management​

Creating or Updating the Role​

# Requires: Privileged Role Administrator or Global Administrator
az login --tenant <tenant-id>
./Infrastructure/Scripts/entra-id/Set-EntraCustomRole.ps1

Viewing Current Permissions​

In the Entra ID portal: Roles and administrators → search for "EnergyConnect Infrastructure Deployer" → Permissions tab.

az rest --method GET `
--url 'https://graph.microsoft.com/v1.0/roleManagement/directory/roleDefinitions' `
--query "value[?displayName=='EnergyConnect Infrastructure Deployer'].rolePermissions[0].allowedResourceActions"