# Language Reference

This document is the authoritative specification of the Rego policy language (V1). All policies in OPA are written in Rego.

## Built-in Functions

The built-in functions for the language provide basic operations to manipulate scalar values (e.g. numbers and strings), and aggregate functions that summarize complex types.

### Comparison

Built-in Inputs Description
`x == y` 2 `x` is equal to `y`
`x != y` 2 `x` is not equal to `y`
`x < y` 2 `x` is less than `y`
`x <= y` 2 `x` is less than or equal to `y`
`x > y` 2 `x` is greater than `y`
`x >= y` 2 `x` is greater than or equal to `y`

### Numbers

Built-in Inputs Description
`z = x + y` 2 `z` is the sum of `x` and `y`
`z = x - y` 2 `z` is the difference of `x` and `y`
`z = x * y` 2 `z` is the product of `x` and `y`
`z = x / y` 2 `z` is the quotient of `x` and `y`
`z = x % y` 2 `z` is the remainder from the division of `x` and `y`
`round(x, output)` 1 `output` is `x` rounded to the nearest integer
`abs(x, output)` 1 `output` is the absolute value of `x`

### Aggregates

Built-in Inputs Description
`count(collection_or_string, output)` 1 `output` is the length of the object, array, set, or string provided as input
`sum(array_or_set, output)` 1 `output` is the sum of the numbers in `array_or_set`
`product(array_or_set, output)` 1 `output` is the product of the numbers in `array_or_set`
`max(array_or_set, output)` 1 `output` is the maximum value in `array_or_set`
`min(array_or_set, output)` 1 `output` is the minimum value in `array_or_set`
`sort(array_or_set, output)` 1 `output` is the sorted `array` containing elements from `array_or_set`.
`all(array_or_set, output)` 1 `output` is `true` if all of the values in `array_or_set` are `true`. A collection of length 0 returns `true`.
`any(array_or_set, output)` 1 `output` is `true` if any of the values in `array_or_set` is `true`. A collection of length 0 returns `false`.

### Arrays

Built-in Inputs Description
`array.concat(array, array, output)` 2 `output` is the result of concatenating the two input arrays together.

### Sets

Built-in Inputs Description
`s3 = s1 & s2` 2 `s3` is the intersection of `s1` and `s2`.
`s3 = s1 | s2` 2 `s3` is the union of `s1` and `s2`.
`s3 = s1 - s2` 2 `s3` is the difference between `s1` and `s2`, i.e., the elements in `s1` that are not in `s2`
`intersection(set[set], output)` 1 `output` is the intersection of the sets in the input set
`union(set[set], output)` 1 `output` is the union of the sets in the input set

### Strings

Built-in Inputs Description
`concat(delimiter, array_or_set, output)` 2 `output` is the result of joining together the elements of `array_or_set` with the string `delimiter`
`contains(string, search)` 2 true if `string` contains `search`
`endswith(string, search)` 2 true if `string` ends with `search`
`format_int(number, base, output)` 2 `output` is string representation of `number` in the given `base`
`indexof(string, search, output)` 2 `output` is the index inside `string` where `search` first occurs, or -1 if `search` does not exist
`lower(string, output)` 1 `output` is `string` after converting to lower case
`replace(string, old, new, output)` 3 `output` is a `string` representing `string` with all instances of `old` replaced by `new`
`split(string, delimiter, output)` 2 `output` is `array[string]` representing elements of `string` separated by `delimiter`
`sprintf(string, values, output)` 2 `output` is a `string` representing `string` formatted by the values in the `array` `values`.
`startswith(string, search)` 2 true if `string` begins with `search`
`substring(string, start, length, output)` 2 `output` is the portion of `string` from index `start` and having a length of `length`. If `length` is less than zero, `length` is the remainder of the `string`.
`trim(string, cutset, output)` 2 `output` is a `string` representing `string` with all leading and trailing instances of the characters in `cutset` removed.
`upper(string, output)` 1 `output` is `string` after converting to upper case

### Regex

