Microsoft Defender for Cloud · Subscription / RBAC
Service Principals should not be assigned with administrative roles at the subscription and resource group level
Written and reviewed by Emnode · Last reviewed
What does the recommendation "Service Principals should not be assigned with administrative roles at the subscription and resource group level" check?
Flags any service principal (an app registration, enterprise application or managed identity) that holds a privileged Azure RBAC role at subscription or resource group scope, specifically Owner, Contributor or User Access Administrator. It inspects role assignments on the resource hierarchy, not the workload itself. It does not cover Microsoft Entra directory roles such as Global Administrator, it does not flag human user accounts, and it does not judge whether the privileged data-plane operations the principal performs are actually used. A principal granted a narrow built-in role such as Reader or a tightly scoped custom role does not trigger this finding.
Why does "Service Principals should not be assigned with administrative roles at the subscription and resource group level" matter?
A service principal authenticates with a client secret or certificate that often lives in a pipeline variable, a config file or a developer laptop, with no interactive sign-in, no MFA prompt and frequently no Conditional Access. If that credential leaks and the principal is Owner or Contributor on a subscription, the attacker inherits standing control-plane access to every resource under it: they can read storage, redeploy infrastructure, create new privileged assignments and pivot laterally, all without tripping a human-login alert. User Access Administrator is worse still, because it lets the principal grant itself any further role it lacks. Capping service principals at least privilege means a stolen automation credential exposes only the handful of resources that one job needs, not the whole estate.
How do I fix "Service Principals should not be assigned with administrative roles at the subscription and resource group level"?
- Enumerate the offending assignments so you know the blast radius before changing anything: 'az role assignment list --assignee <appId-or-objectId> --all -o table' lists every scope the principal holds, and you can confirm the privileged ones are Owner, Contributor or User Access Administrator.
- Replace each broad assignment with the narrowest role the workload genuinely needs at the tightest scope. For example grant 'Storage Blob Data Contributor' on a single resource group instead of Contributor on the subscription: 'az role assignment create --assignee <appId> --role "Storage Blob Data Contributor" --scope /subscriptions/<sub-id>/resourceGroups/<rg>', then remove the old one with 'az role assignment delete --assignee <appId> --role Contributor --scope /subscriptions/<sub-id>'.
- Codify least-privilege assignments in your Bicep or Terraform so the safe grant is the default. In Bicep, a 'Microsoft.Authorization/roleAssignments' resource pins the 'roleDefinitionId' and 'principalId' at module scope, and you can enforce the standard estate-wide with an Azure Policy assignment by looking the definition up at runtime rather than hardcoding a GUID: 'pid=$(az policy definition list --query "[?displayName==''Audit usage of custom RBAC roles'']\.name" -o tsv)'.
Remediation script · bash
# Find the highest-risk privileged assignments first: external accounts and blocked leavers holding Owner.
SUB="00000000-0000-0000-0000-000000000000"
# List Owners, with type and object id, so external and group principals are obvious.
az role assignment list \
--scope "/subscriptions/$SUB" \
--role Owner \
--query "[].{who:principalName, type:principalType, id:principalId}" -o table
# Remove an external partner's Owner assignment (work finished). Keep at least one Owner you control.
az role assignment delete \
--assignee "[email protected]" \
--role Owner \
--scope "/subscriptions/$SUB"
# Remove a deprecated (blocked) account's role assignment by object id.
# Blocking the Entra sign-in does NOT remove the assignment; delete it explicitly.
az role assignment delete \
--assignee-object-id "<blocked-user-object-id>" \
--scope "/subscriptions/$SUB"
# Consolidate the remaining legitimate Owners behind one Entra group, then make it eligible
# (just-in-time) via Privileged Identity Management so nobody holds standing Owner. Full walkthrough (console steps, edge cases and verification) in the lesson Apply least-privilege RBAC on Azure subscriptions.
Is "Service Principals should not be assigned with administrative roles at the subscription and resource group level" a false positive?
A deployment service principal that legitimately needs Contributor across a whole landing-zone subscription, for example the identity an Azure DevOps or GitHub Actions pipeline uses to provision the entire environment, will still flag even though the grant is intentional. The correct response is not to silence it blindly: scope the assignment to the resource groups the pipeline actually touches where possible, rotate its credential on a short cycle, and if subscription-wide Contributor is unavoidable, accept the finding through a documented exemption rather than weakening the rule for everyone.
More Subscription / RBAC controls
- Azure overprovisioned identities should have only the necessary permissions
- Blocked accounts with owner permissions on Azure resources should be removed
- Blocked accounts with read and write permissions on Azure resources should be removed
- Deprecated accounts with owner permissions should be removed from subscriptions
- External accounts with read permissions should be removed from subscriptions
- External accounts with write permissions should be removed from subscriptions
- Guest accounts with owner permissions on Azure resources should be removed
- Guest accounts with read permissions on Azure resources should be removed
- Guest accounts with write permissions on Azure resources should be removed
- Permissions of inactive identities in your Azure subscription should be revoked
- Privileged roles should not have permanent access at the subscription and resource group level
- There should be more than one owner assigned to subscriptions