Someone on your team runs terraform apply from their laptop. The change goes straight to production. There’s no PR, no review, no record of what changed or why. A week later, something breaks in the landing zone and nobody can explain what happened. You check the Azure activity log and find a dozen manual changes made by three different engineers over the past month — all from local terminals, all with permanent admin credentials stored in .env files.
This is not a process problem. It’s an architecture problem. When your pipeline is “run it locally and hope,” every deployment is a single point of failure.
A GitOps approach fixes this. Every change to the infrastructure is a pull request. Every PR triggers a plan. Every plan gets reviewed before it merges. The pipeline authenticates with a short-lived token, not a stored secret. Nothing reaches Azure without a second set of eyes on the predicted diff.
In 2026, the standard for these pipelines is Workload Identity Federation (OIDC), which eliminates static API keys, and Shift-Left Testing using tools like PSRule. Here’s how to build it with GitHub Actions to deploy Azure Verified Modules (AVM).
1. The PR-Driven Plan-First Workflow
The goal is simple: no change reaches Azure without a human review of the predicted impact. We implement a Plan-First workflow.
PR-Driven Plan-First Workflow
When you open a PR, the pipeline runs a “What-If” analysis and posts the result as a collapsible comment. Your reviewer sees exactly which resources will be created, modified, or destroyed before clicking merge. No surprises.
2. Secure Authentication with OIDC
Storing AZURE_CLIENT_SECRET in GitHub Secrets is a high-risk legacy pattern. If the secret leaks, an attacker has permanent access until someone notices and rotates it. You probably won’t notice for a while. OpenID Connect (OIDC) solves this by using a trust relationship between GitHub and Entra ID instead of a static credential.
GitHub OIDC Security Boundary
In 2026, we use Environment-scoped Federated Credentials. This ensures that the production deployment identity can only be used by a workflow running in the production environment branch on GitHub, providing a cryptographic boundary between your dev and prod infrastructure.
3. Shift-Left Testing with PSRule
Compliance should be caught in the pipeline, not in a post-deployment audit. This is the boring part. Do it anyway.
We use PSRule for Azure to validate our Bicep and Terraform code against the Well-Architected Framework (WAF) before it is deployed.
# GitHub Actions: PSRule WAF Compliance
- name: PSRule WAF Compliance
uses: microsoft/ps-rule@v2
with:
modules: PSRule.Rules.Azure
inputPath: live/
If a developer attempts to deploy a VNet without a diagnostic setting or an unencrypted Storage Account, PSRule fails the build, preventing the non-compliant code from ever reaching the main branch.
4. Safe State Storage Architecture
Your Terraform state files or Bicep Deployment Stacks contain the blueprint of your entire cloud estate. Treat them accordingly.
Safe State Storage Architecture
By using Private Endpoints and RBAC-only access (disabling storage account keys), you ensure that only your authorized CI/CD runners can read or write the state.
5. Bicep Deployment Stacks: The Native Way
For Bicep users, Deployment Stacks (GA in 2025) provide the state management and “Action on Unmanage” features previously only found in Terraform.
az stack mg create \
--name "lz-management-layer" \
--management-group-id "mg-platform" \
--deny-settings-mode "denyDelete" \
--action-on-unmanage "deleteResources"
The --deny-settings-mode denyDelete flag acts as a native resource lock, preventing anyone (including owners) from manually deleting resources managed by the stack.
Key Takeaways
- Peer Review is Mandatory: Use PR-driven workflows to ensure every platform change has a second pair of eyes.
- Go Secret-less: Use OIDC for all automation identities. Treat static client secrets as technical debt.
- Validate early: Use PSRule to catch WAF violations in the pipeline rather than the portal.
- Protect the State: Isolate your state storage using Private Link and RBAC to prevent tampering.
Next Steps:
- Read Cost Governance in the Landing Zone: Tagging Enforcement, Budgets, and FinOps Automation to add cost estimation (Infracost) to your PR comments.
- Read Day-2 Operations: Maintaining and Evolving Your Azure Landing Zone to implement automated drift detection using these same pipelines.
