Skip to main content

ABAC condition operators

This reference lists every operator you can use in the conditions of an attribute-based access control (ABAC) condition set created through the Permit API. It is for developers who write condition JSON by hand. For how the pieces fit together, see the ABAC API overview.

A condition uses two kinds of operators:

  • Logical operators combine conditions: allOf, anyOf, and not.
  • Comparison operators test one attribute against a value: equals, in, greater-than, and others.

Logical operators

Logical operators combine several conditions into one boolean result. The allOf and anyOf operators take an array of conditions. The not operator takes a single nested condition or operator, not an array.

Logical operatorKey in the conditionAlternative keyResult
ANDallOfandtrue when every condition in the array is true
ORanyOfortrue when at least one condition in the array is true
NOTnotnonetrue when the nested condition is false

Comparison operators

A comparison operator object holds exactly one operator key and its operand, for example {"greater-than": 18}. To apply two comparisons to one attribute, combine them with a logical operator.

OperatorKey in the conditionResult is true whenOperand type
Equalsequalsa = bBool, Number, String
Does not equalnot-equalsa != bBool, Number, String
Less thanless-thana < bNumber or ISO 8601 date
Greater thangreater-thana > bNumber or ISO 8601 date
Less than or equalless-than-equalsa ≤ bNumber or ISO 8601 date
Greater than or equalgreater-than-equalsa ≥ bNumber or ISO 8601 date
Ininthe attribute value is one of the values in the operand arrayArray
Betweenbetweenthe attribute value is between a lower bound and an upper boundArray of exactly two numbers
Containscontainsthe string attribute contains the operand string, for example "aaa??bbbbbb" contains "??"String
Matchesmatchthe attribute value matches a glob patternString (glob)
Array containsarray_containsthe array attribute contains the operand, for example ["a", "b", "c"] contains "a"Array attribute
Array subsetarray_subsetevery item of the array attribute is in the operand, for example ["a", "b"] is a subset of ["a", "b", "c"]Array
Array supersetarray_supersetthe array attribute contains every item of the operand, for example ["a", "b", "c"] is a superset of ["a", "b"]Array
Array intersectarray_intersectthe array attribute and the operand share at least one value, for example ["a", "b", "c"] and ["c", "d", "e"]Array
Array length equalsarray_len_equalsthe array attribute has exactly the operand number of itemsNumber
Array length greater thanarray_len_greater_thanthe array attribute has more items than the operandNumber
Array length less thanarray_len_less_thanthe array attribute has fewer items than the operandNumber

Compare two attributes with a reference

To compare an attribute with another attribute instead of a fixed value, pass a reference object {"ref": "<object>.<attribute>"} as the operand. The reference is resolved when the policy decision point (PDP) evaluates the check.

Comparison with a referenceExampleAttribute type
Equalsresource owner equals the user emailNumber, Array, String
Does not equalresource owner does not equal the user keyNumber, Array, String
Containstenant name contains the user first_nameString
Array contains["admin", "editor"] contains the user roleArray
Less thana < user.ageNumber
Greater thana > user.ageNumber
Less than or equala ≤ user.ageNumber
Greater than or equala ≥ user.ageNumber
Reference operand example

The following condition is true when the user's email contains the user's first name. The contains operator receives {"ref": "user.first_name"} as its operand.

{
"allOf": [
{
"user.email": {
"contains": {
"ref": "user.first_name"
}
}
}
]
}

Object match operators

Object match operators run several comparisons on the fields of an attribute of type Object or Object Array. Use them when an attribute stores a dictionary, or an array of dictionaries, in the same shape as your source data.

Match the fields of an Object attribute

Suppose the user attribute user.organization has type Object and holds this value:

{
"name": "Cool Inc",
"country": "US",
"subscription": "pro",
...
}

You want a user set of users whose organization is located in the US and has a pro subscription.

If you store each field as a separate Permit attribute, standard comparison operators are enough:

{
"allOf": [
{"user.country": {"equals": "US"}},
{"user.subscription": {"equals": "pro"}}
]
}

With a single user.organization attribute of type Object, use object_match:

{
"allOf": [
{
"user.organization": {
"object_match": {
"match": {
"country": {"equals": "US"},
"subscription": {"equals": "pro"}
}
}
}
}
]
}

Inside the match object, apply one comparison operator to each field. The object_match operator returns true only when every field comparison is true.

Object attributes keep your data close to its source format. Use any_match or all_match when the attribute is an array of objects, because an array can't be split into separate attributes.

Match the items of an Object Array attribute

Suppose the user attribute user.organizations has type Object Array, because a user can belong to several organizations:

[
{
"name": "Cool Inc",
"country": "US",
"subscription": "pro",
...
},
{
"name": "Awesome Inc",
"country": "IN",
"subscription": "enterprise",
...
},
{
"name": "Sweet Inc",
"country": "US",
"subscription": "enterprise",
...
}
]

To match users with at least one organization located in the US with a pro subscription, use any_match. The match object applies to each item of the array:

{
"allOf": [
{
"user.organizations": {
"any_match": {
"match": {
"country": {"equals": "US"},
"subscription": {"equals": "pro"}
}
}
}
}
]
}

The any_match condition is true when at least one item in user.organizations has country equal to "US" and subscription equal to "pro".

To require that every item in the array matches, replace any_match with all_match:

{
"allOf": [
{
"user.organizations": {
"all_match": {
"match": {
"country": {"equals": "US"},
"subscription": {"equals": "pro"}
}
}
}
}
]
}

Object match operator reference

OperatorKey in the conditionResult is true whenAttribute type
Object matchobject_matchevery field condition in match is true for the objectObject
Any matchany_matchevery field condition in match is true for at least one item of the arrayObject Array
All matchall_matchevery field condition in match is true for all items of the arrayObject Array

Match a resource referenced by a foreign key

A resource attribute can store the key of another resource, like a foreign key in a database. For example, the repo resource has a string attribute organization that holds the key of an organization resource.

To test the attributes of the referenced resource, add fk_resource_type to the object_match operand and set it to the referenced resource type. Permit reads the attributes stored for that resource instance and applies the match conditions to them. The following condition is true when the repository's organization is located in the US:

{
"allOf": [
{
"resource.organization": {
"object_match": {
"match": {
"country": {"equals": "US"}
},
"fk_resource_type": "organization"
}
}
}
]
}

The any_match and all_match operators accept fk_resource_type for attributes that hold an array of keys. For example, the repo resource has an attribute issues (array of strings) that holds the keys of its issue resource instances. The following condition is true when every issue of the repository is closed:

{
"allOf": [
{
"resource.issues": {
"all_match": {
"match": {
"status": {"equals": "closed"}
},
"fk_resource_type": "issue"
}
}
}
]
}

The following condition uses any_match and is true when at least one issue of the repository is not closed:

{
"allOf": [
{
"resource.issues": {
"any_match": {
"match": {
"status": {"not-equals": "closed"}
},
"fk_resource_type": "issue"
}
}
}
]
}
Stored attributes only

Other ABAC operators can use attributes passed in the permit.check() call or attributes stored in Permit. A foreign key condition reads the referenced resource's attributes from the resource instance stored in Permit, so the check call doesn't need to pass them.

Next steps