Azure Policy is a powerful governance tool, but when policies are created manually through the portal they quickly become undocumented and inconsistent across environments. By storing policy definitions in a Git repository and deploying them through GitHub Actions, you get full auditability, peer review, and automated enforcement.
Prerequisites
You will need an Azure subscription, a service principal with the Resource Policy Contributor role, and GitHub repository secrets configured for authentication.
# Create service principal and assign role
$sp = New-AzADServicePrincipal -DisplayName "github-policy-deployer"
New-AzRoleAssignment -ObjectId $sp.Id `
-RoleDefinitionName "Resource Policy Contributor" `
-Scope "/subscriptions/$(Get-AzContext).Subscription.Id" Structuring Your Repository
Organise policies in a consistent folder structure so the GitHub Actions workflow can discover and deploy them automatically.
policies/
definitions/
allowed-locations.json
require-tags.json
initiatives/
security-baseline.json
assignments/
prod-subscription.json Deploying Policies with GitHub Actions
The following workflow deploys all policy definitions whenever changes are pushed to the main branch.
name: Deploy Azure Policies
on:
push:
branches: [main]
paths: ['policies/**']
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: azure/login@v2
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Deploy policy definitions
run: |
foreach ($file in Get-ChildItem policies/definitions/*.json) {
az policy definition create --name $file.BaseName \
--rules (Get-Content $file.FullName -Raw | ConvertFrom-Json).policyRule \
--mode All
}
shell: pwsh Enforcing Tag Compliance
A common first policy is requiring specific tags on all resource groups. Here is the JSON definition.
$policy = @{
"if" = @{
"field" = "type"
"equals" = "Microsoft.Resources/subscriptions/resourceGroups"
}
"then" = @{
"effect" = "deny"
"details" = @{
"requiredTags" = @("Environment","Owner","CostCenter")
}
}
} | ConvertTo-Json -Depth 10
$policy | Out-File "policies/definitions/require-rg-tags.json" Summary
Treating Azure Policy as code significantly improves governance consistency. Every change is reviewed, tested, and deployed in a controlled manner — eliminating the risk of accidentally applying overly restrictive policies in production. Combined with Azure Policy’s built-in compliance reporting, you gain end-to-end visibility of your governance posture.