TLDR; you can say any of these:
count(deny) == 0 with input as {"allowed":"yes"}
deny == set() with input as {"allowed":"yes"}
not deny["Must be allowed"] with input as {"allowed":"yes"}
The last one checks if the set does not contain a specific message. This is a good idea if you have multiple deny
rules inside the same package.
The not deny with input as ...
statement fails because the not
keyword only inverts undefined/false statements (making them true). In this case, deny
refers to a set of values. The set can be empty but it's never undefined/false.
In OPA/Rego, all rules are just IF-THEN statements that assign values to variables. If the "IF" portion is the logic in the rule body. The "THEN" portion is the assignment in the rule head. There are two kinds of IF-THEN statements (aka rules):
- Complete rules, e.g.,
deny = true { input.allowed == "no" }
- Partial rules, e.g.,
deny[msg] { input.allowed == "no" }
Complete rules assign a SINGLE value to a variable. If you omit the value it defaults to true (e.g., deny = true { ... }
and deny { ... }
mean the same thing.) When the "IF" portion of the rule is true/satisfied, the variable is assigned the value. When the "IF" portion of the rule is false/not satisfied, the variable is undefined. This is slightly different from false
but in most cases that's not important.
Partial rules assign MULTIPLE values to a variable. In other words, they define a SET of values. When the "IF" portion of the rule is true/satisfied, the value defined in the rule head is added to the set, otherwise the value is NOT added. If no values are added to the set, it's still defined--it's just empty.
This is covered in the introduction: https://www.openpolicyagent.org/docs/latest/#rules
For more examples and information on rules see https://www.openpolicyagent.org/docs/latest/policy-language/#rules