Built-in Inputs Description
`re_match(pattern, value)` 2 true if the `value` matches the regex `pattern`
`regex.split(pattern, string, output)` 2 `output` is `array[string]` representing elements of `string` separated by `pattern`
`regex.globs_match(glob1, glob2)` 2 true if the intersection of regex-style globs `glob1` and `glob2` matches a non-empty set of non-empty strings. The set of regex symbols is limited for this builtin: only `.`, `*`, `+`, `[`, `-`, `]` and `\` are treated as special symbols.
`regex.template_match(patter, string, delimiter_start, delimiter_end, output)` 4 `output` is true if `string` matches `pattern`. `pattern` is a string containing `0..n` regular expressions delimited by `delimiter_start` and `delimiter_end`. Example `regex.template_match("urn:foo:{.*}", "urn:foo:bar:baz", "{", "}", x)` returns `true` for `x`.
`regex.find_n(pattern, string, number)` 3 returns an `array[string]` with the `number` of values matching the `pattern`. A `number` of `-1` means all matches.

### Glob

Built-in Inputs Description
`glob.match(pattern, delimiters, match, output)` 3 `output` is true if `match` can be found in `pattern` which is separated by `delimiters`. For valid patterns, check the table below. Argument `delimiters` is an array of single-characters (e.g. `[".", ":"]`). If `delimiters` is empty, it defaults to `["."]`.
`glob.quote_meta(pattern, output)` 1 `output` is the escaped string of `pattern`. Calling `glob.quote_meta("*.github.com", output)` returns `\\*.github.com` as `output`.

The following table shows examples of how `glob.match` works:

`call` `output` Description
`glob.match("*.github.com", [], "api.github.com", output)` `true` A glob with the default `["."]` delimiter.
`glob.match("*:github:com", [":"], "api:github:com", output)` `true` A glob with delimiters `[":"]`.
`glob.match("api.**.com", [], "api.github.com", output)` `true` A super glob.
`glob.match("api.**.com", [], "api.cdn.github.com", output)` `true` A super glob.
`glob.match("?at", [], "cat", output)` `true` A glob with a single character wildcard.
`glob.match("?at", [], "at", output)` `false` A glob with a single character wildcard.
`glob.match("[abc]at", [], "bat", output)` `true` A glob with character-list matchers.
`glob.match("[abc]at", [], "cat", output)` `true` A glob with character-list matchers.
`glob.match("[abc]at", [], "lat", output)` `false` A glob with character-list matchers.
`glob.match("[!abc]at", [], "cat", output)` `false` A glob with negated character-list matchers.
`glob.match("[!abc]at", [], "lat", output)` `true` A glob with negated character-list matchers.
`glob.match("[a-c]at", [], "cat", output)` `true` A glob with character-range matchers.
`glob.match("[a-c]at", [], "lat", output)` `false` A glob with character-range matchers.
`glob.match("[!a-c]at", [], "cat", output)` `false` A glob with negated character-range matchers.
`glob.match("[!a-c]at", [], "lat", output)` `true` A glob with negated character-range matchers.
`glob.match(""{cat,bat,[fr]at}", [], "cat", output)` `true` A glob with pattern-alternatives matchers.
`glob.match(""{cat,bat,[fr]at}", [], "bat", output)` `true` A glob with pattern-alternatives matchers.
`glob.match(""{cat,bat,[fr]at}", [], "rat", output)` `true` A glob with pattern-alternatives matchers.
`glob.match(""{cat,bat,[fr]at}", [], "at", output)` `false` A glob with pattern-alternatives matchers.

### Types

Built-in Inputs Description
`to_number(x, output)` 1 `output` is `x` converted to a number
`is_number(x, output)` 1 `output` is `true` if `x` is a number
`is_string(x, output)` 1 `output` is `true` if `x` is a string
`cast_string(x, output)` 1 `output` is `x` cast to a string
`is_boolean(x, output)` 1 `output` is `true` if `x` is a boolean
`cast_boolean(x, output)` 1 `output` is `x` cast to a boolean
`is_array(x, output)` 1 `output` is `true` if `x` is an array
`cast_array(x, output)` 1 `output` is `x` cast to an array
`is_set(x, output)` 1 `output` is `true` if `x` is a set
`cast_set(x, output)` 1 `output` is `x` cast to a set
`is_object(x, output)` 1 `output` is `true` if `x` is an object
`cast_object(x, output)` 1 `output` is `x` cast to an object
`is_null(x, output)` 1 `output` is `true` if `x` is null
`cast_null(x, output)` 1 `output` is `x` cast to null
`type_name(x, output)` 1 `output` is the type of `x`

### Encoding

Built-in Inputs Description
`base64.encode(x, output)` 1 `output` is `x` serialized to a base64 encoded string
`base64.decode(string, output)` 1 `output` is `x` deserialized from a base64 encoding string
`base64url.encode(x, output)` 1 `output` is `x` serialized to a base64url encoded string
`base64url.decode(string, output)` 1 `output` is `string` deserialized from a base64url encoding string
`urlquery.encode(string, output)` 1 `output` is `string` serialized to a URL query parameter encoded string
`urlquery.encode_object(object, output)` 1 `output` is `object` serialized to a URL query parameter encoded string
`urlquery.decode(string, output)` 1 `output` is `string` deserialized from a URL query parameter encoded string
`json.marshal(x, output)` 1 `output` is `x` serialized to a JSON string
`json.unmarshal(string, output)` 1 `output` is `string` deserialized to a term from a JSON encoded string
`yaml.marshal(x, output)` 1 `output` is `x` serialized to a YAML string
`yaml.unmarshal(string, output)` 1 `output` is `string` deserialized to a term from YAML encoded string

### Tokens

Built-in Inputs Description
`io.jwt.verify_rs256(string, certificate, output)` 1 `output` is `true` if the RS256 signature of the input token is valid. `certificate` is the PEM encoded certificate used to verify the RS256 signature
`io.jwt.verify_ps256(string, certificate, output)` 1 `output` is `true` if the PS256 signature of the input token is valid. `certificate` is the PEM encoded certificate used to verify the PS256 signature
`io.jwt.verify_es256(string, certificate, output)` 1 `output` is `true` if the ES256 signature of the input token is valid. `certificate` is the PEM encoded certificate used to verify the ES256 signature
`io.jwt.verify_hs256(string, secret, output)` 1 `output` is `true` if the Secret signature of the input token is valid. `secret` is a plain text secret used to verify the HS256 signature
`io.jwt.decode(string, [header, payload, sig])` 1 `header` and `payload` are `object`. `signature` is the hexadecimal representation of the signature on the token.
`io.jwt.decode_verify(string, constraints, [valid, header, payload])` 2 If the input token verifies and meets the requirements of `constraints` then `valid` is `true` and `header` and `payload` are objects containing the JOSE header and the JWT claim set. Otherwise, `valid` is `false` and `header` and `payload` are `{}`.

The input `string` is a JSON Web Token encoded with JWS Compact Serialization. JWE and JWS JSON Serialization are not supported. If nested signing was used, the `header`, `payload` and `signature` will represent the most deeply nested token.

For `io.jwt.decode_verify`, `constraints` is an object with the following members:

Name Meaning Required
`cert` A PEM encoded certificate containing an RSA or ECDSA public key. See below
`secret` The secret key for HS256, HS384 and HS512 verification. See below
`alg` The JWA algorithm name to use. If it is absent then any algorithm that is compatible with the key is accepted. Optional
`iss` The issuer string. If it is present the only tokens with this issuer are accepted. If it is absent then any issuer is accepted. Optional
`time` The time in nanoseconds to verify the token at. If this is present then the `exp` and `nbf` claims are compared against this value. If it is absent then they are compared against the current time. Optional
`aud` The audience that the verifier identifies with. If this is present then the `aud` claim is checked against it. If it is absent then the `aud` claim must be absent too. Optional

Exactly one of `cert` and `secret` must be present. If there are any unrecognized constraints then the token is considered invalid.

### Time

Built-in Inputs Description
`time.now_ns(output)` 0 `output` is `number` representing the current time since epoch in nanoseconds.
`time.parse_ns(layout, value, output)` 2 `output` is `number` representing the time `value` in nanoseconds since epoch. See the Go `time` package documentation for more details on `layout`.
`time.parse_rfc3339_ns(value, output)` 1 `output` is `number` representing the time `value` in nanoseconds since epoch.
`time.parse_duration_ns(duration, output)` 1 `output` is `number` representing the duration `duration` in nanoseconds. See the Go `time` package documentation for more details on `duration`.
`time.date(ns, [year, month, day])` 1 outputs the `year`, `month` (0-12), and `day` (0-31) as `number`s representing the date from the nanoseconds since epoch (`ns`).
`time.clock(ns, [hour, minute, second])` 1 outputs the `hour`, `minute` (0-59), and `second` (0-59) as `number`s representing the time of day for the nanoseconds since epoch (`ns`).
`time.weekday(ns, day)` 1 outputs the `day` as `string` representing the day of the week for the nanoseconds since epoch (`ns`).

Multiple calls to the `time.now_ns` built-in function within a single policy evaluation query will always return the same value.

### Cryptography

Built-in Inputs Description
`crypto.x509.parse_certificates(string, array[object])` 1 `output` is an array of X.509 certificates represented as JSON objects.

### Graphs

Built-in Inputs Description
`walk(x, [path, value])` 0 `walk` is a relation that produces `path` and `value` pairs for documents under `x`. `path` is `array` representing a pointer to `value` in `x`. Queries can use `walk` to traverse documents nested under `x` (recursively).

### HTTP

Built-in Inputs Description
`http.send(request, output)` 1 `http.send` executes a HTTP request and returns the response.`request` is an object containing keys `method`, `url` and optionally `body`, `enable_redirect` and `headers`. For example, `http.send({"method": "get", "url": "http://www.openpolicyagent.org/", "headers": {"X-Foo":"bar", "X-Opa": "rules"}}, output)`. `output` is an object containing keys `status`, `status_code` and `body` which represent the HTTP status, status code and response body respectively. Sample output, `{"status": "200 OK", "status_code": 200, "body": null`}. By default, http redirects are not enabled. To enable, set `enable_redirect` to `true`.

