Rego Keyword: if
The if
keyword is used when defining rules in Rego. if
separates the
rule head from the rule body, making it clear which part of the rule is
is the condition (the part following the if
).
The keyword is also use to make the policy rules written in Rego easier to read by being more 'English-like'. For example:
rule := "some value" if some_condition
Examples
Defining simple rules
Most commonly, if
is used to create boolean rules where if any rule head is
true, then the whole rule is true. In this simple example, when both:
- the
input.role
field is present, - and set to the value of "admin"
Then, the allow
rule will be true
. If either of these conditions is not met,
the rule will be false
.
package play
import rego.v1
allow if input.role == "admin"
allow if {
path[0] == "users"
path[1] == input.user_id
}
{
"role": "admin",
"path": [
"payments",
"approve"
]
}
{}
Rule | Output Value |
---|---|
allow | true |
Defining multi-value rules
The if
keyword is used for all rules though, including rules that create
objects and sets.
package play
import rego.v1
# missing_paths creates a set missing input paths
missing_paths contains path if {
some path in data.required_paths
parts := split(path, ".")
object.get(input, parts, "") == ""
}
# validations is a mapping of input paths to error messages
validations[path] contains "path must be set" if {
some path, _ in missing_paths
}
# role and email have additional validation rules
validations.role contains "role cannot be blank" if {
input.role == ""
}
validations.email contains message if {
not endswith(input.email, "@example.com")
message := sprintf("email %s must end with @example.com", [input.email])
}
{
"roles": [
"admin"
],
"email": "admin@example.net",
"request": {
"headers": {},
"path": "/v1/payments"
}
}
{
"required_paths": [
"request.method",
"request.path",
"request.headers",
"role",
"email"
]
}
Rule | Output Value |
---|---|
validations | {"email":["email admin@example.net must end with @example.com"],"request.method":["path must be set"],"role":["path must be set"]} |
Defining functions
if
is also used in functions. Much like rules, in Rego functions can have one
or more heads. The head and body of a function are also separated by the if
keyword for consistency and readability.
In this example, we can see that the is_sudo
function is incrementally defined
where each head adds new cases to the functionality. In this case, each head
defines scenarios where the user is a 'sudoer' - both when the user is an admin
or when the user has the sudo field set.
package play
import rego.v1
default is_sudo(_) := false
is_sudo(user) if {
user.role == "admin"
}
is_sudo(user) if {
user.sudo == true
}
allow if is_sudo(input.user)
{
"user": {
"sudo": false
}
}
{}
Rule | Output Value | Notes |
---|---|---|
allow | undefined | Since there is no default for allow, it is undefined. |
When if is not used
if
is everywhere in Rego, but there are some cases where we don't use it.
{}
{}
package play
default allow := false # not in default cases
my_constant := 42 # not for constants
# not for rule names
if {
input.admin
}
allow if {
# not inside rules
input.admin if input.roles.admin == true
}
Further Reading
Below are some links that provide more information about the if
keyword:
- If you are interested in learning about why
if
was added to Rego, see the notes in the OPA v1.0 documentation. - Read the release notes from when the
if
keyword was added to Rego in OPA v0.42.0. - Using
if
is also recommended by Regal.