An access review campaign asks named reviewers to confirm or remove every role binding in a part of the organisation. The result is evidence of periodic access certification, which auditors ask for under frameworks such as SOC 2 and ISO 27001. Govern produces the evidence toward those controls; certification remains with your auditor.
Access reviews work through the API. They have no console page yet.
How a campaign works
- A campaign covers the bindings of one role, on one node and, by default, its subtree. When it opens, it snapshots those bindings as items.
- Reviewers decide each item:
keeporrevoke, with a justification. A revoke decision revokes the binding in the same transaction. - A reviewer cannot decide an item about their own access.
- When the campaign closes with
auto_revokeon, undecided items are revoked, except the binding of a node's last administrator. - The evidence export lists every item, decision, reviewer, time and the audit record ids.
Reviewers are the principals you name, or by default the holders of iam.reviews:decide on the item's node.
Schedule campaigns
curl -sS -X POST "$KEYSTONE_URL/api/v1/access/review-schedules" \
-H "Authorization: Bearer $ADMIN_TOKEN" -H 'Content-Type: application/json' \
-d '{"name": "Quarterly production admins", "node_id": "'$PROD_NODE'", "role_id": "'$ROLE_ID'",
"include_subtree": true, "duration_days": 14, "auto_revoke": true,
"frequency_days": 90, "enabled": true, "first_run_at": "2026-11-01T09:00:00Z"}'
| Field | Meaning |
|---|---|
name | Campaign name |
node_id, role_id | The bindings in scope |
include_subtree | Default true |
duration_days | 1 to 90 |
reviewers | Principals who decide; empty means holders of iam.reviews:decide on the node |
auto_revoke | Revoke undecided items when the campaign closes |
frequency_days, enabled, first_run_at | Schedules only |
Schedules and campaign expiry are processed every 5 minutes. To open one campaign now, POST /api/v1/access/reviews with the campaign fields.
Decide items
curl -sS "$KEYSTONE_URL/api/v1/access/reviews/$REVIEW_ID/items" \
-H "Authorization: Bearer $REVIEWER_TOKEN"
curl -sS -X POST "$KEYSTONE_URL/api/v1/access/reviews/$REVIEW_ID/items/$ITEM_ID/decision" \
-H "Authorization: Bearer $REVIEWER_TOKEN" -H 'Content-Type: application/json' \
-d '{"decision": "revoke", "justification": "Moved to another team in September"}'
A revoke needs a justification.
Export evidence
GET /api/v1/access/reviews/{id}/evidence?format=json (the default) or format=csv. Exports need iam.reviews:export.
Routes
| Route | Permission |
|---|---|
GET, POST /api/v1/access/review-schedules; GET, PUT, DELETE /api/v1/access/review-schedules/{id} | iam.reviews:read, iam.reviews:manage |
GET /api/v1/access/reviews (query state) | iam.reviews:read |
POST /api/v1/access/reviews | iam.reviews:manage |
GET /api/v1/access/reviews/{id} | iam.reviews:read |
POST /api/v1/access/reviews/{id}/close | iam.reviews:manage |
GET /api/v1/access/reviews/{id}/items (query outcome) | iam.reviews:read |
POST /api/v1/access/reviews/{id}/items/{item_id}/decision | A named reviewer, or iam.reviews:decide on the item's node; never one's own access |
GET /api/v1/access/reviews/{id}/evidence | iam.reviews:export |
The Security and compliance account role holds iam.reviews:manage and iam.reviews:decide. The auditor role can read and export reviews but not decide.
Scope
Campaigns review role bindings on directory nodes. The design extends reviews to resource shares, API keys and service accounts; that extension is not described in the built routes, so do not rely on it.
Related
- Unused access is also removed by the inactivity setting (
inactivity_disable_days) on Access guardrails. - SCIM deactivation revokes every binding of a leaver at once; see Directory sync with SCIM.
- Review decisions are written to the audit log; see Audit log.