match_on and match_with Operator Reference
Used to filter resources conditionally in match_on and match_with arrays. All objects in the array follow AND logic.
| Operator | Type | Description |
|---|---|---|
property |
String | (Required) The property to evaluate. Supports dot notation traversal (domain.owner). |
relation |
String | Optional. When set, property refers to a property of outgoing relations with this label instead of the node itself. |
value |
Any | Exact equality check. Supports Tera. |
not |
Any | Inequality check. Supports Tera. |
contains |
String | Substring match for strings, or element match for arrays. Supports Tera. |
excludes |
String | Ensures substring or element is missing. Supports Tera. |
exists |
Boolean | Checks if property is present and not null. |
empty |
Boolean | Checks if property is missing, null, "", or []. |
greater |
Number | Strictly greater than (>). |
lower |
Number | Strictly less than (<). |
regexp |
String | Regular expression match. Supports Tera templating. |
expression |
String | Evaluates a Tera template directly; matches if result is exactly "true". |
lib |
Object | Calls a library function (e.g. Rhai in lib/); matches if it returns true. Format: { path = "file.rhai", function = "fn_name" }. |
or |
Array | Groups conditions with logical OR. Accepts a flat list of conditions or condition groups (legacy DNF form), and nests freely with and blocks. |
and |
Array | Groups conditions with logical AND. Accepts a flat list of conditions and nests freely with or blocks. |
in |
Array, String | Matches if the property’s value is contained in this list or comma-separated string. |
match_on is valid inside rule blocks such as [[create_resource]], [[link_resources]], [[output]], [[control]], or [[action]]. At file header scope it is ignored.
Grouping with or and and
Entries in a match_on / match_with array are combined with AND. For other logic, group conditions inside a single entry:
# top level: (A) AND (B OR C)
match_on = [
{ property = "environment", value = "prod" },
{ or = [
{ property = "tier", value = "gold" },
{ property = "tier", value = "silver" }
] }
]
# explicit and-group, nestable inside or
match_on = [
{ or = [
{ and = [ { property = "env", value = "prod" }, { property = "tier", value = "gold" } ] },
{ and = [ { property = "env", value = "dev" } ] }
] }
]
Rules:
and/orblocks nest freely; there is no limit on depth.- One grouping key per object: an object cannot combine
orandand. Split them into separate array entries —match_on = [{ or = ... }, { and = ... }]. - An empty
andgroup ({ and = [] }) evaluates totrue; an emptyorgroup ({ or = [] }) evaluates tofalse. - Bare arrays in entry position (
match_on = [ [ {...}, {...} ] ]) are implicit AND-groups; the legacy DNF form{ or = [ [ {...} ], [ {...} ] ] }is still accepted.
Unknown condition keys are hard errors. If a condition object contains a key that is not in the operator table above (for example a leftover op = "neq"), the build fails with a deserialization error instead of silently ignoring the condition. In Jsonnet models, rescile.neq(...) / rescile.notEq(...) emit the supported not operator.
Cross-Resource Matching in Compliance
In compliance controls ([[control.target]]), match_on evaluates against a traversable vertex representation of origin_resource. This allows dot-notation traversal across relationships directly in property paths:
[[control.target]]
origin_resource_types = "database"
match_on = [
# Check properties on the server running this database
{ property = "server.environment", value = "production" },
{ property = "backup_policy.status", value = "active" }
]
Direction caveat: relation traversal is undirected.
origin_resource.<RELATION>and dot-notation paths collect neighbors across both edge directions, and the list is sorted by neighbor name —[0]does not prefer the outgoing side. When a relation label exists in both directions (e.g. a certificate chain where a subordinate isSIGNED_BYa root and other subordinates are signed by it), select the intended neighbor by direction:{ expression = "{% set issuer = [s for s in origin_resource.SIGNED_BY if s._relation.direction == 'outbound'] %}{{ 'true' if issuer else 'false' }}" }The
outbound/inboundTera filters do the same selection with less ceremony (see the Tera reference).
Library Matching (lib)
To evaluate complex cross-resource conditions or calculations (e.g. time-slice audits or CIDR calculations) without polluting data models, use the lib match operator or Jsonnet rescile.libMatch():
[[control.target]]
origin_resource_types = "fee_schedule"
match_on = [
{ lib = { path = "timeline_audit.rhai", function = "has_schedule_overlap" } }
]
In Jsonnet (compliance/*.jsonnet):
local rescile = import 'rescile/v1/rescile.libsonnet';
rescile.target(
originResourceTypes='fee_schedule',
match=[
rescile.libMatch('timeline_audit.rhai', 'has_schedule_overlap')
],
// ...
)
Notes on expression
- The template must render exactly the string
"true"to match — a common pattern is{% if <condition> %}true{% endif %}. - Inside
[[link_resources]]match_withexpressions, bothorigin_resourceandtarget_resourceare available; in other contexts typically onlyorigin_resource. - Tera’s
inoperator is not supported in these expressions and fails with a render error. Use tests instead:is containing(...)for substring/multi-value cell matching andis ending_with(...)for suffix matching.
# Multi-value cell: link when the algorithm name appears in the endpoint's `algorithms` list
{ expression = "{% if origin_resource.algorithms is containing(target_resource.name) %}true{% endif %}" }
# Suffix match: link a certificate to its parent domain
{ expression = "{% if origin_resource.name is ending_with(target_resource.name) %}true{% endif %}" }
Relation-Property Matching
Set relation to evaluate a condition against properties stored on the relationship instead of the node. The condition looks at every outgoing relation with the given label from the node being evaluated and succeeds if any matching relation satisfies the condition.
# In a compliance rule: flag computes whose DEPLOYED_AS relations lacks encryption
[[control]]
name = "deployment-must-be-encrypted"
[[control.target]]
origin_resource_types = ["compute"]
match_on = [
{ relation = "DEPLOYED_AS", property = "encrypted", value = false }
]
If property is omitted or empty and relation is set, the condition checks only for the existence of a relation with that label. This behaves like the node-level exists operator, but scoped to a specific relationship.