Configure custom rules language attributes

Each Google Cloud Armor security policy rule has a priority, a match condition, and an action. Cloud Armor performs the action of the highest priority rule that matches a request. Rules with a lower priority than the highest priority matching rule are not evaluated, even if they have the same match conditions.

Each security policy rule supports two types of match conditions:

  • A basic match condition contains lists of IP addresses or lists of IP address ranges. Basic match conditions are defined by using the --src-ip-ranges flag when creating a rule using the Google Cloud CLI.
  • An advanced match condition contains an expression with up to five subexpressions that can match a variety of attributes of an incoming request. Advanced match conditions are defined using the --expression flag when creating a rule using the Google Cloud CLI.

This page discusses advanced match conditions and the Cloud Armor custom rules language that you use to write expressions in the advanced match conditions of security policy rules. The Cloud Armor custom rules language is a subset of the Common Expression Language (CEL). Expressions written in the Cloud Armor custom rules language require two components:

  • The attribute: the data to inspect
  • The operation: how to use the data

For example, the following expression uses the attributes origin.ip and 198.51.100.0/24 in the operation inIpRange. In this case, the expression returns true if origin.ip is within the 198.51.100.0/24 IP address range.

inIpRange(origin.ip, '198.51.100.0/24')

Even though the previous example expression only matches on client IP address, when you use the example expression in a Cloud Armor security policy rule, the rule is considered a rule with advanced match conditions from a quota perspective. For more information, see Cloud Armor quotas and limits.

Operations

The following reference describes the operators that you can use with attributes (represented by x, y, and k) to define rule expressions.

Operations Expressions Description
Equality x == y Returns true if x is equal to y.
Equality, string literal x == "foo" Returns true if x is equal to the given constant string literal.
Equality, raw string literal x == R"fo'o" Returns true if x is equal to the given raw string literal that does not interpret escape sequences. Raw string literals are convenient for expressing strings that themselves must use escape sequence characters.
Logical NOT !x Returns true if the Boolean value x is false, or returns false if the Boolean value x is true.
Inequality x != y Returns true if x is not equal to y.
Concatenation x + y Returns the concatenated string xy.
Logical AND x && y Returns true if both x and y are true.
Logical OR x || y Returns true if x, y, or both are true.
Contains substring x.contains(y) Returns true if the string x contains the substring y.
Starts with substring x.startsWith(y) Returns true if the string x begins with the substring y.
Ends with substring x.endsWith(y) Returns true if the string x ends with the substring y.
Regular expression match x.matches(y) Returns true if the string x is partially matched by the specified RE2 pattern y. The RE2 pattern is compiled by using the RE2::Latin1 option that disables Unicode features.
IP address within range inIpRange(x, y) Returns true if the IP address x is contained within the IP range y.
Lowercase x.lower() Returns the lowercase value of the string x.
Uppercase x.upper() Returns the uppercase value of the string x.
Base64 decoded value x.base64Decode() Returns the base64 decoded value of x; the underscore (_) and hyphen (-) are first replaced with forward slash (/) and plus sign (+) respectively. Returns "" (empty string) if x is not a valid base64 value.
Key-map value m['k'] Returns the value at key k in the string-to-string map m if k is available; otherwise, returns an error. Recommended approach is to first check for availability by using "has(m['k'])==true".
Check key availability in a map has(m['k']) Returns true if key k is available in the map m.
Convert to integer int(x) Converts the string result of x to an int type. It can then be used to do an integer comparison by using standard arithmetic operators such as > and <=. This works only for values that are supposed to be integers.
Length size(x) Returns the length of string x.
Decode URL x.urlDecode() Returns the url-decoded value of x; character sequences in %## format are replaced with the non-ASCII equivalents, and + is replaced with a space. Invalid encodings are returned as-is.
Decode URL (Unicode) x.urlDecodeUni() Returns the url-decoded value of x; in addition to urlDecode(), this also handles unicode character sequences in %u### format. Invalid encodings are returned as-is.
Convert utf8 to Unicode x.utf8ToUnicode() Returns the lowercase Unicode representation of a UTF-8 encoded x.

Attributes

Attributes represent information from an incoming request, such as the client IP address or the requested URL path.

Field Type Field description
origin.ip string The IP address of the client that initiated the request.
origin.user_ip string The IP address of the originating client, which is included in the HTTP-HEADER by an upstream proxy. Before you use this attribute, you must configure the userIpRequestHeaders[] option in the security policy's advancedOptionsConfig field to match a source like True-Client-IP, X-Forwarded-For, or X-Real-IP. For more information, see User IP addresses overview.

If you don't configure the userIpRequestHeaders[] option, if the configured header contains invalid IP address values, or if the configured header is not present, origin.user_ip defaults to origin.ip. For more information, see the securityPolicy resource reference.

origin.tls_ja4_fingerprint string JA4 TLS/SSL fingerprint if the client connects using HTTPS, HTTP/2, or HTTP/3. If not available, an empty string is returned.
origin.tls_ja3_fingerprint string JA3 TLS/SSL fingerprint if the client connects using HTTPS, HTTP/2, or HTTP/3. If not available, an empty string is returned.
request.headers map A string-to-string map of the HTTP request headers. If a header contains multiple values, the value in this map would be a comma-separated string of all of the values of the header. The keys in this map are all lowercase. All headers accepted by external Application Load Balancers are inspected, and the same header limitations apply.

Recommended approach is to first check for availability using has(), such as