Platform Landing Zone: Part 2 - Building the Foundation for Enterprise Azure
Stephen Tulp
December 16, 2025
4 minutes to read
In Part 1 we deployed the foundational Platform Landing Zone architecture using Azure Verified Modules, GitHub Copilot, and Bicep. Today we will introduce CI/CD using GitHub Actions to automate the deployment process, ensuring that our Platform Landing Zone is consistently and reliably deployed across our Azure environment.
Overview
The table below outlines the GitHub Action Release workflows that we will implement across the different deployments.
| Repo | Pipeline | Description |
|---|---|---|
| adventCalendar-2025 | Pull Request | Pull Request validation into Main |
| adventCalendar-2025 | Release - Platform | Deployment of the Platform Services resources |
| adventCalendar-2025 | Release - Platform (Canary) | Deployment of the Platform Services resources |
| adventCalendar-2025 | Release - Platform Connectivity | Deployment of the Platform Connectivity Landing Zone resources |
| adventCalendar-2025 | Release - Platform Management | Deployment of the Platform Management Landing Zone resources |
| adventCalendar-2025 | Repository Management | Repository management activities (GH Labels, Publish Wiki, Releases, Stale PRs ) |
| adventCalendar-2025 | PR - Labeler | Apply GitHub labels to GitHub Issues and Pull Requests |
There are also reusable workflows that have been created to support the Azure Landing Zone architecture.
| Repo | Reusable Workflow | Used By |
|---|---|---|
| adventCalendar-2025 | Reusable Workflow: Deploy | Release - Platform, Release - Platform (Canary), Release - Platform Connectivity, Release - Platform Management |
Setting up Identities
To enable GitHub Actions to deploy resources into Azure, we need to create a series of Application Registrations and assign them the appropriate roles at the required scopes. We will use OpenID Connect (OIDC) to allow GitHub Actions to authenticate to Azure without needing to store long-lived credentials in GitHub Secrets.
The table below outlines the application registrations that we will need, the associated permissions, and the GitHub Subject Identifiers that will be used to link the application registrations to the GitHub Environments.
| Application Registration | Applied Scope | Azure RBAC | GitHub Subject Identifier |
|---|---|---|---|
| app-registration-gh-platform-landing-zones-canary | Management Group (mg-alz) | Contributor, User Access Administrator |
platform_canary |
| app-registration-gh-platform-landing-zones-tenant | Management Group (mg-alz) | Contributor, User Access Administrator |
platform_tenant |
| app-registration-gh-platform-connectivity-landing-zones | Management Group (mg-alz) | Contributor, User Access Administrator |
platform_connectivity |
| app-registration-gh-platform-management-landing-zones | Management Group (mg-alz) | Contributor, User Access Administrator |
platform_management |
| app-registration-gh-whatif | Tenant Root | Reader |
whatif |
Bicep Module with Entra Extension
There is a Bicep modules in the Advent Calendar 2025 Repository that uses the Bicep Microsoft Graph extension to create all the required Application Registrations and federated credentials. Use the VS Code Bicep deployment feature for this.
Lokka
Using Lokka we can quickly create the required Application Registrations and federated credentials using natural language. This will need to be done for each application registration with details updated to match your environment.
Prompt:
Hey Lokka, create an application registration for GitHub OIDC using federated credentials called
app-registration-gh-whatifusing GitHub OrganisationInsight-Services-APACand the repo asazure-landing-zones-perth-extended-zoneand GitHub Environment namewhatif. Apply the app registration to themg-alzmanagement group with the roles ofReader
GitHub Environments
The following GitHub Environments have been created to support the Azure Landing Zone architecture.
| Environment Name | Description | Comments |
|---|---|---|
| platform_services | Platform Services Landing Zone | Default |
| platform_connectivity | Platform Connectivity Landing Zone environment | Default |
| platform_identity | Platform Identity Landing Zone environment | Default |
| epac_canary | Enterprise Policy as Code Canary deployment | Default |
| epac_plan | Enterprise Policy as Code Plan (Canary and Tenant) | Default |
| epac_tenant_policy | Enterprise Policy as Code Tenant Policy deployment | Default |
| epac_tenant_roles | Enterprise Policy as Code Tenant Role deployment | Default |
| iaas_dev | IaaS Landing Zone Development environment | Custom |
| iaas_uat | IaaS Landing Zone User Acceptance Testing environment | Custom |
| iaas_prd | IaaS Landing Zone Production environment | Custom |
These environment can be configured and changed in code to be different, however the defaults are recommended for the purposes of completeness.
Approval gates, timers, and other measures have been configured on these environments to prevent automatic deployment without first having human intervention. As a default, all environments will have the same approval gate of:
- One person to approve
- Code must be in
main - Cannot self approve