Skip to main content

Predicate Language

Teleport's predicate language is used to define conditions for filtering in dynamic configuration resources. It is also used as a query language to filter and search through a list of select resources.

The predicate language uses a slightly different syntax depending on whether it is used in:

Scoping allow/deny rules in role resources

Some fields in Teleport's role resources use the predicate language to define the scope of a role's permissions:

When used in role resources, the predicate language supports the following operators:

OperatorMeaningExample
&&and (all conditions must match)contains(field1, field2) && equals(field2, "val")
||or (any one condition should match)contains(field1, field2) || contains(field1, "val2")
!not (used with functions, more about this below)!equals(field1, field2)

The language also supports the following functions:

FunctionsDescription
contains(<field>, <field2>)checks if the value from <field2> is included in the list of strings from <field>
contains(<field>, "<value>")checks if <value> is included in the list of strings from <field>
equals(<field>, <field2>)checks if the value from <field2> is equal to the value from <field>
equals(<field>, "<value>")checks if <value> is equal to the value from <field>

Resource filtering

Both the tsh and tctl CLI tools allow you to filter nodes, applications, databases, and Kubernetes resources using the --query flag. The --query flag allows you to perform more sophisticated searches using the predicate language.

For common resource fields, we defined shortened field names that can easily be accessed by:

Short FieldActual Field EquivalentExample
labels["<key>"]resource.metadata.labels + resource.spec.dynamic_labelslabels["env"] == "staging"
nameresource.spec.hostname (only applies to server resource) or resource.metadata.namename == "jenkins"

The language supports the following operators:

OperatorMeaningExample
==equal tolabels["env"] == "prod" or labels[`env`] == "prod"
!=not equal tolabels["env"] != "prod"
&&and (all conditions must match)labels["env"] == "prod" && labels["os"] == "mac"
||or (any one condition should match)labels["env"] == "dev" || labels["env"] == "qa"
!not (used with functions)!equals(labels["env"], "prod")

The language also supports the following functions:

Functions (with examples)Description
equals(labels["env"], "prod")resources with label key env equal to label value prod
exists(labels["env"])resources with a label key env; label value unchecked
!exists(labels["env"])resources without a label key env; label value unchecked
search("foo", "bar", "some phrase")fuzzy match against common resource fields
hasPrefix(name, "foo")resources with a name that starts with the prefix foo
split(labels["foo"], ",")converts a delimited string into a list
contains(split(labels["foo"], ","), "bar")determines if a value exists in a list

See some examples of the different ways you can filter resources.

Label expressions

Label expressions can be used in Teleport roles to define access to resources with custom logic. Check out the Access Controls reference page for an overview of label expressions and where they can be used.

Label expressions support a predicate language with the following fields available:

FieldTypeDescription
labelsmap[string]stringCombined static and dynamic labels of the resource (server, application, etc.) being accessed.
user.spec.traitsmap[string][]stringAll traits of the user accessing the resource (referred to as external or internal in role template expressions).

The language supports the following operators:

OperatorMeaningExample
==equal tolabels["env"] == "staging"
!=not equal tolabels["env"] != "production"
||or (any one condition should match)labels["env"] == "staging" || labels["env"] == "test"
&&and (all conditions must match)labels["env"] == "staging" && labels["team"] == "dev"
!not (logical negation)!regexp.match(user.spec.traits["teams"], "contractor")

The language also supports the following functions:

SyntaxReturn typeDescriptionExample
contains(list, item)BooleanReturns true if list contains an exact match for itemcontains(user.spec.traits[teams], labels["team"])
regexp.match(list, re)BooleanReturns true if list contains a match for reregexp.match(labels["team"], "dev-team-\d+$")
regexp.replace(list, re, replacement)[]stringReplaces all matches of re with replacement for all items in listcontains(regexp.replace(user.spec.traits["allowed-env"], "^env-(.*)$", "$1"), labels["env"])
email.local(list)[]stringReturns the local part of each email in list, or an error if any email fails to parsecontains(email.local(user.spec.traits["email"]), labels["owner"])
strings.upper(list)[]stringConverts all items of the list to uppercasecontains(strings.upper(user.spec.traits["username"]), labels["owner"])
strings.lower(list)[]stringConverts all items of the list to lowercasecontains(strings.lower(user.spec.traits["username"]), labels["owner"])
labels_matching(re)[]stringReturns the aggregate of all label values with keys matching re, which can be a glob or a regular expressioncontains(labels_matching("^project-(team|label)$"), "security")
contains_any(list, items)BooleanReturns true if list contains an exact match for any element of itemscontains_any(user.spec.traits["projects"], labels_matching("project-*"))
contains_all(list, items)BooleanReturns true if list contains an exact match for all elements of itemscontains_all(user.spec.traits["projects"], labels_matching("project-*"))

Above, any argument named list can accept a list of values (like the list of values for a specific user trait) or a single value (like the value of a resource label or a string literal).

Access Monitoring Rules

Access Monitoring Rules use the predicate language to define conditions for applying notification routing rules or automatic review rules to Access Requests.

Access Monitoring Rules support a predicate language with the following fields available:

FieldDescription
access_request.spec.rolesThe set of roles requested.
access_request.spec.suggested_reviewersThe set of reviewers specified in the request.
access_request.spec.system_annotationsA map of system annotations on the request.
access_request.spec.userThe requesting user.
access_request.spec.request_reasonThe request reason.
access_request.spec.creation_timeThe creation time of the request.
access_request.spec.expiryThe expiry time of the request.
access_request.spec.resource_labels_intersectionA map containing the intersection of all requested resource labels.
access_request.spec.resource_labels_unionA map containing the union of all requested resource labels.
user.traitsA map of traits of the requesting user.

The language supports the following operators:

OperatorMeaningExample
==equal toaccess_request.spec.user == "example_user"
!=not equal toaccess_request.spec.user != "example_user"
&&and (all conditions must match)regexp.match(user.traits["level"], "^L1$") && regexp.match(user.traits["team"], "^Cloud$")
||or (any one condition should match)regexp.match(user.traits["level"], "^L1$") || regexp.match(user.traits["team"], "^Cloud$")
!not (used with functions)!regexp.match(set(access_request.spec.request_reason), "*important*")

The language also supports the following functions:

FunctionsDescriptionExample
contains_any(set, items)Returns true if set contains an exact match for any element of itemscontains_any(user.traits["team"], set("dev", "stage"))
contains_all(set, items)Returns true if set contains an exact match for all elements of itemscontains_all(set("dev"), access_request.spec.roles)
set.contains(item)Returns true if set contains an exact match for itemaccess_request.spec.roles.contains("example_role")
regexp.match(set, re)Returns true if set contains a match for reregexp.match(set(access_request.spec.request_reason), "*on-call*")
is_empty(set)Returns true if set contains no elementsis_empty(access_request.spec.roles)