Overview and What You Will Learn
In this lab, you will create a Cloud Armor security policy, add a rate-limiting rule to block a source IP exceeding a request threshold, and attach a pre-configured WAF rule blocking common SQL injection patterns - filtering malicious requests before they ever reach your actual backend.
Why This Matters in Production
A public-facing API experiences a basic application-layer flood from a single source, and without any rate limiting in place, that flood consumes backend compute capacity that legitimate customers needed, effectively causing an outage even though no single request was individually malicious. Cloud Armor's rate-based rules exist specifically to stop this pattern before it ever reaches the backend at all.
Core Principles
Cloud Armor attaches to a Global External HTTP(S) Load Balancer and inspects incoming requests against configured rules before they're allowed through, blocking common attack patterns at the edge rather than letting them reach your application.
+------------------------------------------+| Request arrives at the Load Balancer |+------------------------------------------+ | v+------------------------------------------+| Cloud Armor evaluates against the attached || security policy's rules |+------------------------------------------+ | | Blocked Allowed | | v vRequest rejected, Proceeds normally tobackend never sees it the backend serviceDetailed Step-by-Step Practical Lab
- Create a project with a basic load balancer setup to attach Cloud Armor to:
gcloud projects create gcp-armor-lab-2026 --name="Cloud Armor Lab"gcloud config set project gcp-armor-lab-2026gcloud services enable compute.googleapis.com gcloud compute addresses create armor-lab-ip --globalgcloud compute health-checks create http health-check-armor --port=80gcloud compute backend-services create backend-armor-lab \ --protocol=HTTP --port-name=http --health-checks=health-check-armor --global- Create a Cloud Armor security policy:
gcloud compute security-policies create armor-policy-lab \ --description="Rate limiting and WAF rules for the lab backend"- Add a rate-limiting rule blocking any single source IP exceeding 100 requests per minute:
gcloud compute security-policies rules create 1000 \ --security-policy=armor-policy-lab \ --expression="true" \ --action=rate-based-ban \ --rate-limit-threshold-count=100 \ --rate-limit-threshold-interval-sec=60 \ --ban-duration-sec=300 \ --conform-action=allow \ --exceed-action=deny-429 \ --enforce-on-key=IPNote
--ban-duration-sec=300means once an IP exceeds the threshold, it is blocked for 5 minutes before being allowed to try again - this is a common defense against basic application-layer floods that doesn't require permanently blocking a source that might resume legitimate behavior later.
- Add a pre-configured WAF rule blocking common SQL injection patterns:
gcloud compute security-policies rules create 2000 \ --security-policy=armor-policy-lab \ --expression="evaluatePreconfiguredExpr('sqli-stable')" \ --action=deny-403- Attach the security policy to the backend service:
gcloud compute backend-services update backend-armor-lab \ --security-policy=armor-policy-lab \ --global- Confirm the policy is correctly attached:
gcloud compute backend-services describe backend-armor-lab \ --global \ --format="value(securityPolicy)"- Review the security policy's rules to confirm both the rate limit and WAF rule are active:
gcloud compute security-policies rules list \ --security-policy=armor-policy-lab- Clean up:
gcloud compute backend-services delete backend-armor-lab --global --quietgcloud compute security-policies delete armor-policy-lab --quietgcloud compute health-checks delete health-check-armor --quietgcloud compute addresses delete armor-lab-ip --global --quietgcloud projects delete gcp-armor-lab-2026 --quietProduction Best Practices & Common Pitfalls
Common MistakeDeploying a public-facing load balancer with no Cloud Armor policy attached at all, leaving the backend exposed to basic application-layer floods and common web attack patterns that a pre-configured WAF rule would have blocked at the edge with minimal configuration effort.
TipTest a new Cloud Armor rule with
--action=deny-403temporarily changed to a preview-only mode where supported, or start with a higher, more conservative rate-limiting threshold and tighten it gradually once you've confirmed it doesn't affect legitimate traffic patterns.
- Cloud Armor only protects traffic passing through a Global External HTTP(S) Load Balancer - a backend reachable through some other path (like a direct external IP on a VM) is not protected by a Cloud Armor policy at all, regardless of how it's configured.
- Preconfigured WAF rules (like
sqli-stablefor SQL injection) are maintained by Google and updated over time as new attack patterns emerge, similar in concept to AWS WAF's Managed Rule Groups or Azure WAF's managed rule sets - reach for these before writing custom expression-based rules for common, well-known attack categories.
Quick Reference & Troubleshooting Commands
| Command | Description |
|---|---|
gcloud compute security-policies create |
Create a new Cloud Armor security policy |
gcloud compute security-policies rules create --action=rate-based-ban |
Add a rate-limiting rule |
gcloud compute security-policies rules create --expression="evaluatePreconfiguredExpr(...)" |
Add a preconfigured WAF rule |
gcloud compute backend-services update --security-policy= |
Attach a policy to a backend service |