π§Query Language Basics
A beginner's guide to querying P0's Access Inventory. Learn the core search terms (identity, credential, entitlement, risk), the colon, arrow, and reverse-arrow operators, the type argument, and how t
This guide introduces the query language you use to search the Access Inventory. It assumes no prior experience. By the end, you can read and write queries like identity:->identity:->entitlement:->risk: and understand exactly what they return.
If you want the complete reference β every operator, search term, and attribute β see the Search Reference. For an overview of the search interface itself, see Query Search.
Your inventory is a graph
P0 models your cloud IAM configuration as a graph: a set of items (called nodes) connected by relationships (called edges).
Each node is one piece of your access setup, such as a user, an access key, or a permission grant. Each edge records how two nodes relate, such as "this identity holds this entitlement."
You query the inventory by describing a pattern of nodes and the connections between them. P0 finds every part of your graph that matches the pattern and shows you the results.
You don't need to know graph theory to write queries. Think of each query as a sentence that describes the access you're looking for, reading from left to right.
The core search terms
The most common nodes you search for are the four that follow. Type one of these words to limit your search to that kind of node.
identity
A user, group, machine identity, or role that can authenticate.
An employee, a service account, an AWS IAM role.
credential
A single way to authenticate, such as an access key or a federated SSO login.
An AWS access key, a short-lived token.
entitlement
A grant that gives an identity privileges over one or more resources.
An AWS policy attachment, a GCP role binding.
risk
A security risk that a privilege carries.
A privilege that allows data exfiltration.
These four are the terms you use most often, but they aren't the only ones. The inventory also models resource, privilege, usage, and more. For the complete list, see Search types.
The colon operator: :
:The colon turns a word into a node-type filter. On its own, a term followed by a colon matches every node of that type:
This query matches every identity in your inventory.
To narrow the search, add a keyword after the colon. P0 then matches nodes of that type whose name contains the keyword:
This query matches identities whose name contains alice.
Read the colon as "that is a." So identity:alice reads as "a node that is an identity, named alice."
A colon with nothing after it (risk:) is a presence search: it finds every node of that type. Use it to answer questions like "which entitlements carry any risk at all?" with entitlement:->risk:.
The type argument
Many node types come in several varieties. An identity might be a user, a group, or a machine role. A credential might be a static key or a short-lived token. To filter by variety, use the type argument.
The type argument is an attribute of a node, so you write it as a second colon-separated value:
This reads as "an identity whose type is user." The pattern is always:
Here are some common examples:
identity:type:user
Human user identities.
identity:type:aws-iam-role
AWS IAM roles.
identity:type:service-account
Machine identities (service accounts).
credential:type:key
Static secret credentials, such as access keys.
credential:type:short-lived
Ephemeral credentials, such as temporary tokens.
usage:type:unused
Privileges that have gone unused.
type is one of several attributes you can filter on. Each search term supports its own attributes, such as identity:status or credential:last90. See Search attributes for the full set and their allowed values.
The inverted operator: !
!Put a ! immediately before a keyword to match nodes whose value does not contain it. This is the inverted (or "NOT") operator.
This reads as "an identity whose status is not disabled." It returns every identity that is enabled or whose status is unknown.
The ! goes after the type and attribute, directly in front of the keyword it inverts. The pattern is:
On its own, an inverted keyword does little, because each identity and grant connects to many values and some won't match anyway. Inverted matches work best combined with a type or attribute, as in credential:type:!key (credentials that aren't static keys).
The inverted operator (!) flips a single keyword. A related operator, the exclusion operator (^), removes whole results that match a term. For both, see Inverted matches and Exclusion matches in the reference.
Matching with a regular expression: /.../
/.../A plain keyword matches any value that contains it. When you need more control β a value that starts with something, or matches one of several patterns β wrap a regular expression in forward slashes.
This reads as "an identity whose name matches the pattern ^svc-," which finds identities whose name starts with svc-. The ^ anchors the match to the beginning of the value.
You can use the full standard regular expression syntax, including anchors (^, $), character classes, and alternation:
This matches identities whose name contains either prod or staging.
Regex works wherever a keyword does, including after an attribute (identity:status:/^en/) and combined with the inverted operator (identity:type:!/role/).
Regex matches are case sensitive, unlike plain keyword matches. To match either case, build it into the pattern β for example, /[Pp]rod/ rather than /prod/i.
For escaping rules, limitations, and the equivalent Cypher, see Regex matches in the reference.
The path operators: -> and <-
-> and <-A single term finds nodes in isolation. To describe how nodes connect, join terms with an arrow. We call this a path.
The arrow points along the direction of the graph's edges:
->
Child path
Follow the connection forward, from the left term toward the right term.
<-
Parent path
Follow the connection backward, from the left term toward its parent.
For example, to find identities that hold an entitlement, follow the connection forward:
This reads as "an identity that connects forward to an entitlement." The same relationship viewed from the other side uses the reverse arrow:
Both describe the same connection. You pick the direction that matches how you want to read the query and which nodes you want to start from.
You can chain as many terms as you need, adding one arrow between each pair:
This reads as "an identity that holds an entitlement that carries a risk."
Switch to the graph view to see the matching paths. Each row traces an identity (left) through the entitlement it holds to the risk that entitlement carries (right), with the nodes that match your query highlighted in yellow:

identity:->entitlement:->risk:A single path must use one direction throughout. Mixed paths like a:->b:<-c: are not supported. Use all -> or all <- within one path.
Arrows follow the real connections in the graph, so not every combination is valid. For example, identity:->entitlement:->risk: works, but resource:->risk: doesn't, because resources don't connect directly to risks. The IAM graph diagram shows which connections exist.
Reading a worked example
Now you can read the example query from the top of this guide:
Walk through it one hop at a time, left to right:
identity:β Start from an identity.->identity:β Follow the connection forward to another identity that the first one is linked to. For example, a user and a group or role that user can act through.->entitlement:β Follow the connection forward to an entitlement that this second ("right") identity holds.->risk:β Follow the connection forward to a risk that the entitlement carries.
Put together, the query finds identities that are linked to other identities, the entitlements those linked identities hold, and the risks those entitlements carry. It's a way to surface indirect risk: access that one identity gains through another, and the danger that access brings.
The graph view makes each hop visible. Here, Okta users reach groups, which hold AWS policy assignments, whose privileges carry critical exfiltration risks β each matching node highlighted in yellow:

identity:->identity:->entitlement:->risk:More example queries
identity:
Every identity in your inventory.
identity:type:service-account
Every service account.
credential:type:key
Every static access key.
identity:->entitlement:
Identities and the entitlements they hold.
entitlement:->risk:
Entitlements that carry any risk.
entitlement:->risk:CRITICAL
Entitlements that carry a critical risk.
identity:type:service-account->entitlement:->risk:
Service accounts whose entitlements carry a risk.
Build queries visually with the Query builder
If you'd rather not type the syntax by hand, use the Query builder. Click the + button next to the where box, above the table or graph, to open it.
The Query builder is a form that assembles one search term and inserts it into the where box for you. In it, you:
Choose a connection β are (match the displayed node itself) or can reach (match a node it connects to).
Select a search type, such as identities or entitlements, and an attribute to filter on.
Pick containing (substring) or equal to (exact), then enter a keyword.
Optionally turn on Invert match? to apply the
!operator, Remove match? to apply the exclusion operator (^), or Only first node? to match just the first node in a chain.
A live preview shows the term as you build it. Click Add term to drop it into the where box, where you can edit it or chain it with other terms.
The Query builder produces ordinary query text β the same syntax this guide describes. It's a quick way to discover operators and exact attribute values; once you know the syntax, typing is often faster.
Next steps
Try a query: open the Inventory page, choose what to display in the show control, and type a query in the where box. See Access Inventory for a tour of the search interface.
Look up the rest of the operators (exact matches, inverted matches, exclusions, and more) with every search term and attribute in the Search Reference.
Last updated