Skip to content

Greenfield Azure Baseline — Infrastructure & Identity Handover

Package: Baseline "Cloud Secure" [B] (part 1 of 2) · Milestone: M2a Scenario: Day-0 greenfield Azure client on GitHub Actions, no existing IaC. Ownership: Primarily [CO] Client-Owned — SnowOps provisions; you own and operate after handover.

This is the infrastructure and identity half of the Baseline package. The compliance-monitoring half is covered in the M2b Compliance Monitoring Handover. A full Baseline engagement delivers both.


What You Now Own

A hardened, policy-governed Azure subscription with secure networking, identity with MFA + PIM + break-glass, an AKS-ready foundation, and a complete CI/CD pipeline with policy gates. Everything is Terraform-managed and reproducible.

Layer Assets Module / Workflow
Subscription baseline F1, B3 modules/azure/baseline/, modules/azure/subscription-baseline/ (Mgmt Group, Policy, Defender, Log Analytics, MCSB)
Network F2, N5, N6 modules/azure/network-hub/, private-endpoint-policy/, nsg-baseline/
Compute (AKS-ready) F3, D4 modules/azure/aks-secure/ + Kyverno policies (policy/kyverno/)
Registry F4 modules/azure/acr/ (Premium, private endpoint, AAD-only)
Secrets F5 modules/azure/key-vault/ (Premium, RBAC mode, purge-protect)
State backend F6, B4 modules/azure/state-backend/, client-state-backend/
Identity H1, H2, H3, H5, H7, B2, B5 aad-baseline/, conditional-access/, pim-templates/, pim-azure-resources/, break-glass/, client-bootstrap/, apps/sp-inventory/
Data protection (policy) M1, M2, M3, M6 encryption-policy/, cmk/, tls-policy/, data-residency-policy/
Cost governance U1, U2 budget-alert/, tag-policy/
CI/CD C1, C2, C3 .github/workflows/terraform-plan-apply.yml, container-build-sign.yml, aks-deploy.yml
Sandbox hygiene X7 .github/workflows/sandbox-cleanup.yml

Module names above are the real on-disk paths under modules/azure/. Pin every module reference to a semver tag via the F11 registry — never ref=main.


The Identity Model You Are Inheriting

This is the most important thing to understand at handover. SnowOps follows Identity > Secrets — there are deliberately no long-lived cloud credentials anywhere in your pipeline.

Concept What it means for your team
Federated OIDC (B2) GitHub Actions authenticates to Azure via federated identity. No client secret exists to leak or rotate.
PIM — Azure resource roles (B5) Owner/Contributor/UAA are eligible, not standing. Activate just-in-time with MFA + justification; Tier-0 (Owner) is capped at 8h with approval, Tier-1 (Contributor) at 4h.
PIM — Entra directory roles (H3) Same model for directory roles, activated via the Graph PATCH rules in the runbook.
Break-glass (H7) Two emergency Global Admin accounts in a role-assignable group, excluded from all Conditional Access, with a severity-0 sign-in alert. These are your last-resort access — store the credentials per the ceremony in the H7 runbook (hardware FIDO2 + split-knowledge). Test break-glass sign-in quarterly.
Conditional Access (H2) 6 policies: MFA mandatory, Tier-0 phishing-resistant + compliant device, block legacy auth, geo-block, high/medium-risk gating. Every policy excludes the break-glass group.
SP credential hygiene (H5) sp-inventory-rotation.yml scans app-registration credentials weekly and opens a rotation PR for anything aged/expiring. Federated-OIDC SPs never go stale.

Day-one action for your team: confirm you can activate PIM, and run a break-glass sign-in drill so you're never locked out.


How to Deploy a Change (Your New Workflow)

Your infrastructure changes flow through the C1 pipeline (terraform-plan-apply.yml), which enforces the policy gates automatically:

