Manage Azure Firewall Policy rules using CSV files, Bicep, PowerShell, and Azure DevOps. This repository provides Infrastructure as Code (IaC) tooling to export, validate, and deploy firewall rules with automated PR validation to ensure quality before deployment.
- π CSV-based Rule Management - Edit firewall rules in spreadsheet-friendly CSV format
- β Automated Validation - PR checks ensure rules are properly formatted before merge
- π Azure DevOps Integration - CI/CD pipelines for deployment automation
- ποΈ Hub Network Deployment - Complete hub-and-spoke network infrastructure
- οΏ½ Private DNS Zones - Optional deployment of Azure Private Link DNS zones for private endpoints
- οΏ½π Export Existing Rules - Extract current rules from Azure Firewall Policy to CSV
- π Bidirectional Sync - Export from Azure, edit locally, deploy back to Azure
- Quick Start
- Prerequisites
- Initial Setup
- Working with Firewall Rules
- Pull Request Validation
- Deployment
- Documentation
- Credits
# 1. Clone the repository
git clone https://github.com/awood-ops/AzureFirewallRulesAsCode.git
cd AzureFirewallRulesAsCode
# 2. Configure environment
Copy-Item config/prd/.env.template config/prd/.env
# Edit config/prd/.env with your values
# 3. Import environment variables
.\scripts\Set-EnvParams.ps1
# 4. Create Log Analytics workspace
.\scripts\New-LogAnalyticsWorkspace.ps1
# 5. Deploy hub network
.\pipeline-scripts\Deploy-Infrastructure.ps1
# 6. Validate firewall rules CSV
.\pipeline-scripts\Test-FirewallRulesCsv.ps1
# 7. Deploy firewall rules
.\pipeline-scripts\Invoke-DeployFirewallPolicyRules.ps1- Azure Subscription with appropriate permissions
- PowerShell 7+
- Azure CLI or Azure PowerShell modules
- Bicep CLI (for infrastructure deployment)
- VS Code (recommended) with Azure extensions
- Azure DevOps (for CI/CD pipelines)
Start by provisioning a Log Analytics workspace for monitoring and diagnostics:
.\scripts\New-LogAnalyticsWorkspace.ps1Environment variables are managed via .env files located in config/{environment}/:
- Production:
config/prd/.env - Testing:
config/testing/.env
Required variables:
ENVIRONMENT_CODE="prd"
WORKLOAD_CODE="hub"
LOCATION="eastus"
COMPANY_CODE="contoso"
SUBSCRIPTION_ID="00000000-0000-0000-0000-000000000000"
LOG_ANALYTICS_SUBSCRIPTION_ID="00000000-0000-0000-0000-000000000000"
LOG_ANALYTICS_RESOURCE_GROUP_NAME="rg-logs-prd"
LOG_ANALYTICS_WORKSPACE_NAME="log-hub-prd"
VNET_ADDRESS_PREFIX="10.0.0.0/20"
FIREWALL_PREMIUM_ENABLED="true"
FIREWALL_INSIGHTS_ENABLED="true"
DEPLOY_PRIVATE_DNS_ZONES="true"
DIAGNOSTICS_ENABLED="true"Local setup:
.\scripts\Set-EnvParams.ps1Note: This will reload VS Code to apply environment variables
Pipeline setup:
Variables are automatically imported during the "Import Environment Variables from File" step.
Deploy the hub-and-spoke network infrastructure:
.\pipeline-scripts\Deploy-Infrastructure.ps1This uses Azure Verified Modules and Azure Deployment Stacks for robust infrastructure provisioning.
Private DNS Zones:
The deployment can optionally create Azure Private Link DNS zones for all Azure services. These zones enable private endpoint DNS resolution for services like Storage, Key Vault, SQL Database, etc.
- Enable: Set
DEPLOY_PRIVATE_DNS_ZONES="true"- Recommended for hub networks that will host private endpoints - Disable: Set
DEPLOY_PRIVATE_DNS_ZONES="false"- Use if you have centralized DNS zones elsewhere or don't use private endpoints
The module automatically:
- Deploys ~70 private DNS zones for Azure services (blob, file, vault, sql, etc.)
- Links zones to your hub VNet for DNS resolution
- Follows Azure Landing Zone best practices
Expected result:
βββββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββββ
β Export β βββ> β Edit β βββ> β Validate β βββ> β Deploy β
β from Azure β β CSV β β Rules β β to Azure β
βββββββββββββββ ββββββββββββ ββββββββββββ ββββββββββββββ
Extract rules from your current Azure Firewall Policy:
.\pipeline-scripts\Export-AzFirewallPolicyRulesToCsv.ps1 `
-SubscriptionId "00000000-0000-0000-0000-000000000000" `
-ResourceGroupName "rg-firewall-prd" `
-FirewallPolicyName "afwp-hub-prd" `
-OutputPath ".\config\parameters\FirewallRules\FirewallRules.csv"Open config/parameters/FirewallRules/FirewallRules.csv and make changes:
- Add new rules - Copy existing rows and modify
- Update priorities - Change rule collection priorities
- Modify destinations - Update FQDNs, IPs, or ports
- Change actions - Switch between Allow/Deny
Example CSV structure:
RuleCollectionGroup,RuleCollectionGroupPriority,RuleCollectionName,RuleCollectionPriority,RuleCollectionAction,RuleCollectionType,RuleType,RuleName,SourceType,Source,Protocols,TerminateTLS,DestinationPorts,DestinationType,Destination
DevOpsAgents,110,GitHub,180,Allow,FirewallPolicyFilterRuleCollection,ApplicationRule,GitHub,SourceAddresses,10.100.1.0/24,Https:443,,,TargetFqdns,github.com,*.github.comBefore committing, validate your changes locally:
# Basic validation
.\pipeline-scripts\Test-FirewallRulesCsv.ps1
# Validate specific file
.\pipeline-scripts\Test-FirewallRulesCsv.ps1 -PolicyCsvPath ".\config\parameters\FirewallRules\FirewallRules.csv"
# Strict mode (warnings = errors)
.\pipeline-scripts\Test-FirewallRulesCsv.ps1 -StrictWhat's validated:
- β CSV formatting (quotes, delimiters, structure)
- β Priority conflicts and duplicates
- β IP addresses and CIDR notation
- β
FQDN formats (supports wildcards like
*.microsoft.com) - β Protocol and port formats
- β Rule completeness (required fields)
- β Priority ranges (100-65000)
- π Destination restrictions (blocks
*and0.0.0.0/0in Allow rules)
Deploy validated rules to Azure:
Connect-AzAccount
.\pipeline-scripts\Invoke-DeployFirewallPolicyRules.ps1Optional parameters:
.\pipeline-scripts\Invoke-DeployFirewallPolicyRules.ps1 `
-SubscriptionId "00000000-0000-0000-0000-000000000000" `
-ResourceGroupName "rg-firewall-prd" `
-FirewallPolicyName "afwp-hub-prd" `
-PolicyCsvPath ".\config\parameters\FirewallRules\FirewallRules.csv" `
-TemplateParameterFile ".\config\parameters\HubNetworking\main.bicepparam"By default, the script extracts parameters from the Bicep parameter file.
Automated quality gates prevent broken rules from being deployed.
Developer creates branch
β
Edits CSV file
β
Commits & pushes
β
Creates Pull Request βββ Validation Pipeline Runs
β β
βββ β
Pass βββ PR can be merged
βββ β Fail βββ PR blocked until fixed
-
Create the pipeline
Azure DevOps β Pipelines β New Pipeline β Existing YAML β .azuredevops/PR-Validation.yaml -
Configure branch policy β This blocks bad PRs
Repos β Branches β main β ... β Branch Policies β Build Validation β + β Select "PR-Validation" β Policy requirement: Required β -
Test it
- Create a test branch
- Make a CSV change
- Open PR to
main - Watch validation run automatically
| Check | Examples | Impact |
|---|---|---|
| CSV Format | Balanced quotes, proper delimiters | β Blocks PR |
| Priority Conflicts | Duplicate priorities in same group | β Blocks PR |
| IP/CIDR | Valid: 10.0.0.0/24, Invalid: 10.0.0.0/33 |
β Blocks PR |
| FQDNs | Valid: *.github.com, Invalid: github..com |
β Blocks PR |
| Protocols | Valid: Https:443, Invalid: Https444 |
β Blocks PR |
| Ports | Valid: 1-65535, Invalid: 70000 |
β Blocks PR |
| Completeness | Missing Source/Destination | β Blocks PR |
| Security | Allow rules with destination * or 0.0.0.0/0 |
β Blocks PR |
π Full guide: docs/PR-Validation-Setup.md
π Validation reference: docs/CSV-Validation-Reference.md
# Connect to Azure
Connect-AzAccount
# Deploy rules
.\pipeline-scripts\Invoke-DeployFirewallPolicyRules.ps1- Setup pipeline from
.azuredevops/Deploy-Firewall-Rules.yaml - Configure service connection in pipeline variables
- Update environment file at
config/prd/.env - Run pipeline manually or on commit to
main
Pipeline triggers:
- Automatic on changes to
config/parameters/FirewallRules.csv - Manual run from Azure DevOps
| Document | Description |
|---|---|
| PR-Validation-Setup.md | Complete guide to setting up PR validation with branch policies |
| CSV-Validation-Reference.md | Quick reference for validation script and rules |
| Test-FirewallRulesCsv.ps1 | Validation script with inline documentation |
| Invoke-DeployFirewallPolicyRules.ps1 | Deployment script with parameter reference |
AzureFirewallRulesAsCode/
βββ .azuredevops/ # Azure DevOps pipelines
β βββ Deploy-Core-Networking.yaml
β βββ Deploy-Firewall-Rules.yaml
β βββ PR-Validation.yaml # β PR validation pipeline
βββ config/
β βββ parameters/
β β βββ FirewallRules/ # β Firewall rules CSV files
β β βββ HubNetworking/ # Hub network parameters
β βββ prd/ # Production environment
β βββ testing/ # Testing environment
βββ docs/ # β Documentation
βββ modules/ # Bicep modules
βββ pipeline-scripts/ # Deployment & validation scripts
β βββ Test-FirewallRulesCsv.ps1 # β Validation script
β βββ Invoke-DeployFirewallPolicyRules.ps1
βββ scripts/ # Setup scripts
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Run validation:
.\pipeline-scripts\Test-FirewallRulesCsv.ps1 - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is licensed under the MIT License - see the LICENSE file for details.
This repository builds upon excellent work by:
- Will Moselhy - Original export/import functionality
- Justin Mendon - Rules as Code implementation
Questions or Issues? Open an issue or reach out to the maintainers.
