Manual Test Runbook — N5: Deny Public Network Access on PaaS (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 N5 (
modules/azure/private-endpoint-policy/) from 🟦 Code Complete → 🟩 Shipped. Part C/D cost ~$0 (policy assignments are free; the drill creates and deletes a single storage account). N5 is validate-only in the automated suite — a live apply mutates the subscription's policy state and the built-in GUIDs are sourced per-tenant, so the apply + Deny drill are manual here (same pattern as M1/J2/H3/B5).
Prerequisites
- Sandbox subscription access active (PIM activated if required)
-
az logindone;az account showconfirms 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)
- Module + example:
terraform -chdir=modules/azure/private-endpoint-policy fmt -recursive -check
terraform -chdir=modules/azure/private-endpoint-policy init -backend=false -input=false
terraform -chdir=modules/azure/private-endpoint-policy validate
terraform -chdir=modules/azure/private-endpoint-policy/examples/basic init -backend=false -input=false
terraform -chdir=modules/azure/private-endpoint-policy/examples/basic validate
Expected: Success! The configuration is valid. for both.
- Offline Terratest case:
cd tests/terratest
go test -v -timeout 5m ./modules/azure/... -run TestPrivateEndpointPolicyValidate
Expected: PASS.
Part B — full Terratest suite (offline, ~3 min)
bash cd tests/terratest go test -count=1 -timeout 15m ./...
Expected: full offline suite green (33 top-level tests across all packages).
Part C — live apply, Audit mode first (sandbox, ~15 min, ~$0)
- Verify the curated default built-in GUIDs resolve in your tenant (N5 bundles stable well-known IDs, but confirm before a Deny rollout):
az policy definition list \
--query "[?policyType=='BuiltIn' && contains(displayName,'public network access')].{name:name, display:displayName}" -o table
If a curated default is missing/renamed, pass a corrected var.policies map.
- Apply the example in Audit mode (default — never blocks unrelated sandbox resources):
cd modules/azure/private-endpoint-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 "effect=Audit"
- Confirm the initiative + assignment exist:
az policy assignment show --name snowops-private-endpoint \
--query "{name:name, enforcement:enforcementMode, effect:parameters.effect.value}" -o json
Expected: assignment present; effect = Audit.
Part D — Deny drill (optional, ~15 min)
Proves the catalog criterion: "public PaaS create attempt denied." Re-apply with
effect = "Deny"then attempt a non-compliant create.
- Flip to Deny:
terraform apply -auto-approve \
-var "subscription_id=$SNOWOPS_SANDBOX_SUBSCRIPTION_ID" \
-var "tenant_id=$SNOWOPS_SANDBOX_TENANT_ID" \
-var "effect=Deny"
- Attempt to create a storage account WITH public network access enabled (the
storage_public_access_disabledreference should block it). Allow a few minutes for the assignment to take effect:
az group create -n n5-probe-rg -l eastus
az storage account create -n n5probe$RANDOM -g n5-probe-rg -l eastus \
--sku Standard_LRS --public-network-access Enabled
Expected: the create is denied with a RequestDisallowedByPolicy error
naming the SnowOps private-endpoint initiative. (If it succeeds, the policy
assignment has not propagated yet — retry after ~5–10 min, or confirm the
built-in supports Deny via az policy definition show.)
- Cleanup the probe:
Pass criteria
- Part A — module + example validate;
TestPrivateEndpointPolicyValidatepasses - Part B — full offline Terratest suite passes (33 top-level)
- (Part C) assignment created in Audit mode; curated GUIDs resolve
- (Part D) a public-network-access storage create is denied under
effect = Deny - All test resources removed; no orphaned probe RG
Teardown
cd modules/azure/private-endpoint-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 n5-probe-rg --yes --no-wait # if Part D ran
Destroying the assignment stops future Deny enforcement; resources created while it was active are unaffected.
Sign-off
- Tester: _ | Date: _ | Result: PASS / FAIL / N/A
- Notes: