AZ-104 · Skill Domain

Identity & Governance

Entra ID user and group management, least-privilege RBAC assignments, custom role definitions, Azure Policy initiatives, resource locks, and cost management — the security and compliance layer that everything else runs on top of.

2Projects
10Policy assignments
3RBAC groups
P1–P2Phase 1
01

Projects

01
Entra ID · RBAC · Custom Roles · MFA
Entra ID & Role-Based Access Control
User + group provisioning · least-privilege role assignments · custom role definition · MFA · sign-in audit logs

Simulated enterprise user onboarding by provisioning four Entra ID accounts across three security groups, assigning built-in roles at resource group scope using the principle of least privilege, and creating a custom role definition for a Storage Blob Reader Plus permission set that didn't exist in the built-in catalog. Verified the assignments by signing in as each test user and confirming the access boundaries held. Enabled MFA on all accounts and reviewed Entra ID sign-in audit logs.

Management Group Inherits down
Subscription 343a8a7e-… (VSE)
Resource Group rg-phase1-lab — assignments here
Resource Most granular scope
Group Role Scope
grp-developers Contributor RG
grp-ops VM Contributor RG
grp-readonly Reader RG
dev1 Storage Blob Reader Plus (custom) RG
View RBAC hierarchy diagram — project2-rbac-hierarchy.svg
  • Groups, not individual users — Role assignments are on security groups, not individual accounts. Adding a new developer means adding them to grp-developers — no new role assignments required. This is the correct enterprise pattern: manage group membership, not role assignments, as the team evolves.
  • Resource group scope, not subscription — Assignments scoped to rg-phase1-lab only. Scoping to subscription would give grp-developers Contributor access to every resource in the subscription — a significant blast radius for a lab. Narrowest scope that satisfies the requirement.
  • Custom role for gaps in built-in catalog — No built-in role provided exactly Storage Blob read access without additional permissions. Rather than assigning a broader role than necessary, a custom role was created with exactly the required action. This is the least-privilege approach applied at the permission level.
  • Test every assignment before declaring done — Signed in as each test user in a private browser session and verified access boundaries. A role assignment that hasn't been tested is an assumption, not a control.
Why group-based RBAC matters at scale

An organization with 200 Azure resources and 50 engineers can't maintain individual role assignments — the combination count grows faster than anyone can manage. Group-based RBAC means access is controlled in one place (group membership) and role assignments are stable infrastructure. New hire: add to group. Offboarding: remove from group. All access changes flow from that one action.

Microsoft Entra ID RBAC Security Groups Custom Roles MFA Sign-in Audit Logs Least Privilege
02
Azure Policy · Resource Locks · Cost Management
Azure Policy, Locks & Cost Management
Policy initiative · Deny + Audit + Inherit effects · resource locks · budget alerts · 10 assignments on lab RG

Built a governance baseline using Azure Policy — three policies bundled into an initiative, deployed with Deny effect to prevent out-of-region resources and enforce required tags, and Audit effect for non-destructive compliance reporting. Verified the controls by deliberately triggering the location policy denial and the resource lock block, capturing both as evidence. Configured budget alerts at 80% actual and 100% forecast to prevent cost overruns. The governance pattern established here was extended in Phase 4: the lab resource group carried 10 active policy assignments throughout all subsequent projects.

Assignment Effect
require-tag-env Deny
require-tag-owner Deny
allowed-locations-wus3 Deny
appsvc-https-only Deny
appsvc-managed-identity Deny
appsvc-no-remote-debug Deny
inherit-tag-env Inherit
inherit-tag-owner Inherit
inherit-tag-project Inherit
inherit-tag-phase Inherit
  • Audit before Deny for new policies — The managed-disk audit policy was intentionally set to Audit rather than Deny. Switching an existing environment to Deny without first understanding the compliance state causes unexpected deployment failures. Audit → review → Deny is the production-safe rollout sequence.
  • Initiatives over standalone assignments — Even with three policies, bundling into an initiative made compliance reporting cleaner and assignment to new scopes a single action. Always start with an initiative — standalone assignments don't scale beyond a handful of policies.
  • Tag inheritance via policy, not manual tagging — Tags on the resource group propagate automatically to all resources via inherit-tag-* policy assignments. Manual tagging is inconsistent and breaks. Policy-enforced inheritance is the only reliable approach at scale.
  • Policy definition IDs — never hardcode — Policy definition GUIDs change between CLI versions. Always query: az policy definition list --query "[?displayName=='Allowed locations'].name" -o tsv. One character difference caused significant debugging time.
  • Forecast alert over actual spend alert — A 100% actual spend alert tells you money has already been spent. A 100% forecast alert fires before you hit the limit and leaves time to react. In production the forecast alert is the one that matters.
