WAF Customization
tsdevstack ships with WAF (Web Application Firewall) protection enabled by default on all three providers. This page explains what's included, how to diagnose issues, and how to add your own rules.
What's included by default
The framework generates WAF rules covering these attack categories:
GCP and AWS use provider-managed rulesets where available — these are auto-updated by the cloud provider's security team. Azure Standard uses ~75 custom rules written by tsdevstack (Azure Standard doesn't offer managed rulesets). Azure Premium uses Microsoft's DRS 2.1 managed rulesets for the major categories, with ~31 custom rules covering the gaps.
All providers achieve equivalent coverage — the mechanism differs but the protection is the same.
Rate limit configuration
The default rate limit is 1000 requests per 60 seconds per IP. Override it in infrastructure.json:
The framework translates this to each provider's native format:
Adding custom rules
Each provider has its own custom rule format. The JSON schema is provider-aware — your IDE autocomplete will show only the format relevant to your cloud provider.
GCP (Cloud Armor — CEL expressions)
GCP rules use CEL (Common Expression Language). Available actions: "allow", "deny(403)", "deny(404)", "deny(429)", "throttle".
Use priority 800-899 for custom rules to avoid conflicts with framework rules (1-799).
AWS (WAF v2 — byte match, rate, geo)
AWS rules support three match types: byte_match (string matching), rate_based (rate limiting), and geo_match (country blocking). Available actions: "block", "allow", "count".
Use priority 100-899 for custom rules (managed rules use 1-99).
Azure (Front Door — match conditions)
Azure rules support two types: MatchRule (block/allow based on conditions) and RateLimitRule (rate limiting with conditions). Available actions: "Block", "Allow", "Log".
Match variables: RequestUri, RequestMethod, RequestHeader, RequestBody, SocketAddr, QueryString. Operators: Contains, Equal, IPMatch, GreaterThan. Optional transforms: Lowercase, UrlDecode.
Use priority 1000+ for custom rules to avoid conflicts with framework rules (100-999).
Diagnosing false positives
If the WAF blocks a legitimate request (you get a 403 that shouldn't happen):
1. Check the logs
2. Identify the rule
The logs will show which rule triggered. Look for:
- GCP:
enforcedSecurityPolicy.nameandenforcedSecurityPolicy.configuredAction - AWS:
terminatingRuleIdin the WAF log entry - Azure:
ruleNameandactionin the WAF diagnostic log
3. Add an exclusion or override
Once you identify the rule, add a custom rule with higher priority that allows the specific traffic pattern. For example, if a GCP managed ruleset blocks a specific path:
Known exclusions
The framework ships with these exclusions to prevent known false positives:
Applying changes
After modifying WAF configuration in infrastructure.json:
WAF rule changes take effect immediately after deployment. There is no propagation delay on any provider.
Further reading
- Service Configuration — WAF Rules for the full configuration reference
- GCP Architecture, AWS Architecture, Azure Architecture for provider-specific WAF details
- Compliance Readiness for how WAF maps to compliance frameworks