1. Open a PR with a Terraform change
2. C1 runs `terraform plan` → posts the plan as a PR comment
3. The D3 OPA bundle runs against the plan JSON (post-plan gate)
4. CODEOWNER review + passing checks required (branch protection from C4)
5. Merge → C1 applies against the target environment (with environment gates)

Container workloads follow C2 (container-build-sign.yml): build → push to ACR by digest → Notation v2 sign → Syft SBOM → Grype scan. AKS deployments follow C3 (aks-deploy.yml): ArgoCD image override → sync → smoke probe → optional rollback drill.

The OPA gate (D3) and Kyverno admission policies (D4) mean non-compliant infrastructure cannot be applied — encryption, tagging, network isolation, and region constraints are enforced at plan-time and admission-time, not audited after the fact.


What This Delivers for Compliance

Control theme Framework reference Asset / Evidence
Logical access — least privilege, JIT SOC 2 CC6.1–CC6.3 · ISO 27001 A.8.2/A.8.3 PIM (B5/H3), Conditional Access (H2), RBAC (B3)
MFA enforced SOC 2 CC6.1 · ISO 27001 A.8.5 Conditional Access policy export (H2)
Encryption at rest / in transit SOC 2 CC6.7 · ISO 27001 A.8.24 Deny initiatives M1/M3 + CMK (M2)
Network security SOC 2 CC6.6 · ISO 27001 A.8.20/A.8.22 F2 topology, N5/N6, private endpoints
Audit logging SOC 2 CC7.2 · ISO 27001 A.8.15 Log Analytics (F1), diagnostic policies
Vulnerability management SOC 2 CC7.1 · ISO 27001 A.8.8 Defender for Cloud (F1/B3), image signing+scan (C2)

Full mappings: compliance/soc2/control-mapping.md, compliance/iso27001/control-mapping.md, compliance/cis-azure/control-mapping.md.


Verification at Handover

SnowOps signs off each asset against its manual test runbook (docs/runbooks/test/<id>.md) in a sandbox before handover. To independently verify your own environment:

  • terraform plan against each stack shows no drift (clean plan).
  • A deliberately non-compliant test PR (e.g. unencrypted storage) is blocked by the C1 OPA gate.
  • PIM activation works for at least one Tier-0 and one Tier-1 role.
  • Break-glass sign-in succeeds and fires the severity-0 alert.
  • Defender for Cloud is On with the MCSB initiative assigned (B3).
  • The C2 pipeline produces a signed image; notation verify succeeds.

Failure Modes You Should Know

Symptom Cause Response
Pipeline can't authenticate to Azure Federated OIDC subject mismatch (branch/environment changed) Update the federated credential subject in B2; the repo: prefix is validated.
Locked out of the subscription PIM eligibility misconfigured or expired Use break-glass (H7) — this is exactly what it's for.
terraform apply blocked by a Deny policy A resource violates M1/M3/N5/U2 Fix the resource, or file a D5 waiver (time-boxed) if it's a temporary, justified exception.
AKS pod rejected at admission Kyverno policy (D4) — unsigned image, latest tag, privileged container Sign the image / pin the tag / drop privilege. This is the gate working.

Removal / Offboarding Path

Every module ships with a verified terraform destroy path (DoD #8). Because you own the state and subscription ([CO]), offboarding from SnowOps does not strand your infrastructure:

  1. Module sources are pinned to public git tags — they keep resolving even without SnowOps.
  2. Run terraform destroy per stack to tear down, or simply keep operating the infrastructure yourself; nothing depends on SnowOps' tenancy.
  3. Revoke the SnowOps operator's PIM eligibility and any guest access.
  4. For a formal handover/exit, follow the engagement offboarding checklist (M3 deliverable — see the Brownfield Adoption guide's offboarding section).

Cost note: This baseline runs real Azure resources (AKS, Premium ACR/KV, Log Analytics). Per-module estimated costs are in each module README. Budget alerts (U1) are wired in to warn at your configured thresholds.


Next