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..c1b91113 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,82 @@ 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('${replace(frontDoorName, '-', '')}wafDDoS${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: [ + '/*' + ] + } + ] + } + } +}