We’re using Cloudflare WAF for our production app, and I’m starting to write custom rules. My problem is that when I create or test a new rule, it sometimes blocks traffic to our staging environment, which shares the same zone. I don’t want to accidentally break staging for the team.
Is there a recommended way to manage custom WAF rules so they only apply to production? I’ve heard about rule expressions with IPs or hostnames, but I’m not sure what’s best practice. How do others handle this separation?
Still learning.
You're already on the right track with expressions. The hostname field is the most straightforward filter. Just add something like `(http.host eq "www.production.com")` to your rule logic. Relying on IPs is fragile, especially if your staging IPs aren't static.
But a more fundamental question: why are production and staging sharing a zone? That's asking for trouble. The "best practice" is to separate them entirely, giving staging its own zone with its own WAF policy. That way you can't break one from the other. The hostname workaround is just that, a workaround for a less-than-ideal setup.
Have you considered the blast radius of a misconfigured rule expression? One typo in that logic and your filter is gone, applying the rule to everything.
Data skeptic, not a data cynic.
Good point about the hostname filter. That's definitely the first line of defense. I always add a second condition, like `and cf.zone.name eq "your-zone.com"` just to be extra safe - belt and suspenders approach.
One trick I use in our pipeline: we deploy WAF rules as code (Terraform or the API) and run a quick integration test against a staging hostname before enabling the rule in "block" mode. The test makes a malformed request and expects it to log, but not block. If it blocks, we know the expression is too broad. It's saved us a few times.
Separate zones is the gold standard, but if you're stuck sharing, that pre-production test can be a lifesaver.
Pipeline Pilot
Separate zones as the "best practice" is great in theory, but it's a classic example of solution that ignores cost. You're now paying for two zones, two sets of WAF rule quotas, and managing two configurations. Vendor loves that.
That said, the blast radius warning is the real meat here. The hostname filter is a single point of failure. I'd never rely on just that. You need a mandatory tagging system in your pipeline that slaps a `env:production` label on any rule, then use that as a second filter clause. Makes the expression error more obvious.
-- cost first