From b5cdbf9f687fc0a3f4b2c4abbabe1a74d495c99c Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Fri, 30 Jan 2026 14:46:11 -0600 Subject: [PATCH 1/2] Configure WAF on the Azure Front Door These policies are required by Microsoft to prevent DDOS attacks on the site. --- .../Bicep/front-door-appservice.bicep | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/src/apphost/Aspire.Dev.AppHost/Bicep/front-door-appservice.bicep b/src/apphost/Aspire.Dev.AppHost/Bicep/front-door-appservice.bicep index e8b41def..a2b5687b 100644 --- a/src/apphost/Aspire.Dev.AppHost/Bicep/front-door-appservice.bicep +++ b/src/apphost/Aspire.Dev.AppHost/Bicep/front-door-appservice.bicep @@ -4,6 +4,9 @@ param appServiceHostName string @description('Location for all resources, needed because Aspire always injects a location parameter') param location string = resourceGroup().location +@description('Rate limit threshold value for rate limit custom rule (requests per 5 minutes)') +param rateLimitThreshold int = 500 + resource frontDoorProfile 'Microsoft.Cdn/profiles@2024-02-01' = { name: take('${frontDoorName}${uniqueString(resourceGroup().id)}', 50) location: 'Global' @@ -96,3 +99,81 @@ resource route 'Microsoft.Cdn/profiles/afdEndpoints/routes@2025-06-01' = { } output endpointUrl string = 'https://${frontDoorEndpoint.properties.hostName}' + +// WAF Policy for DDoS compliance +resource wafPolicy 'Microsoft.Network/FrontDoorWebApplicationFirewallPolicies@2025-03-01' = { + name: take('${frontDoorName}-waf-AppDDoS${uniqueString(resourceGroup().id)}', 128) + location: 'Global' + sku: { + name: 'Premium_AzureFrontDoor' + } + properties: { + policySettings: { + enabledState: 'Enabled' + mode: 'Detection' + customBlockResponseStatusCode: 403 + requestBodyCheck: 'Enabled' + javascriptChallengeExpirationInMinutes: 30 + } + customRules: { + rules: [ + { + name: 'GlobalRateLimitRule' + enabledState: 'Enabled' + priority: 100 + ruleType: 'RateLimitRule' + rateLimitDurationInMinutes: 5 + rateLimitThreshold: rateLimitThreshold + matchConditions: [ + { + matchVariable: 'RequestUri' + operator: 'Contains' + negateCondition: false + matchValue: [ + '/' + ] + transforms: [] + } + ] + action: 'Block' + } + ] + } + managedRules: { + managedRuleSets: [ + { + ruleSetType: 'Microsoft_BotManagerRuleSet' + ruleSetVersion: '1.1' + ruleGroupOverrides: [] + exclusions: [] + } + ] + } + } +} + +// Security policy to associate WAF with Front Door endpoint +resource securityPolicy 'Microsoft.Cdn/profiles/securityPolicies@2025-06-01' = { + parent: frontDoorProfile + name: take('${frontDoorName}-AppDDoS${uniqueString(resourceGroup().id)}', 260) + properties: { + parameters: { + type: 'WebApplicationFirewall' + wafPolicy: { + id: wafPolicy.id + } + associations: [ + { + domains: [ + { + id: frontDoorEndpoint.id + } + ] + patternsToMatch: [ + '/*' + ] + } + ] + } + } +} From d81b7bbc9fa89676b31719e81b285a89a494127c Mon Sep 17 00:00:00 2001 From: Eric Erhardt Date: Fri, 30 Jan 2026 17:03:18 -0600 Subject: [PATCH 2/2] Fix invalid wafPolicy name --- .../Aspire.Dev.AppHost/Bicep/front-door-appservice.bicep | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/apphost/Aspire.Dev.AppHost/Bicep/front-door-appservice.bicep b/src/apphost/Aspire.Dev.AppHost/Bicep/front-door-appservice.bicep index a2b5687b..c1b91113 100644 --- a/src/apphost/Aspire.Dev.AppHost/Bicep/front-door-appservice.bicep +++ b/src/apphost/Aspire.Dev.AppHost/Bicep/front-door-appservice.bicep @@ -101,8 +101,9 @@ resource route 'Microsoft.Cdn/profiles/afdEndpoints/routes@2025-06-01' = { output endpointUrl string = 'https://${frontDoorEndpoint.properties.hostName}' // WAF Policy for DDoS compliance +// Note: WAF policy names must be alphanumeric only (no hyphens) resource wafPolicy 'Microsoft.Network/FrontDoorWebApplicationFirewallPolicies@2025-03-01' = { - name: take('${frontDoorName}-waf-AppDDoS${uniqueString(resourceGroup().id)}', 128) + name: take('${replace(frontDoorName, '-', '')}wafDDoS${uniqueString(resourceGroup().id)}', 128) location: 'Global' sku: { name: 'Premium_AzureFrontDoor'