### Net

Built-in Inputs Description
`net.cidr_overlap(cidr, ip, output)` 2 `output` is `true` if `ip` (e.g. `127.0.0.1`) overlaps with `cidr` (e.g. `127.0.0.1/24`) and false otherwise. Supports both IPv4 and IPv6 notations.

### Rego

Built-in Inputs Description
`rego.parse_module(filename, string, output)` 2 `rego.parse_module` parses the input `string` as a Rego module and returns the AST as a JSON object `output`.

### OPA

Built-in Inputs Description
`opa.runtime(output)` 0 `opa.runtime` returns a JSON object `output` that describes the runtime environment where OPA is deployed. Caution: Policies that depend on the output of `opa.runtime` may return different answers depending on how OPA was started. If possible, prefer using an explicit `input` or `data` value instead of `opa.runtime`. The `output` of `opa.runtime` will include a `"config"` key if OPA was started with a configuration file. The `output` of `opa.runtime` will include a `"env"` key containing the environment variables that the OPA process was started with.

### Debugging

Built-in Inputs Description
`trace(string)` 1 `trace` outputs the debug message `string` as a `Note` event in the query explanation. For example, `trace("Hello There!")` includes `Note "Hello There!"` in the query explanation. To print variables, use sprintf. For example, `person = "Bob"; trace(sprintf("Hello There! %v", [person]))` will emit `Note "Hello There! Bob"`.

