Google Cloud Armor protects internet-facing load balancers on Google Cloud, but a security policy with rules left in preview, a default rule set to allow, logging switched off on the backend service and no client IP header behind a CDN gives the appearance of protection without the effect. Cloud Armor applies security policies to backend services, backend buckets and some network endpoints: an ordered list of rules using IP ranges, geography, a custom expression language and preconfigured WAF rules based on the OWASP ModSecurity Core Rule Set, plus rate limiting, bot challenges and machine-learning detection of layer 7 floods. This guide covers the policy types and where they sit, who can change and attach policies, the integrations that act on them, logging and detection, and a hardening baseline with real rule names, rate limit values and log fields. It is for cloud security and platform engineers running workloads behind Google Cloud load balancers, checked against Google Cloud's Cloud Armor documentation in November 2026. Vendor-neutral selection criteria are in the WAF and WAAP Buyer's Guide; this page stays on Cloud Armor.
This is an independent guide from NHI Mgmt Group, based on Google Cloud's public documentation as of November 2026. It is not sponsored or reviewed by Google Cloud. Product features change, so confirm settings against Google Cloud's current documentation.
Key takeaways
- The default rule decides your posture. Every policy has a default rule at priority 2147483647 that cannot be deleted. Rules run from the lowest number up, so check the default action and rule order before the rule list.
- Preview is a phase, not a state. Preview rules log what they would have done without enforcing it. Tune preconfigured WAF rules in preview, then move them to deny on a dated plan.
- Rate limits are approximate and per region. Thresholds apply independently in each region with backends, so cross-region traffic can reach a multiple of the configured value. Use them for abuse and availability, not strict quotas.
- Logs only exist if the backend logs. Cloud Armor fields are written into load balancer request logs, which are off by default on new backend services and follow their sampling rate.
- Policy changes are privileged. Whoever holds
roles/compute.securityAdmincan switch the default rule to allow; whoever holdsroles/compute.networkAdmincan detach a policy. Treat both as perimeter administration.
How Cloud Armor policies work
A security policy is a project resource attached to one or more targets. The type determines where it is evaluated and what it can do.
| Policy type | API type | Applies to | Use it for |
|---|---|---|---|
| Backend security policy | CLOUD_ARMOR (default) | Backend services behind external Application Load Balancers, external proxy Network Load Balancers | Full WAF, rate limiting, bot management, Adaptive Protection |
| Edge security policy | CLOUD_ARMOR_EDGE | Backend services and backend buckets, evaluated before Cloud CDN cache and before Identity-Aware Proxy | IP and geography filtering of cached content |
| Network edge security policy | CLOUD_ARMOR_NETWORK | Regional external passthrough Network Load Balancers, protocol forwarding, VMs with external IPs | Blocking at Google's network edge; needs advanced network DDoS protection in the region |
| Regional backend security policy | Regional scope | Regional load balancers, including the regional internal Application Load Balancer | Internal and regional applications |
| Hierarchical security policy | Organisation, folder or project | Everything beneath the attachment point, with a reduced feature set | Central baselines that project teams cannot remove |
- Rule evaluation: priorities run from 0 to 2147483646 and must be unique. Header-based rules evaluate first; body-based rules (
evaluatePreconfiguredWafand custom rules usingrequest.bodyorrequest.params) evaluate once the body arrives, and only the first 64 kB of a body is inspected. - Actions: allow; deny with 403, 404 or 502; redirect to
GOOGLE_RECAPTCHAorEXTERNAL_302; throttle; and rate-based ban. - Preconfigured WAF rules: Google recommends Core Rule Set 4.22 rule sets such as
sqli-v422-stable,xss-v422-stable,lfi-v422-stable,rfi-v422-stable,rce-v422-stable,methodenforcement-v422-stable,scannerdetection-v422-stable,protocolattack-v422-stable,php-v422-stable,sessionfixation-v422-stable,java-v422-stableandgeneric-v422-stable. CRS 3.3 (-v33-stable) and 3.0 remain, and Google advises avoiding 3.0. Canary rulescve-canary(Log4j and React remote code execution) andjson-sqli-canary(JSON-based SQL injection bypass) are available to all customers. - Sensitivity: each rule set has sensitivity levels, for example 1 to 4 for SQL injection and 1 to 3 for remote code execution. Higher levels catch more and produce more false positives, so set the level explicitly in
evaluatePreconfiguredWaf()and exclude individual signatures withopt_out_rule_idswhere tuning shows a false positive.
Availability: Cloud Armor Standard includes always-on layer 3 and 4 DDoS protection for external Application Load Balancers and external proxy Network Load Balancers, Cloud CDN integration and the preconfigured WAF rules, billed per policy, rule and request. Cloud Armor Enterprise (Paygo, or Annual with a 12-month commitment) adds DDoS protection for passthrough load balancers, protocol forwarding and VM public IPs, full Adaptive Protection, Google Threat Intelligence, third-party named IP lists, advanced network DDoS protection, attack visibility and hierarchical policies. Enterprise Annual adds DDoS response support, subject to eligibility, and DDoS bill protection.
Admin roles and privileged access
Cloud Armor permissions are part of Compute Engine IAM. Google's documentation splits them so that writing a policy and attaching it are different rights.
| Task | Role in Google's documentation | Key permissions | Guardrail |
|---|---|---|---|
| Create, change or delete policies | Compute Security Admin (roles/compute.securityAdmin) | compute.securityPolicies.create, .update, .delete | Small edge security group; changes through infrastructure as code and review |
| Attach a policy to a backend service | Compute Network Admin (roles/compute.networkAdmin) | compute.securityPolicies.use, compute.backendServices.setSecurityPolicy | Alert on any detach; consider a custom role without setSecurityPolicy for application teams |
| View policies | Security Admin (roles/iam.securityAdmin) with Compute Network Admin | compute.securityPolicies.get, .list | For read-only analysts, build a custom role with only the get and list permissions rather than granting broad admin roles |
- Least privilege in practice: the predefined roles carry many other Compute permissions.
roles/iam.securityAdminin particular can change IAM policies, so do not hand it out to give someone read access to Cloud Armor. Custom roles built from thecompute.securityPolicies.*permissions are the cleaner route. See the Google Cloud IAM and Service Accounts Guide. - Use hierarchical policies for non-negotiables: an organisation or folder policy can deny known-bad sources or sanctioned regions for every project beneath it, so a project owner cannot remove the baseline. See the Google Cloud Organization Policy Guide for related guardrails.
- The default rule is the highest-impact field: changing it from deny to allow on an allowlist policy, or the reverse on a public site, has immediate effect. Require review for that change specifically.
Integrations, API tokens and service accounts
Cloud Armor itself has no API keys; its machine identities are the service accounts and pipelines that manage policies, and the signals it consumes from other services.
- Infrastructure as code: Terraform or Config Connector service accounts that manage policies need the security policy permissions on the specific project, not Compute Admin across the organisation. Use workload identity federation for pipelines rather than service account keys. See the Google Cloud Service Account Keys Security Guide.
- Automated blocking: scripts that add attacker IPs to a deny rule from a SIEM or threat feed hold write access to your perimeter. Scope them to updating one rule or address group, log every change, and expire entries.
- reCAPTCHA integration: the
GOOGLE_RECAPTCHAredirect action and reCAPTCHA token scores (recaptchaActionToken.score,recaptchaSessionToken.scorein logs) let rules challenge suspected bots instead of blocking them. See the Bot Management Guide. - Client IP behind a proxy or CDN: if another proxy or CDN sits in front of the load balancer, configure
userIpRequestHeadersand match withorigin.user_ipor theUSER_IPrate limit key. Without it, Adaptive Protection and IP rules see the proxy's address, and a block can take out all your traffic. - Adaptive Protection auto-deploy: a placeholder rule matching
evaluateAdaptiveProtectionAutoDeploy()lets the service apply its suggested rules automatically, with allow, deny, throttle or redirect actions. That is an automated change to production traffic handling; start it in preview. - Identity-Aware Proxy: edge policies run before IAP, so IP and geography filtering happens before identity checks. Cloud Armor complements, not replaces, authentication. See the Identity-Aware Proxy Guide.
Rate limiting and DDoS protection
| Setting | Throttle | Rate-based ban |
|---|---|---|
| Behaviour over the threshold | Excess requests get the exceed action for the rest of the interval; traffic continues at a capped rate | All requests from the client get the exceed action for the interval plus ban_duration_sec |
rate_limit_threshold_count | 1 to 1,000,000 | 1 to 10,000 |
interval_sec | 10, 30, 60, 120, 180, 240, 300, 600, 900, 1200, 1800, 2700 or 3600 | |
| Ban duration | Not applicable | 60 to 3600 seconds; optional ban_threshold_count so only sustained offenders are banned |
exceed_action | deny with 403, 404, 429 or 502 (Google recommends 429), or redirect to reCAPTCHA or an external URL | |
| Change later | Can be changed to a ban | Cannot be changed back to a throttle |
- Choose the key deliberately: keys are
ALL,IP,XFF_IP,HTTP_HEADER,HTTP_COOKIE,HTTP_PATH,SNI,REGION_CODE,TLS_JA3_FINGERPRINT,TLS_JA4_FINGERPRINT,USER_IPandASN, and up to three can be combined. A login rule keyed on IP plus path, or an API rule keyed on an API key header, is far more precise than a broad per-IP limit. Header and cookie keys fall back toALLif absent, so an attacker who omits the header shares one bucket with everyone else who omits it. See the Rate Limiting and API Abuse Guide. - Adaptive Protection: machine-learning models baseline traffic per backend service and alert on anomalous layer 7 floods with a confidence score from 0 to 1, an attack signature and a suggested rule. It needs at least an hour of training, and creating a new policy discards the baseline, so do not rebuild policies mid-attack. Without Enterprise, alerts carry only the confidence score and attack size. Google suggests starting alerting at a confidence above 0.5.
- Network layer: always-on layer 3 and 4 protection covers the proxy load balancers; passthrough load balancers and VM public IPs need Enterprise and, for network edge policies, advanced network DDoS protection. See the DDoS Protection Guide and the DDoS Response Playbook.
Logging and detection
Cloud Armor writes per-request decisions into external Application Load Balancer and external proxy Network Load Balancer logs. Logging is disabled by default for new backend services and follows the backend's sample rate, so enable it at a rate that keeps denials visible.
| Field or source | What it tells you | Use |
|---|---|---|
jsonPayload.enforcedSecurityPolicy.outcome="DENY" | Requests blocked, with policy name, priority and configuredAction | Dashboards of blocks by rule; spikes indicate attack or a bad rule |
enforcedSecurityPolicy.preconfiguredExprIds | Which WAF signature matched | False positive triage and opt_out_rule_ids decisions |
previewSecurityPolicy | What a preview rule would have done | Evidence to promote a rule to enforcement |
rateLimitAction.outcome | RATE_LIMIT_THRESHOLD_EXCEED or BAN_THRESHOLD_EXCEED | Tuning thresholds; detecting floods (ATT&CK T1499.002, T1499.003) |
securityPolicyRequestData.userIpInfo, remoteIpInfo, tlsJa4Fingerprint | Client IP source, region, ASN, TLS fingerprint | Confirm the user IP header works; build fingerprint-keyed rules |
| Adaptive Protection alerts | Attack signature and confidence, also sent to Security Command Center | Alerting policy and incident response |
Cloud Audit Logs for securityPolicies and setSecurityPolicy | Who changed or detached a policy | Alert on default rule changes and detaches (T1685 Disable or Modify Tools) |
Verbose logging (--log-level=VERBOSE) adds matchedFieldName, matchedFieldValue and offsets for preconfigured WAF matches. Google notes the snippets can contain sensitive request data and recommends using it only during rule creation and troubleshooting. Add a custom response header such as X-Cloud-Trace-Id: {cloud_trace_id} on the backend service so a user reporting a block can give you the trace to look up. See the Google Cloud Audit Logs and Log Sinks Guide.
Measures that show the control is working: share of internet-facing backend services with a policy attached (target 100%), number of WAF rules still in preview for more than 30 days, false positive rate on enforced WAF rules, blocked requests per rule per week, and time from an Adaptive Protection alert to a deployed mitigation.
Hardening baseline
- Inventory and attach: list every external load balancer, backend service and backend bucket, and attach a backend policy (and an edge policy where Cloud CDN serves content). Enable request logging on each backend service.
- Set the default rule: deny by default for internal or partner-only applications with allowlisted ranges; allow by default for public sites with explicit deny and WAF rules above it.
- Add WAF rules in preview: start with
sqli-v422-stable,xss-v422-stable,lfi-v422-stable,rce-v422-stable,rfi-v422-stable,scannerdetection-v422-stable,protocolattack-v422-stableandcve-canaryat a low sensitivity, plus the language rule sets that match your stack. - Tune: review
previewSecurityPolicymatches with verbose logging on for one to two weeks, addopt_out_rule_idsfor confirmed false positives, raise sensitivity where clean, then switch off verbose logging. - Enforce: remove preview (
--no-preview) rule by rule during low-traffic windows. Roll back by re-enabling preview on the offending rule, which takes effect without deleting it. - Rate limits: add a broad per-IP throttle sized above real peaks, then scoped bans for login, password reset and expensive API paths, returning 429.
- Proxy awareness: configure
userIpRequestHeadersif anything sits in front, and lock backends so they only accept traffic from the load balancer. - DDoS readiness: for critical services, evaluate Enterprise for Adaptive Protection and response support, enable Adaptive Protection, and create a Cloud Logging alerting policy on its alerts. See the DDoS Readiness Checklist.
Common misconfigurations
- Rules parked in preview: the dashboards show matches, so teams assume protection, but nothing is blocked.
- Logging off or heavily sampled: new backend services do not log, and a low sample rate hides targeted attacks and false positives alike.
- No user IP header behind another CDN: per-IP rate limits and Adaptive Protection treat the CDN as one client, so the first ban blocks everyone.
- Large bodies assumed inspected: only the first 64 kB is inspected; payloads placed later in a large body are not seen by body rules. Pair WAF rules with input validation in the application.
- Rate limits treated as quotas: per-region enforcement and approximation mean limits can be exceeded several times over across regions.
- Origin left reachable: backends with public IPs that accept traffic directly bypass Cloud Armor entirely. Restrict them with firewall rules to the load balancer ranges. See the Google Cloud VPC and Cloud NGFW Security Guide.
Framework mapping
| Area | NIST SP 800-53 Rev. 5 | MITRE ATT&CK |
|---|---|---|
| WAF rules on public applications | SC-7 Boundary Protection, SI-10 | T1190 Exploit Public-Facing Application; T1595.002 Vulnerability Scanning |
| Rate limiting and Adaptive Protection | SC-5 Denial-of-service Protection | T1499.002 Service Exhaustion Flood, T1499.003 Application Exhaustion Flood |
| Network edge and always-on DDoS protection | SC-5 | T1498 Network Denial of Service |
| Policy change and attach permissions | AC-6, CM-6 | T1685 Disable or Modify Tools |
| Request and audit logging | AU-12, SI-4 | Supports detection of all of the above |
Practitioner checklist
- Attach a Cloud Armor policy to every internet-facing backend service and backend bucket, and enable request logging on each.
- Review each policy's default rule action and rule priorities against the application's exposure.
- Deploy CRS 4.22 preconfigured WAF rules and
cve-canaryin preview, tune with verbose logging andopt_out_rule_ids, then enforce on a dated plan. - Add per-IP throttling and scoped rate-based bans on login and expensive paths, returning 429.
- Configure
userIpRequestHeaderswhen a proxy or CDN sits in front, and block direct access to origins. - Restrict
compute.securityPolicies.updateandcompute.backendServices.setSecurityPolicyto a small group, and alert on changes in Cloud Audit Logs. - Use hierarchical policies for organisation-wide denies where you have Enterprise.
- Enable Adaptive Protection on critical policies and route its alerts to on-call.
- Report monthly on coverage, preview age, false positives and blocked traffic by rule.
Standards and references
- Google Cloud: Security Policy Overview
- Google Cloud: Preconfigured WAF Rules
- Google Cloud: Rate Limiting Overview
- Google Cloud: Adaptive Protection Overview
- Google Cloud: Request Logging
- Google Cloud: Configure Security Policies
- Google Cloud: Cloud Armor Enterprise Overview
- MITRE ATT&CK: Endpoint Denial of Service
Related NHI Mgmt Group resources: Google Cloud Security Guide · WAF and WAAP Buyer's Guide · Web Application Firewall Guide · DDoS Protection Guide · Google Cloud IAM and Service Accounts Guide