This page describes how you can create Google Cloud Armor security policies to filter incoming traffic to your application. For information about security policy concepts, see the Cloud Armor security policy overview.
Before you begin
Before you configure security policies, do the following:
Make sure that you're familiar with external Application Load Balancer concepts.
Examine your existing backend services to determine which ones don't have a security policy attached. These backend services and their associated backends are not protected. To add Cloud Armor protection, attach a new or existing security policy to the backend service.
Set up IAM permissions for Cloud Armor security policies
The following operations require the Identity and Access Management (IAM)
Compute Security Admin role
(roles/compute.securityAdmin):
- Configuring, modifying, updating, and deleting a Cloud Armor security policy
- Using the following API methods:
SecurityPolicies insertSecurityPolicies deleteSecurityPolicies patchSecurityPolicies addRuleSecurityPolicies patchRuleSecurityPolicies removeRule
A user with the
Compute Network Admin role
(roles/compute.networkAdmin) can perform the following operations:
- Setting a Cloud Armor security policy for a backend service
- Using the following API methods:
BackendServices setSecurityPolicyBackendServices list(gcloudonly)
Users with the Security Admin role
(roles/iam.securityAdmin) and the Compute Network Admin role
(roles/compute.networkAdmin) can view Cloud Armor security
policies by using the SecurityPolicies API methods get, list, and
getRule.
Set up IAM permissions for custom roles
The following table lists the IAM roles' base permissions, their associated API methods, and the roles that grant that permission.
| IAM permission | API methods | Roles |
|---|---|---|
compute.securityPolicies.create |
SecurityPolicies insert |
Compute Security Admin (roles/compute.securityAdmin) |
compute.securityPolicies.delete |
SecurityPolicies delete |
Compute Security Admin (roles/compute.securityAdmin) |
compute.securityPolicies.get |
SecurityPolicies getSecurityPolicies getRule |
Security Admin (roles/iam.securityAdmin) |
compute.securityPolicies.list |
SecurityPolicies list |
Security Admin (roles/iam.securityAdmin) |
Both of the following:
|
BackendServices |
Compute Network Admin (roles/compute.networkAdmin) |
compute.securityPolicies.update |
SecurityPolicies patchSecurityPolicies addRuleSecurityPolicies patchRuleSecurityPolicies removeRule |
Compute Security Admin (roles/compute.securityAdmin) |
Create security policies
Use the Cloud de Confiance console, the Google Cloud CLI, or the REST API to configure
Cloud Armor security policies, rules, and expressions. When you use
the gcloud CLI, use the --type flag to specify whether the security
policy is a backend security policy or an edge security policy.
If you're unfamiliar with security policy configuration, review the example security policies.
Sample expressions
The following are sample expressions. For more information, see the Cloud Armor custom rules language reference.
If your rule or expression uses ISO 3166-1 alpha-2 country or region codes, Cloud Armor treats each code independently. Cloud Armor rules and expressions use those codes to permit or deny requests.
The following expression matches requests from the IP address
1.2.3.4that contain the stringexamplein theUser-Agentheader:inIpRange(origin.ip, '1.2.3.4/32') && has(request.headers['user-agent']) && request.headers['user-agent'].contains('example')Alternatively, match on the IP address range of a custom client IP address header by using the
origin.user_ipattribute:inIpRange(origin.user_ip, '1.2.3.4/32') && has(request.headers['user-agent']) && request.headers['user-agent'].contains('example')The following expression matches requests that have a cookie with a specific value:
has(request.headers['cookie']) && request.headers['cookie'].contains('cookie_name=cookie_value')The following expression matches requests from the region
AU:origin.region_code == 'AU'
The following expression matches requests from the region
AUthat aren't in the specified IP range:origin.region_code == "AU" && !inIpRange(origin.ip, '1.2.3.0/24')
The following expression matches requests with a numbered variable path to a specific file if the URI matches a regular expression:
request.path.matches('/path/[0-9]+/target_file.html')The following expression matches requests if the Base64-decoded value of the
user-idheader contains a specific value:has(request.headers['user-id']) && request.headers['user-id'].base64Decode().contains('myValue')The following expression uses a preconfigured expression set to match against SQLi attacks:
evaluatePreconfiguredWaf('sqli-stable')
Path traversal and normalization
Normalize content in your path-based rules to manage path traversal and encoding rules and to create generalized rules that avoid capitalization or content-specific encoding.
When you write rules that use startsWith, endsWith, or contains to match
on request.path, use lower and urlDecode to normalize the path before
matching. This helps prevent bypasses that use URL-encoding or case variations.
For example, to block access to the /admin directory, use the following
expression:
request.path.lower().urlDecode().startsWith('/admin')
This rule blocks requests for /admin, /Admin, /a%64min, and other
variations.
When you write rules that use matches to match on request.path, account for
the backslash character (\) in your regular expression.
For example, to block access to the /admin directory, use the following
expression to block bypasses that use the backslash character (\):
request.path.matches(r'^/\\*admin')
Combine this with urlDecode to handle both URL-encoding and the backslash
character (\) bypasses:
request.path.urlDecode().matches(r'^/\\*admin')