Skip to main content

Identity Security is available only with Teleport Enterprise. Start your free trial.

Start your free trial

Review Identity Access from the CLI

Report an Issue

tctl access-review answers who can reach which resources, what grants that access, and — optionally — whether that access has actually been used. Use it to review and certify role and access-list grants, answer "who can reach this database", or find dormant standing privileges.

You scope every review with a --query: a SQL SELECT against the Access Graph access_path model. The query defines which identities and resources the review covers; the results describe the access each identity has to each resource and how that access is granted. It reports access paths only — it does not enumerate other relationships, such as who can review an Access List rather than gain access through it.

Prerequisites

See Identity Security from the Command Line for the shared prerequisites and how the CLI authenticates to Access Graph. This command requires Access Graph v1.30.1 or later, and tctl access-review requires a --query.

Identity Activity Center is optional. Without it, the review still reports access paths and their grants, but the activity columns are omitted and the output notes why.

Review access

Scope the review with a --query. The query is a SQL SELECT against access_path; the WHERE clause is where you narrow it. For example, to review everything one user can reach:

tctl access-review --query "SELECT * FROM access_path WHERE identity = 'alice'"

identity matches a user or bot by its stored name or alias — for SSO users this is usually their username or email. resource matches a resource by name, and identity_group matches what grants access — a role, Access List, or Access Request (shown as Granted By in the output). Matches with = and IN are exact and case-sensitive; use ILIKE for case-insensitive or prefix matching when you are unsure of the exact name.

Common review patterns

GoalQuery
Everything one user can reachSELECT * FROM access_path WHERE identity = 'alice'
Who can reach a resourceSELECT * FROM access_path WHERE resource ILIKE 'prod-db%'
What a role grants, and to whomSELECT * FROM access_path WHERE identity_group IN ('prod-db-admin')
What an Access List grants, and to whomSELECT * FROM access_path WHERE identity_group IN ('Prod Admins')
Why a resource is reachable through a roleSELECT * FROM access_path WHERE resource = 'prod-db' AND identity_group IN ('prod-db-admin')

Roles and Access Lists are both identity_group nodes. The text output does not mark a grantor's kind; to tell a role from an access_list, use --format=json (or yaml) and read granted_by[].node.sub_kind. When you scope a review through a grantor like this, mind what the results do and do not cover — see Understand query scope.

By default the output summarizes each identity's resources, resolved access level, the primary grant (the Granted By column), and grant counts. Add --detailed to break each resource down by each grant and the level it contributes:

tctl access-review --query "<query>" --detailed

Granted By is the identity group — a role, Access List, or Access Request — that confers the access; it is what you filter on with identity_group in a query.

FlagDescription
--queryRequired. SQL SELECT against access_path scoping the identities to review.
--fromShow activity at or after this time. RFC3339, YYYY-MM-DD, or durations like 24h, 7d. Defaults to 24 hours ago.
--toUpper bound for activity. Defaults to now.
--no-activitySkip the activity lookup and hide the activity columns for a faster review. Takes priority over --from/--to.
--detailedShow each grant with its individual access level instead of summary counts.
--limitMaximum identities to return. Default: 50.
--formattext, json, yaml.

In text output, a * marks self-expiring access or a temporary grant.

Understand query scope

Results are derived only from the paths your query produces. When you scope a review through a given node — a role, an Access List, or any other identity group — the results show only the paths that flow through that node, not necessarily every path the matched identities have to the matched resources.

For example, this query answers "what does membership in Prod Admins grant, and to whom":

tctl access-review --query "SELECT * FROM access_path WHERE identity_group IN ('Prod Admins')"

It does not tell you the full access of each of those members. A member might also reach the same resource through another role, another Access List, or an approved Access Request, and those paths are invisible to a query scoped to Prod Admins.

So when a scoped query shows an identity reaching a resource, it is usually worth confirming that identity's complete access to the resource with a follow-up query scoped by identity and resource directly:

tctl access-review --query "SELECT * FROM access_path WHERE identity = 'alice' AND resource = 'prod-server'"

This returns every path from alice to prod-server, with each grant that backs it — the authoritative view to check before you add or remove access.

Show access activity

If your cluster has Identity Activity Center enabled, tctl access-review shows the activity columns by default over the last 24 hours — how often each access was used and when it was last exercised. Widen the window with --from (and optionally --to):

tctl access-review --query "<query>" --from=30d

To skip the activity lookup entirely — for a faster, structural-only review of who can reach what — pass --no-activity.

Activity counts come from Teleport session-start events, so they cover only resources reached through a Teleport session (SSH, database, Kubernetes, app, desktop). Resources used outside a session — such as AWS, Okta, or GitLab resources — leave the activity columns blank even when the access is used.

Use tctl access-review with an AI agent

tip

To let an AI agent drive this command, install the matching Agent Skill:

npx skills add https://github.com/gravitational/teleport/tree/master/skills/teleport-access-review

Next steps

Troubleshooting

access-review is unavailable on this cluster

This usually means Identity Security is not enabled, or the access-review endpoint is not yet available on this cluster. Confirm Identity Security is enabled and that your cluster is v18.11.0 or later.

column "..." not found

The WHERE clause references a column access_path does not have. The queryable columns include identity, resource, identity_group, source, and id — for example, filter users with identity, not identity_name.

No access found

An empty result is more often a name mismatch than a true "no access". = and IN match the stored name exactly and case-sensitively, so re-run with ILIKE (for example, resource ILIKE '%db%'), read the names from the output, then scope precisely.