# 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](https://golang.org/pkg/time/#Parse) 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](https://golang.org/pkg/time/#ParseDuration) 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)`` | 3+ | ``http.send`` executes a HTTP request and returns the response.``request`` is an object containing keys ``method``, ``url`` and optionally ``body``, ``enable_redirect``, ``headers``, ``tls_use_system_certs``, ``tls_ca_cert_file``, ``tls_ca_cert_env_variable``, ``tls_client_cert_env_variable``, ``tls_client_key_env_variable`` or ``tls_client_cert_file``, ``tls_client_key_file`` . 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``.|
#### HTTPs Usage
The following table explains the HTTPs objects
| Object | Definition | Value|
| -------- |-----------|------|
| tls_use_system_certs | Use system certificate pool | true or false
| tls_ca_cert_file | Path to file containing a root certificate in PEM encoded format | double-quoted string
| tls_ca_cert_env_variable | Environment variable containing a root certificate in PEM encoded format | double-quoted string
| tls_client_cert_env_variable | Environment variable containing a client certificate in PEM encoded format | double-quoted string
| tls_client_key_env_variable | Environment variable containing a client key in PEM encoded format | double-quoted string
| tls_client_cert_file | Path to file containing a client certificate in PEM encoded format | double-quoted string
| tls_client_key_file | Path to file containing a key in PEM encoded format | double-quoted string
In order to trigger the use of HTTPs the user must provide one of the following combinations:
* ``tls_client_cert_file``, ``tls_client_key_file``
* ``tls_client_cert_env_variable``, ``tls_client_key_env_variable``
The user must also provide a trusted root CA through tls_ca_cert_file or tls_ca_cert_env_variable. Alternatively the user could set tls_use_system_certs to ``true`` and the system certificate pool will be used.
#### HTTPs Examples
| Examples | Comments |
| -------- |-----------|
| Files containing TLS material | ``http.send({"method": "get", "url": "https://127.0.0.1:65331", "tls_ca_cert_file": "testdata/ca.pem", "tls_client_cert_file": "testdata/client-cert.pem", "tls_client_key_file": "testdata/client-key.pem"}, output)``.
|Environment variables containing TLS material | ``http.send({"method": "get", "url": "https://127.0.0.1:65360", "tls_ca_cert_env_variable": "CLIENT_CA_ENV", "tls_client_cert_env_variable": "CLIENT_CERT_ENV", "tls_client_key_env_variable": "CLIENT_KEY_ENV"}, output)``.|
| Accessing Google using System Cert Pool | ``http.send({"method": "get", "url": "https://www.google.com", "tls_use_system_certs": true, "tls_client_cert_file": "testdata/client-cert.pem", "tls_client_key_file": "testdata/client-key.pem"}, output)``
### 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
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 | object-compr | set-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](https://en.wikipedia.org/wiki/Extended_Backus–Naur_Form) 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
```