Skip to content

Manual Test Runbook — U2: Require Mandatory Tags (Azure Policy)

Owner: Sagar  |  Time: ~10 min (Parts A + B) · +15 min (optional Part C live apply) · +15 min (optional Part D Deny drill)  |  Sandbox: snowops-sandbox-01

Promotes U2 (modules/azure/tag-policy/) from 🟦 Code Complete → 🟩 Shipped. Part C/D cost ~$0 (policy assignments are free; the drill creates and deletes a single resource group). U2 is validate-only in the automated suite — a live apply mutates the subscription's policy state, so the apply + Deny drill are manual here (same pattern as M6/N5/J2/H3/B5). The "Require a tag" built-ins are Deny-only, so the rollout knob is enforce = false → true (no Audit effect).


Prerequisites

  • Sandbox subscription access active (PIM activated if required)
  • az login done; az account show confirms the sandbox subscription is selected
  • Identity has Owner OR Resource Policy Contributor on the sandbox sub
  • Local tooling: terraform >= 1.6, go >= 1.22, az CLI >= 2.50
  • Working directory: repo root

Steps

Part A — terraform fmt + validate (offline, ~3 min)

  1. Module + example:
terraform -chdir=modules/azure/tag-policy fmt -recursive -check
terraform -chdir=modules/azure/tag-policy init -backend=false -input=false
terraform -chdir=modules/azure/tag-policy validate

terraform -chdir=modules/azure/tag-policy/examples/basic init -backend=false -input=false
terraform -chdir=modules/azure/tag-policy/examples/basic validate

Expected: Success! The configuration is valid. for both.

  1. Offline Terratest case:
cd tests/terratest
go test -v -timeout 5m ./modules/azure/... -run TestTagPolicyValidate

Expected: PASS.

Part B — full Terratest suite (offline, ~3 min)

  1. bash cd tests/terratest go test -count=1 -timeout 15m ./...

Expected: full offline suite green (35 top-level tests across all packages).

Part C — live apply, rollout (enforce=false) mode first (sandbox, ~15 min, ~$0)

  1. Verify the curated default built-in GUIDs resolve in your tenant:
az policy definition list \
  --query "[?policyType=='BuiltIn' && contains(displayName,'Require a tag')].{name:name, display:displayName}" -o table

If a curated default is missing/renamed, pass a corrected var.resource_tag_policy_id.

  1. Apply the example in rollout mode (enforce = false — never blocks unrelated sandbox resources):
cd modules/azure/tag-policy/examples/basic
terraform init -input=false
terraform apply -auto-approve \
  -var "subscription_id=$SNOWOPS_SANDBOX_SUBSCRIPTION_ID" \
  -var "tenant_id=$SNOWOPS_SANDBOX_TENANT_ID" \
  -var "enforce=false"
  1. Confirm the initiative + assignment exist and the per-tag references are present:
az policy assignment show --name snowops-mandatory-tags \
  --query "{name:name, enforcement:enforcementMode}" -o json
az policy set-definition show --name snowops-mandatory-tags \
  --query "policyDefinitions[].policyDefinitionReferenceId" -o tsv

Expected: assignment present, enforcementMode = DoNotEnforce; reference IDs resource/Environment, resource/Owner, … and rg/Environment, … listed.

Part D — Deny drill (optional, ~15 min)

Proves the catalog criterion: "untagged create denied." Re-apply with enforce = true, then attempt a create with a tag missing.

  1. Flip to enforce:
terraform apply -auto-approve \
  -var "subscription_id=$SNOWOPS_SANDBOX_SUBSCRIPTION_ID" \
  -var "tenant_id=$SNOWOPS_SANDBOX_TENANT_ID" \
  -var "enforce=true"
  1. Attempt to create a resource group WITHOUT the mandatory tags (the rg/* references should block it). Allow a few minutes for the assignment to take effect:
az group create -n u2-probe-rg -l eastus   # no --tags

Expected: the create is denied with a RequestDisallowedByPolicy error naming the SnowOps mandatory-tags initiative. (If it succeeds, the assignment has not propagated yet — retry after ~5–10 min.)

  1. Confirm a fully-tagged create succeeds:
az group create -n u2-ok-rg -l eastus \
  --tags Environment=sandbox Owner=sagar CostCenter=platform Compliance=SOC2 Client=internal

Expected: succeeds.

  1. Cleanup the probes:

    az group delete -n u2-ok-rg --yes --no-wait
    az group delete -n u2-probe-rg --yes --no-wait 2>/dev/null || true
    

Pass criteria

  • Part A — module + example validate; TestTagPolicyValidate passes
  • Part B — full offline Terratest suite passes (35 top-level)
  • (Part C) assignment created in DoNotEnforce mode; per-tag references present
  • (Part D) an untagged RG create is denied under enforce = true; a fully-tagged create succeeds
  • All test resources removed; no orphaned probe RGs

Teardown

cd modules/azure/tag-policy/examples/basic
terraform destroy -auto-approve \
  -var "subscription_id=$SNOWOPS_SANDBOX_SUBSCRIPTION_ID" \
  -var "tenant_id=$SNOWOPS_SANDBOX_TENANT_ID"
az group delete -n u2-ok-rg --yes --no-wait 2>/dev/null || true   # if Part D ran

Destroying the assignment stops future tag enforcement; resources created while it was active are unaffected.


Sign-off

  • Tester: _  |  Date: _  |  Result: PASS / FAIL / N/A
  • Notes: