Conditions :: Cerbos Authorization Management Platform // Documentation
Conditions
| This documentation is for a previous version of Cerbos. Choose 0.53.0 from the version picker at the top right or navigate to https://docs.cerbos.dev for the latest version. |
A powerful feature of Cerbos policies is the ability to define conditions that are evaluated against the data provided in the request. Conditions are written using the Common Expression Language (CEL).
Cerbos ships with an interactive REPL that can be used to experiment with writing CEL conditions. It can be started by running cerbos repl. See the REPL documentation for more information. |
Every condition expression must evaluate to a boolean true/false value. A condition block in a policy can contain either a single condition expression, or multiple expressions combined using the all, any, or none operators. These logical operators may be nested.
Condition block
condition:
match:
all:
of:
- expr: request.resource.attr.status == "PENDING_APPROVAL"
- expr: >
"GB" in request.resource.attr.geographies
Top-level identifiers
Within a condition expression, you have access to several top-level identifiers:
request
Data provided in the check or plan request (principal, resource, and auxiliary data).
runtime
Additional data computed while evaluating the policy.
variables
Variables declared in the variables section of the policy.
globals
Global variables declared in the policy engine configuration.
There are also single-letter aliases available to allow you to write terser expressions:
P
request.principal
R
request.resource
V
variables
G
globals
The request object
request:
principal: (1)
id: alice (2)
roles: (3)
- employee
attr: (4)
geography: GB
resource: (5)
kind: leave_request (6)
id: XX125 (7)
attr: (8)
owner: alice
auxData: (9)
jwt: (10)
iss: acme.corp
| 1 | The principal whose permissions are being checked. |
| 2 | ID of the principal. |
| 3 | Static roles that are assigned to the principal by your identity management system. |
| 4 | Free-form context data about the principal. |
| 5 | The resource on which the principal is performing actions. |
| 6 | Resource kind. |
| 7 | ID of the resource instance. |
| 8 | Free-form context data about the resource instance. |
| 9 | Auxiliary data sources. |
| 10 | JWT claims. |
The runtime object
runtime:
effectiveDerivedRoles: (1)
- owner
- gb_employee
| 1 | Derived roles that were assigned to to the principal by Cerbos while evaluating the policy. This is only populated in expressions in resource policies, and only includes derived roles that are referenced in at least one policy rule. |
Expressions and blocks
Single boolean expression
condition:
match:
expr: P.id.matches("^dev_.*")
all operator: all expressions must evaluate to true (logical AND)
condition:
match:
all:
of:
- expr: R.attr.status == "PENDING_APPROVAL"
- expr: >
"GB" in R.attr.geographies
- expr: P.attr.geography == "GB"
any operator: only one of the expressions has to evaluate to true (logical OR)
condition:
match:
any:
of:
- expr: R.attr.status == "PENDING_APPROVAL"
- expr: >
"GB" in R.attr.geographies
- expr: P.attr.geography == "GB"
none operator: none of the expressions should evaluate to true (logical negation)
condition:
match:
none:
of:
- expr: R.attr.status == "PENDING_APPROVAL"
- expr: >
"GB" in R.attr.geographies
- expr: P.attr.geography == "GB"
Nesting operators
condition:
match:
all:
of:
- expr: R.attr.status == "DRAFT"
- any:
of:
- expr: R.attr.dev == true
- expr: R.attr.id.matches("^[98][0-9]+")
- none:
of:
- expr: R.attr.qa == true
- expr: R.attr.canary == true
Quotes in expressions
Single and double quotes have special meanings in YAML. To avoid parsing errors when your expression contains quotes, use the YAML block scalar syntax or wrap the expression in parentheses.
expr: >
"GB" in R.attr.geographies
Policy variables
To avoid duplication in condition expressions, you can define variables in policies.
Auxiliary data
If you have auxiliary data sources configured, they can be accessed using request.auxData.
Accessing JWT claims
"cerbie" in request.auxData.jwt.aud && request.auxData.jwt.iss == "cerbos"
Operators
| Operator | Description |
|---|---|
! |
Logical negation (NOT) |
- |
Subtraction/numeric negation |
!= |
Unequals |
% |
Modulo |
&& |
Logical AND |
| ` | |
* |
Multiplication |
+ |
Addition/concatenation |
/ |
Division |
⇐ |
Less than or equal to |
< |
Less than |
== |
Equals |
>= |
Greater than or equal to |
> |
Greater than |
in |
Membership in lists or maps |
? : |
Ternary condition (if-then-else) |
Durations
| Suffix | Unit |
|---|---|
ns |
Nanoseconds |
us |
Microseconds |
ms |
Milliseconds |
s |
Seconds |
m |
Minutes |
h |
Hours |
Test data
...
"resource": {
"kind": "leave_request",
"attr": {
"cooldownPeriod": "3750s",
"lastAccessed": "2021-04-20T10:00:20.021-05:00"
}
}
...```
## Hierarchies
| Function | Description | Example |
| --- | --- | --- |
| `hierarchy` | Convert a dotted string or a string list to a hierarchy | `hierarchy("a.b.c") == hierarchy(["a","b","c"])` |
| `ancestorOf` | Returns true if the first hierarchy shares a common prefix with the second hierarchy | `hierarchy("a.b").ancestorOf(hierarchy("a.b.c.d")) == true` |
## IP addresses
| Function | Description | Example |
| --- | --- | --- |
| `inIPAddrRange` | Check whether the IP address is in the range defined by the CIDR | `P.attr.ipv4Address.inIPAddrRange("192.168.0.0/24") && P.attr.ipv6Address.inIPAddrRange("2001:db8::/48")` |
## Lists and maps
| Operator/Function | Description | Example |
| --- | --- | --- |
| `+` | Concatenates lists | `P.attr.teams + ["design", "engineering"]` |
| `exists` | Check whether at least one element matching the predicate exists | `P.attr.teams.exists(t, t.startsWith("comm"))` |
## Math
| Function | Description | Example |
| --- | --- | --- |
| `math.greatest` | Get the greatest valued number present in the arguments | `math.greatest([1, 3, 5]) == 5` |
## Strings
| Function | Description | Example |
| --- | --- | --- |
| `base64.encode` | Encode as base64 | `base64.encode(bytes("hello")) == "aGVsbG8="` |
## Timestamps
| Function | Description | Example |
| --- | --- | --- |
| `timestamp` | Convert an RFC3339 formatted string to a timestamp | `timestamp(R.attr.lastAccessed).getFullYear() == 2021` |
### Example: Assert that more than 36 hours has elapsed between last access time and last update time
```yaml
timestamp(R.attr.lastUpdateTime) - timestamp(R.attr.lastAccessed) > duration("36h")
Example: Add a duration to a timestamp
timestamp(R.attr.lastUpdateTime) + duration("24h") == timestamp("2021-05-02T13:34:12.024Z")