Skip to content

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 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/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.

  1. 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)

  1. 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)

  1. 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.

  1. 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"
  1. 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.

  1. Flip to Deny:
terraform apply -auto-approve \
  -var "subscription_id=$SNOWOPS_SANDBOX_SUBSCRIPTION_ID" \
  -var "tenant_id=$SNOWOPS_SANDBOX_TENANT_ID" \
  -var "effect=Deny"
  1. Attempt to create a storage account WITH public network access enabled (the storage_public_access_disabled reference 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.)

  1. Cleanup the probe:
az group delete -n n5-probe-rg --yes --no-wait

Pass criteria

  • Part A — module + example validate; TestPrivateEndpointPolicyValidate passes
  • 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: