River
Y CombinatorBacked by Y Combinator
FREE TEMPLATE

User Access Review Template

Four documents and five sheets, including a register where every keep decision carries the date the entitlement was last used.

Free download  ·  No account needed

Access Register, one row

One principal, one system, one entitlement, and the fact behind the decision

Class assigned before a reviewer sees it  ·  Routed to the named owner of the system  ·  Frozen at sign-off

Last Sign-In

Belongs to the account. Says the person came to work and nothing about the entitlement in front of it.

Last Entitlement Use

Belongs to the grant. Read out of the access log, filled in before the row is sent, and the only column a keep can rest on.

Class Federated with a current HR record, federated with none, local human, machine, or external. Five values, one per row, and an unclassified row blocks the review rather than joining it.

Live Credentials Counted separately from the account state, because an access key does not stop working when somebody disables the login beside it.

Decision Keep, reduce, revoke or escalate. Nothing else, and each one requires a different fact in the evidence column.

Evidence

The date, the exercised action set, or the missing HR record. A keep with an empty evidence column goes back to the reviewer with the last-use date attached.

Remediation

A ticket, an owner and a due date for every revoke and every reduce. An exception is allowed, with a named approver and an expiry, because an exception that renews itself is a permanent grant under another name.

Every access review template on the first page of a search asks for the same column, and it is the wrong one. Last login belongs to the account. It says somebody came to work, not that they touched the production role they hold. AWS keeps the two apart in its own credential report, which carries password_last_used for the login and access_key_1_last_used_date for the key as separate facts. Every row in this pack carries both, and a keep can only rest on the second.

Halwill runs logistics software. Nine systems in scope, 214 people on the roster, two acquisitions behind it. Exported from each system rather than from the directory, 389 principals could reach production and 158 of them had no directory account at all. Crossed against HR, 30 human principals could reach production with no current employment record. A review run the usual way, from the directory export, would have surfaced twelve of those thirty and reported the rest clean.

Then the departures. Forty-seven people left in twelve months, all 47 accounts were disabled, and nine of them still held a working credential: four cloud keys, three tokens, an SSH key, a database password. Two had been used after the leaving date, one of them 118 days later from an address nobody could account for. Disabling an account and revoking access are different operations, which is why the offboarding access matrix and this check are keyed on different objects.

Three rosters, forty-seven clean departures, and nine credentials that still worked

The reconciliation, the departure check, the usage comparison and last quarter's decisions.

Principal Reconciliation  ·  Halwill logistics  ·  nine systems, review of 12 October 2026

PopulationCountShareWhat it means for the review
Principals that can reach production389100%Taken from each system, not from the directory
Resolve to an enabled directory account23159%The population a directory export would have covered
No directory account at all15841%Never seen by any previous review
machine principals9725%Need an owner and a rotation date, not a manager’s tick
local human accounts4411%Created before single sign-on, or outside it
external principals174%A partner role, two webhooks, a support vendor seat

Against an HR roster of 214 current workers, 30 human principals could reach production with no current HR record. Twelve of them appeared in the directory export. The other 18 were local accounts in systems that never federated.

Departed User Check  ·  47 leavers, all 47 accounts disabled, every quarterly review passed

Credential still workingCountMedian gapWhy the account check missed it
Cloud access keys marked active4214 daysA key is a separate object with its own state
Personal access tokens3265 daysIssued by the person, not by the directory
SSH key in a bastion196 daysSits in a file no identity system reads
Database role with a password1214 daysNever federated, so nothing propagates to it
Used after the leaving date219 and 118 daysAn incident, handed over rather than logged as a finding

The longest gap was 631 days. Deprovisioning had a perfect record against accounts and a nine-credential hole underneath it.

Over-permission Flags  ·  production cloud, 90-day window

SignalValueReading
Human principals signed in within 30 days112 of 11895% look active
Principal-action pairs granted2,847What the policies permit
Exercised at least once61179% never used
Holding an administrator policy24Five used an admin-only action
Held admin and never used it19A revocation list you can send today

Review Evidence  ·  what the previous quarter decided about the same access

OutcomeRowsAgainst the usage data
Keep1,171604 of them unexercised in 90 days
Revoke31The same rows support 604
Escalate2Both closed without a decision
Median reviewer46 rowsSix minutes, so 7.8 seconds a row

Nobody was cutting corners. A row reading only Priya Raman, warehouse-ms, dispatch_admin cannot be answered. The same row carrying last used 14 March, 187 days ago, is answered correctly in the same seven seconds.

What is in the pack

01

Access Register

One row per principal per system, carrying last sign-in and last entitlement use as two separate columns.

02

Principal Reconciliation

The three-way join of HR roster, directory and per-system exports, with every principal assigned one of five classes.

03

Departed User Check

One row per live credential per leaver, with the gap in days and whether use postdates the leaving date.

04

Over-permission Flags

Granted actions against exercised actions per principal, with the unused share and every unexercised administrator grant.

05

Review Evidence

The frozen record an auditor tests: decision, usage fact, reviewer, remediation ticket and any exception expiry.

06

Review Procedure

The document fieldwork reads, written from the register in front of you rather than from a framework's wording.

07

Revocation Note

Five things and no apology: what went, why, what still works, the route back, and who decided.

08

Departure Credential Check

A weekly pass over recent leavers reporting credential state, which hands any use after a leaving date to security.

How it works

  1. 1

    Open it in River, or download it

    Edit with AI opens the pack as a private Space with the agent ready to run the joins. Download hands you four Word documents and five CSV sheets, no account required.

  2. 2

    Send three rosters, not one

    The HR roster with leaving dates, the directory export including disabled accounts, and a principal list taken from each system itself. The third one is where the findings live.

  3. 3

    Get a class on every principal

    River runs both joins and marks each principal federated with a record, federated without one, local human, machine or external. Anything unclassified blocks the review.

  4. 4

    Fill the last-use column first

    Access logs go in before a single row is routed, because a reviewer with no usage fact has one cheap answer available and will give it 1,171 times.

Frequently asked questions

Is this template free?

Yes, and the download needs no account, card or email. Edit with AI is the optional half and the one that does the joins: it reconciles your three rosters, classifies every principal and fills the last-use column before anything is routed. The rest of the template library works the same way.

What format are the downloaded files?

Four documents as .docx and five sheets as .csv, in one zip. Word, Pages, Google Docs, Excel, Numbers and Sheets open them with nothing to convert. The sheets arrive carrying the worked logistics example, so you can see a filled register before you replace it with your own.

Our identity provider already exports everyone. Why three rosters?

Because that export is the accounts single sign-on happens to know about. At Halwill it covered 231 of 389 principals, and 18 of the 30 human principals with no HR record sat in systems that never federated. A directory-scoped review cannot see a principal the directory never created.

We disable accounts the day somebody leaves. Is that not enough?

It was not at Halwill, where all 47 departures were cleanly deprovisioned and nine still held something that worked. A long-lived credential is a separate object with its own lifecycle, so the check enumerates keys, tokens, SSH entries, OAuth grants and database roles rather than accounts. Whether you promised 24 hours in writing is a question for the policy set.

How does this reduce permissions rather than just certify them?

By comparing granted actions with exercised ones, which turns a judgement call into a diff. AWS will generate a policy from access activity in CloudTrail, so the replacement grant is written from the log. Where the finding is a package rather than a person, that is a supply chain review.

Will this satisfy an auditor?

It produces what the control asks for. NIST SP 800-53 words AC-6(7) as reviewing privileges to validate the need for such privileges, and taking corrective action where the need cannot be revalidated. Validation needs a fact, which is what the evidence column holds. The surrounding narratives belong in a SOC 2 evidence pack.

Our permission exports cannot leave our network. Can we still use this?

Then run it inside a private AI workspace, where rosters, principal lists and access logs stay in your own tenancy. The joins and the arithmetic behave exactly as they do here, and so do the questionnaire answers that cite the review afterwards.

Put the last-use date in the row

Edit with AI