Azure Front Door with WAF — Setup Guide
Scope note. This document describes the reference Azure deployment of CTN ASR — the prototype that ran on Azure Static Web Apps and Azure Functions. The ASR architecture is cloud-agnostic by intent (see Solution Strategy and ASR Deployment Procedures). The naming below (“admin portal”, “member portal”) reflects the prototype; the chosen Quarkus implementation will use the same portal layout under the new naming (admin portal + participant portal).
Overview
Section titled “Overview”This guide covers the Azure Front Door and Web Application Firewall (WAF) implementation for the CTN ASR admin and member portals.
Architecture
Section titled “Architecture”Components
Section titled “Components”- Azure Front Door - Global load balancer, CDN, and routing service
- Web Application Firewall (WAF) - Security protection layer
- Static Web Apps - Backend origins for admin and member portals
Data Flow
Section titled “Data Flow”User Request ↓[Azure Front Door] ↓ (Global routing + Caching)[WAF Policy Evaluation] ↓ (Security checks)If Allowed → [Admin/Member Portal Static Web App]If Blocked → 403 ForbiddenResources Created
Section titled “Resources Created”- WAF Policy:
waf-ctn-asr-{environment} - Front Door Profile:
fd-ctn-asr-{environment} - Admin Endpoint:
admin-ctn-asr-{environment}.z01.azurefd.net - Member Endpoint:
portal-ctn-asr-{environment}.z01.azurefd.net
Features
Section titled “Features”Front Door Capabilities
Section titled “Front Door Capabilities”-
Global Load Balancing
- Routes traffic to nearest/healthiest backend
- Session affinity (sticky sessions) enabled
- Health probes every 100 seconds
-
Performance Optimization
- Content caching at edge locations worldwide
- SSL/TLS termination
- Traffic acceleration via Microsoft global network
-
High Availability
- Automatic failover
- DDoS protection (L3/L4)
- 99.99% SLA (Standard) / 99.995% SLA (Premium)
WAF Security Features
Section titled “WAF Security Features”-
OWASP Protection
- Microsoft Default Rule Set 2.1 (based on OWASP CRS)
- Blocks SQL injection, XSS, RCE, LFI, RFI, etc.
- Automatic threat intelligence updates
-
Rate Limiting
- 100 requests per minute per IP address
- Prevents brute force attacks
- Mitigates DDoS attacks
-
Bot Management
- Microsoft Bot Manager Rule Set 1.0
- Blocks malicious bots
- Allows legitimate search engine crawlers
-
Custom Rules
- Suspicious User Agent Blocking: Blocks sqlmap, nikto, masscan, nmap, wpscan
- Geo-Restriction (Production only): Only allows NL, BE, DE, FR, GB, US
-
Mode Selection
- Detection Mode (dev): Logs threats but doesn’t block
- Prevention Mode (prod): Actively blocks threats
Deployment
Section titled “Deployment”Prerequisites
Section titled “Prerequisites”- Azure subscription with permissions to create resources
- Static Web Apps already deployed (admin and member portals)
- OpenTofu (applied via GitHub Actions; GitOps with ArgoCD for cluster workloads)
Deployment via OpenTofu
Section titled “Deployment via OpenTofu”The Front Door and WAF are provisioned with OpenTofu (the azurerm provider) as part of the main infrastructure. The resource snippets later in this document are shown in Bicep syntax for readability; in the repo they are authored as OpenTofu modules.
# Provision the whole infrastructure (includes Front Door + WAF)# export DB_PASSWORD=YourSecurePasswordHerecd infrastructure/tofutofu apply -var-file=env/dev.tfvars -var="database_admin_password=$DB_PASSWORD"Deploy Only Front Door and WAF
Section titled “Deploy Only Front Door and WAF”# 1. Deploy WAF Policyaz deployment group create \ --resource-group rg-ctn-asr-dev \ --template-file infrastructure/bicep/modules/waf-policy.bicep \ --parameters environment=dev \ --parameters location=westeurope \ --parameters resourcePrefix=ctn-asr
# 2. Deploy Front Door (requires WAF Policy ID and Static Web App hostnames)WAF_POLICY_ID=$(az deployment group show \ --resource-group rg-ctn-asr-dev \ --name waf-policy-deployment \ --query properties.outputs.wafPolicyId.value -o tsv)
ADMIN_HOSTNAME=$(az staticwebapp show \ --name stapp-ctn-demo-asr-dev \ --query defaultHostname -o tsv)
MEMBER_HOSTNAME=$(az staticwebapp show \ --name ctn-member-portal \ --query defaultHostname -o tsv)
az deployment group create \ --resource-group rg-ctn-asr-dev \ --template-file infrastructure/bicep/modules/front-door.bicep \ --parameters environment=dev \ --parameters resourcePrefix=ctn-asr \ --parameters wafPolicyId=$WAF_POLICY_ID \ --parameters adminPortalHostname=$ADMIN_HOSTNAME \ --parameters memberPortalHostname=$MEMBER_HOSTNAMEConfiguration
Section titled “Configuration”WAF Policy Settings
Section titled “WAF Policy Settings”File: infrastructure/bicep/modules/waf-policy.bicep
Policy Mode
Section titled “Policy Mode”mode: isProd ? 'Prevention' : 'Detection'- Detection Mode (dev): Logs threats, allows traffic
- Prevention Mode (prod): Blocks threats
Rate Limiting
Section titled “Rate Limiting”{ name: 'RateLimitRule' rateLimitThreshold: 100 // requests rateLimitDurationInMinutes: 1 // per minute action: 'Block'}Geo-Restriction
Section titled “Geo-Restriction”{ name: 'GeoRestriction' matchValue: ['NL', 'BE', 'DE', 'FR', 'GB', 'US'] negateCondition: true // Block all EXCEPT these countries action: isProd ? 'Block' : 'Log' enabledState: isProd ? 'Enabled' : 'Disabled'}Note: Only enforced in production environment.
Managed Rule Sets
Section titled “Managed Rule Sets”-
Microsoft_DefaultRuleSet 2.1
- OWASP CRS-based rules
- SQL injection, XSS, RCE, etc.
- Action: Block
-
Microsoft_BotManagerRuleSet 1.0
- Bad bot detection
- Good bot allowlist
- Action: Block
Front Door Settings
Section titled “Front Door Settings”File: infrastructure/bicep/modules/front-door.bicep
Origin Configuration
Section titled “Origin Configuration”properties: { hostName: adminPortalHostname httpPort: 80 httpsPort: 443 originHostHeader: adminPortalHostname priority: 1 weight: 1000 enabledState: 'Enabled' enforceCertificateNameCheck: true}Health Probes
Section titled “Health Probes”healthProbeSettings: { probePath: '/' probeRequestType: 'GET' probeProtocol: 'Https' probeIntervalInSeconds: 100}Load Balancing
Section titled “Load Balancing”loadBalancingSettings: { sampleSize: 4 successfulSamplesRequired: 3 additionalLatencyInMilliseconds: 50}HTTPS Enforcement
Section titled “HTTPS Enforcement”properties: { supportedProtocols: ['Https'] // HTTPS only forwardingProtocol: 'HttpsOnly' // Always forward as HTTPS httpsRedirect: 'Enabled' // Redirect HTTP → HTTPS}Custom Domains (Production)
Section titled “Custom Domains (Production)”Prerequisites
Section titled “Prerequisites”- Domain ownership verification
- DNS management access
- SSL certificate (managed by Azure)
Setup Steps
Section titled “Setup Steps”- Add Custom Domain to Front Door
# Admin Portalaz afd custom-domain create \ --profile-name fd-ctn-asr-prod \ --custom-domain-name admin-ctn-nl \ --resource-group rg-ctn-asr-prod \ --host-name admin.ctn.nl \ --minimum-tls-version TLS12
# Member Portalaz afd custom-domain create \ --profile-name fd-ctn-asr-prod \ --custom-domain-name portal-ctn-nl \ --resource-group rg-ctn-asr-prod \ --host-name portal.ctn.nl \ --minimum-tls-version TLS12- Create DNS CNAME Records
admin.ctn.nl CNAME admin-ctn-asr-prod.z01.azurefd.netportal.ctn.nl CNAME portal-ctn-asr-prod.z01.azurefd.net- Enable Managed Certificate
az afd custom-domain update \ --profile-name fd-ctn-asr-prod \ --custom-domain-name admin-ctn-nl \ --resource-group rg-ctn-asr-prod \ --certificate-type ManagedCertificate- Associate Domain with Route
az afd route update \ --profile-name fd-ctn-asr-prod \ --endpoint-name admin-ctn-asr-prod \ --route-name admin-portal-route \ --resource-group rg-ctn-asr-prod \ --custom-domains admin-ctn-nlMonitoring
Section titled “Monitoring”Key Metrics to Monitor
Section titled “Key Metrics to Monitor”- Request Count - Total requests per endpoint
- Error Rate - 4xx/5xx response codes
- Latency - Response time at edge
- WAF Blocks - Threats blocked by WAF
- Origin Health - Backend availability
Azure Monitor Queries
Section titled “Azure Monitor Queries”WAF Blocks by Rule
Section titled “WAF Blocks by Rule”AzureDiagnostics| where ResourceType == "FRONTDOORWEBAPPLICATIONFIREWALLPOLICIES"| where action_s == "Block"| summarize count() by ruleName_s| order by count_ descTop Blocked IPs
Section titled “Top Blocked IPs”AzureDiagnostics| where ResourceType == "FRONTDOORWEBAPPLICATIONFIREWALLPOLICIES"| where action_s == "Block"| summarize count() by clientIP_s| order by count_ desc| take 10Request Latency P95
Section titled “Request Latency P95”AzureDiagnostics| where ResourceType == "FRONTDOOR"| summarize percentile(timeTaken_d, 95) by bin(TimeGenerated, 5m)| render timechartAlerts
Section titled “Alerts”Recommended alerts:
- High Error Rate: > 5% 5xx errors in 5 minutes
- WAF Attack Surge: > 100 blocks in 1 minute
- Origin Unhealthy: Health probe failures
- High Latency: P95 latency > 2 seconds
Troubleshooting
Section titled “Troubleshooting”Issue: 403 Forbidden
Section titled “Issue: 403 Forbidden”Possible Causes:
- WAF blocking legitimate traffic
- Geo-restriction blocking user’s country
- Rate limit exceeded
Solution:
# Check WAF logsaz monitor diagnostic-settings list \ --resource waf-ctn-asr-dev \ --resource-type Microsoft.Network/FrontDoorWebApplicationFirewallPolicies
# Temporarily switch to Detection mode for testingaz network front-door waf-policy update \ --name waf-ctn-asr-dev \ --resource-group rg-ctn-asr-dev \ --mode DetectionIssue: Origin Unreachable
Section titled “Issue: Origin Unreachable”Possible Causes:
- Static Web App down
- Origin hostname incorrect
- Certificate validation failure
Solution:
# Check origin healthaz afd origin show \ --profile-name fd-ctn-asr-dev \ --origin-group-name admin-portal-origin-group \ --origin-name admin-portal-origin \ --resource-group rg-ctn-asr-dev
# Test origin directlycurl -I https://calm-tree-03352ba03.1.azurestaticapps.netIssue: Slow Performance
Section titled “Issue: Slow Performance”Possible Causes:
- Cache not configured properly
- Origin response time slow
- TLS handshake overhead
Solution:
# Check cache statisticsaz monitor metrics list \ --resource fd-ctn-asr-dev \ --resource-type Microsoft.Cdn/profiles \ --metric CacheHitRatio
# Enable query string cachingaz afd route update \ --profile-name fd-ctn-asr-dev \ --endpoint-name admin-ctn-asr-dev \ --route-name admin-portal-route \ --query-string-caching-behavior IgnoreQueryStringSecurity Best Practices
Section titled “Security Best Practices”-
Always Use Prevention Mode in Production
- Detection mode logs but doesn’t block
- Only use Detection for testing/debugging
-
Monitor WAF Logs Regularly
- Review blocked requests
- Identify false positives
- Tune custom rules
-
Keep Managed Rule Sets Updated
- Azure automatically updates rule sets
- Review change logs for new rules
-
Use Geo-Restriction Wisely
- Only block countries if necessary
- Consider legitimate international users
- Federated IdP auth (e.g. Entra ID) may require US endpoints if the participant’s tenant home region is US
-
Test Rate Limits
- Ensure legitimate traffic isn’t blocked
- Consider API usage patterns
- Adjust thresholds based on metrics
-
Enable HTTPS Only
- Enforce HTTPS at Front Door level
- Redirect HTTP → HTTPS automatically
- Use TLS 1.2 minimum
-
Review Custom Domain Setup
- Verify domain ownership
- Use managed certificates
- Monitor certificate expiration
Cost Optimization
Section titled “Cost Optimization”SKU Selection
Section titled “SKU Selection”-
Standard (dev/staging):
- Basic WAF features
- Standard managed rules
- Cost: ~$35/month base + usage
-
Premium (production):
- Advanced WAF features
- Private Link support
- Bot protection
- Cost: ~$330/month base + usage
Usage Charges
Section titled “Usage Charges”- Data Transfer: $0.05/GB (first 10TB)
- Requests: $0.0075 per 10,000 requests
- WAF Requests: $0.00025 per request
Cost Saving Tips
Section titled “Cost Saving Tips”- Enable caching to reduce origin requests
- Use Standard SKU for non-production
- Set appropriate cache TTLs
- Monitor and optimize request patterns
References
Section titled “References”- Azure Front Door Documentation
- Azure WAF on Front Door
- OWASP CRS Documentation
- Azure DDoS Protection
Support
Section titled “Support”For issues or questions:
- Check Azure Monitor logs
- Review this documentation
- Contact Azure Support
- Consult CLAUDE.md for project-specific guidance
In samenwerking met