Policy initiative — exported definition
{
  "name": "initiative-baseline-governance",
  "properties": {
    "displayName": "Baseline Governance Initiative",
    "description": "Location, tagging, and disk compliance",
    "policyDefinitions": [
      {
        "policyDefinitionId": "/providers/Microsoft.Authorization/
  policyDefinitions/e56962a6-4747-49cd-b67b-bf8b01975c4f",
        "parameters": {
          "listOfAllowedLocations": {
            "value": ["westus3"]
          }
        }
      },
      {
        "policyDefinitionId": "/providers/Microsoft.Authorization/
  policyDefinitions/96670d01-0a4d-4649-9c89-2d3abc0a5025",
        "parameters": {
          "tagName": { "value": "environment" }
        }
      },
      {
        "policyDefinitionId": "/providers/Microsoft.Authorization/
  policyDefinitions/06a78e20-9358-41c9-923c-fb736d382a4d"
      }
    ]
  }
}
⚠ Gotcha — policy remediation has a propagation delay

Remediation tasks fail immediately after policy assignment because the managed identity needs 30–60 seconds to propagate through Entra ID. Wait 60 seconds and use unique names for retry attempts. Fallback: az resource tag --is-incremental for immediate tagging without waiting on remediation.

Azure Policy Policy Initiatives Deny Effect Audit Effect Tag Inheritance Resource Locks Cost Management Budget Alerts
Policy location denial
Policy denial — location blocked
Policy details
Policy — location assignment
Delete lock blocking deletion
Delete lock — deletion blocked
02

Lessons Learned

Governance is infrastructure, not afterthought
Configuring policy assignments, RBAC groups, and budget alerts before deploying any workload — not after — is the correct sequence. Retrofitting governance onto an existing environment is harder, riskier, and produces gaps. The P2 governance baseline was active for every project in Phases 3 and 4, enforcing location and tagging compliance automatically without any manual intervention.
ReadOnly locks block more than expected
A ReadOnly lock prevents writes to resource properties but also blocks operations that internally require write access to metadata — including some operations that appear read-only, such as listing storage account keys. Understanding the full scope of what a lock blocks before applying it in production prevents unexpected application failures.
Policy evaluation is asynchronous
After assigning a policy, Azure evaluates existing resources asynchronously — the compliance dashboard takes 5–15 minutes to reflect the current state. A policy that appears to have no effect immediately after assignment is likely still propagating. Trigger immediate evaluation with az policy state trigger-scan rather than assuming misconfiguration.
RBAC and governance work together
RBAC controls what a principal can do. Azure Policy controls what can be deployed, regardless of who deploys it. A Contributor with full RBAC access cannot deploy a resource to a blocked region — the policy evaluation happens before the deployment is accepted. These are complementary controls, not alternatives: RBAC handles identity; Policy handles compliance.
Initiatives scale; standalone assignments don't
An initiative exported as JSON can be applied to hundreds of subscriptions in a single pipeline run. A collection of standalone policy assignments must be individually re-applied to each scope. Starting with an initiative from day one — even when only managing three policies — is the correct pattern because it costs nothing extra and makes the governance layer portable.
Test every control you deploy
Deliberately triggering the location policy denial and the resource lock block — and capturing both as evidence — demonstrates that the controls actually work. An untested policy is an assumption, not a control. In a production environment, unverified governance is the same as no governance: it provides false confidence without providing actual protection.