## Reserved Names

The following words are reserved and cannot be used as variable names, rule names, or dot-access style reference arguments:

``````as
default
else
false
import
package
not
null
true
with
``````

## Grammar

Rego’s syntax is defined by the following grammar:

``````module          = package { import } policy
package         = "package" ref
import          = "import" package [ "as" var ]
policy          = { rule }
rule            = [ "default" ] rule-head { rule-body }
rule-head       = var [ "(" rule-args ")" ] [ "[" term "]" ] [ = term ]
rule-args       = term { "," term }
rule-body       = [ else [ = term ] ] "{" query "}"
query           = literal { ";" | [\r\n] literal }
literal         = ( expr | "not" expr ) { with-modifier }
with-modifier   = "with" term "as" term
instructions    = expr { ";" | [\r\n] expr }
expr            = term | expr-built-in | expr-infix
expr-built-in   = var [ "." var ] "(" [ term { , term } ] ")"
expr-infix      = [ term "=" ] term infix-operator term
term            = ref | var | scalar | array | object | set | array-compr
array-compr     = "[" term "|" rule-body "]"
set-compr       = "{" term "|" rule-body "}"
object-compr    = "{" object-item "|" rule-body "}"
infix-operator  = bool-operator | arith-operator | bin-operator
bool-operator   = "=" | "!=" | "<" | ">" | ">=" | "<="
arith-operator  = "+" | "-" | "*" | "/"
bin-operator    = "&" | "|"
ref             = var { ref-arg }
ref-arg         = ref-arg-dot | ref-arg-brack
ref-arg-brack   = "[" ( scalar | var | array | object | set | "_" ) "]"
ref-arg-dot     = "." var
var             = ( ALPHA | "_" ) { ALPHA | DIGIT | "_" }
scalar          = string | NUMBER | TRUE | FALSE | NULL
string          = STRING | raw-string
raw-string      = "`" { CHAR-"`" } "`"
array           = "[" term { "," term } "]"
object          = "{" object-item { "," object-item } "}"
object-item     = ( scalar | ref | var ) ":" term
set             = empty-set | non-empty-set
non-empty-set   = "{" term { "," term } "}"
empty-set       = "set(" ")"
``````

The grammar defined above makes use of the following syntax. See the Wikipedia page on EBNF for more details:

``````[]     optional (zero or one instances)
{}     repetition (zero or more instances)
|      alternation (one of the instances)
()     grouping (order of expansion)
STRING JSON string
NUMBER JSON number
TRUE   JSON true
FALSE  JSON false
NULL   JSON null
CHAR   Unicode character
ALPHA  ASCII characters A-Z and a-z
DIGIT  ASCII characters 0-9
``````