Access Review
The periodic check that the people and services with production access are the ones who should have it — a backstop for expiry, not a substitute for it.
The question, the obvious approach, and why it breaks
Every lesson starts where the work starts: an operational problem, a first attempt that is entirely reasonable, and the way production disagrees with it.
How do you find out who currently has production access, and how do you make that answer smaller?
Access is granted continuously by people responding to immediate needs and revoked by nobody. Without a periodic check, the set of identities that can change production grows monotonically and nobody can describe it.
People lose access when they leave. Offboarding covers it, and everything else is fine because we trust our engineers.
Offboarding catches leavers and nothing else. Internal moves are far more common, and someone who moved from payments to frontend two years ago still holds payments production access.
- Offboarding catches leavers and nothing else. Internal moves are far more common, and someone who moved from payments to frontend two years ago still holds payments production access.
- Contractors, vendors and integration accounts are frequently outside the offboarding process entirely, and they are often the ones with the broadest grants.
- Service accounts are almost never reviewed. They have standing credentials, no MFA, no leaver event and typically the widest permissions in the environment (Workload Identity).
- Access granted through group membership is invisible to a per-user review: the user has no direct grants and reaches production through three nested groups (Anatomy of a Policy).
- Emergency and project-based grants have no natural end, so break-glass profiles and migration roles persist long after the reason (Break-Glass Access).
- Without a periodic answer to "who can do this", the blast radius of a compromise is unknown, and unknown blast radius means incident response has to assume the worst.
What is actually happening
Underneath the tooling, which is the part that survives a change of tool.
- Review is a backstop, not the primary control. Expiry is the primary control — it removes access by default, which is the only mechanism that survives everyone being busy. Review exists to catch what has no expiry: group membership, service accounts, integrations and grants made outside the normal path (Least Privilege in Production).
- For a review to be meaningful, it has to answer the effective question — "what can this identity actually do?" — rather than the direct one. Direct grants are a small fraction of effective permission in any real system, and a review that only reads them will confidently report that nobody has access to anything.
- The reviewer has to have context. A central security team can see the permissions and cannot know whether this person still needs them; the owning team knows and often will not look. The workable arrangement is that the owning team reviews and the central team is accountable for the review happening.
- Rubber-stamping is the dominant failure and it is a design problem, not a diligence problem: presented with two hundred entries and a deadline, approving all is the only rational action. Reviews stay honest by being small, which means most access should have expired before review time.
- Usage data changes the economics. "This permission has not been exercised in ninety days" turns a judgement into an observation, and it is the single highest-leverage input a review can have.
- The output that matters is removals. A review that confirms everything either found a genuinely tight system or was not a review.
One review cycle
The steps that decide whether a review is real are the first and the last. Enumerate effective permissions rather than direct grants, and measure the output in removals rather than in completion.
- 1Enumerate
Compute effective permissions for every human, service account and integration.
fails by Lists direct grants only, missing access that arrives through nested groups.
evidence A per-identity answer to "what can this actually do?", generated rather than assembled.
- 2Enrich
Attach last-used dates and the reason each grant exists.
fails by No usage data, so every entry is a judgement call with no information behind it.
evidence A last-used timestamp on each permission.
- 3Route
Send each identity to the team that owns the resources it can reach.
fails by Routed to a central team with no context, who approve everything.
evidence The reviewer can say why each grant does or does not still make sense (The Ownership Record).
- 4Decide
Keep, reduce or remove each grant.
fails by Approve-all, because the list is long and the deadline is close.
evidence A per-entry decision, with removals in it.
- 5Stage
Deny and log before deleting, for anything with unclear usage.
fails by Immediate deletion, which breaks a seasonal job nobody thought about.
evidence A watch period with no denied-access errors before final removal.
- 6Apply
Execute the removals.
fails by Decisions recorded and never applied — the most common way a review becomes theatre.
evidence Permissions actually gone, verified by re-enumerating.
- 7Measure
Count removals, standing high-privilege identities, and stale grants.
fails by Measures completion rate instead of effect.
evidence A trend in what access exists, not a trend in reviews completed.
The Stage step is what makes "default to remove" affordable. Deny-and-log converts a risky revocation into a cheap observation, and it is the reason a team can be aggressive about removal without breaking production.
What reviews miss
Every row here is access that a normal review will report as absent. They share a shape: the access does not arrive through a direct grant to a person, so a per-user list does not contain it.
| Trigger | Symptom | Cause | Response |
|---|---|---|---|
| Access through nested group membership | User shows no direct grants and can administer production | Review reads assignments rather than effective permissions | Compute effective permissions with groups and inherited policies expanded (Anatomy of a Policy) |
| Service account created for a migration | Standing credential with broad rights, two years old | Machine identities excluded from human-centred reviews | Review service accounts on the same cadence; prefer workload identity with no standing credential (Workload Identity) |
| Internal team move | Engineer retains access to a system they no longer work on | Offboarding triggers on leaving the company, not on changing team | Trigger reviews on role and team change events |
| Vendor or contractor account | External identity with production access after the engagement ended | Outside the employee lifecycle entirely | Time-bound at creation to the contract end date; no exceptions |
| CI role granted deploy access to everything | Any repository can deploy any service | Enumerating per-service permissions was slower than a wildcard | Scope pipeline identity per service; a broad CI role is a path from any repo to production (Securing the Pipeline Itself) |
| Break-glass profile left active | Standing elevated access from an emergency months ago | Expiry was manual | Hard expiry on all elevation; review confirms none are live (Break-Glass Access) |
| Long-lived static credential | An API key in a config file, valid indefinitely | Nothing forces rotation and nothing tracks the key's existence | Rotate on a schedule; prefer short-lived credentials over keys (Rotation That Applications Survive) |
| Database user created during an incident | A user with write access nobody remembers creating | Created under elevation, never reconciled | Reconcile emergency changes, including identities (Manual Production Changes) |
How often, and triggered by what
Cadence is the wrong first question. Reviews driven by events catch the common cases within days; a calendar catches them within a quarter, on average, and costs the same amount of attention per cycle.
The strongest position combines them: expiry as the default so the list stays short, events as the trigger for the cases that matter, and a long periodic backstop for everything that has neither.
When should production access be re-examined?
when Always, as the base mechanism. Access is time-bound at grant and renewal is a deliberate act.
cost Renewal friction on legitimate ongoing work; needs tooling to make renewal fast enough not to be resented (Short-Lived Credentials).
when Team change, role change, project end, contract end. Catches the largest population within days.
cost Depends on HR and project systems emitting reliable events, which is often the hard part.
when A backstop for grants with no expiry and no triggering event — group memberships, integrations, legacy accounts.
cost Up to three months of staleness; large lists invite approve-all, so it only works if expiry has kept the list short.
when High-privilege access, where standing admin should be alerted on rather than reviewed later.
cost Needs tuning to avoid alert fatigue, and it detects rather than removes (Alert Fatigue).
when A compliance floor, not a control. Rarely sufficient on its own.
cost Up to twelve months of stale access; produces evidence of a review rather than a smaller permission set.
How to do it properly
Most important first.
- Make expiry the default so that review handles the exceptions rather than the population.
- Review effective permissions, expanding groups, inherited policies and resource-attached grants — not the direct assignment list.
- Include service accounts, CI identities, integrations and vendor access. These are usually the broadest grants and the ones most reliably skipped (CI Security).
- Give the review to the owning team, and make its completion visible to whoever is accountable for it (The Ownership Record).
- Attach usage data to every entry. Unused permission is the easiest possible removal decision.
- Trigger reviews on events as well as on a calendar: role change, team change, project completion, contract end. Event-driven catches the common case that a quarterly cadence misses by up to three months.
- Default to removal when nobody can justify an entry. Restoring access is cheap; discovering a forgotten grant during a breach is not.
- Track removals as the outcome. If reviews are not removing anything, either the system is unusually tight or the review is a formality — and you should know which.
How much can this affect
Every production change has a blast radius. Stated as a scale so it is comparable between changes rather than adjectival — and paired with what actually contains it, because a wide scope with a real containment mechanism is a different situation from a wide scope with none.
Contained by whatever scoping the accumulated grants happen to have — which, since nobody has enumerated them, is unknown by definition until a review or a breach establishes it.
What can go wrong
- Approve-all as the default action, which is what any long list plus a deadline produces.
- Reviewing direct grants only, which misses most effective access.
- Reviewer without context — a security team that can see everything and knows nothing about whether it is needed.
- Service accounts excluded because "they are not people", leaving the standing-credential population unreviewed.
- Quarterly cadence treated as sufficient, so an internal move leaves stale access live for up to three months.
- Review as a compliance artifact: the evidence that a review happened is produced, and no permission changes.
- Removals that break something in production because usage was seasonal and nobody checked before revoking (Region Failover).
- A review process so heavy that teams postpone it, and the exception becomes the practice.
- "We do reviews, so access is under control." A review that approves everything is a record of a meeting. Removals are the evidence.
- "Offboarding covers this." Offboarding covers leavers. Internal moves, contractors, service accounts and integrations are the larger population and the one that accumulates.
- "Review is the main control." Expiry is the main control. Review is what catches the access that has no expiry, and it should be looking at a short list (Least Privilege in Production).
- "Removing access is risky." Restoring is minutes. A forgotten standing grant discovered during a breach is a much longer conversation.
Operating it
Evidence is the signal, not the intention. Rollback is sometimes 'you cannot, and that is the point'.
- The last review removed access, and you can name what was removed.
- You can produce the current effective permission set for any identity, including service accounts, without a manual investigation.
- Access following internal moves is removed within days, driven by the move rather than by the calendar.
- The count of identities with standing high-privilege access is known, small, and trending down.
- A revocation has not caused a production incident, because usage was checked before removal.
- Removals should be easy to reverse for a period. Keep the grant recoverable rather than deleted, so restoring is a request rather than a reconstruction — that is what makes "default to remove" safe enough to actually do.
- Stage large revocations: deny and log rather than delete, watch for what breaks, then remove. This turns a risky revocation into an observation, in the same way as tightening a role.
- Never revoke a break-glass path as part of a routine review clean-up without confirming the replacement works. That is the one removal that fails silently until an emergency (Break-Glass Access).
- Automate effective-permission computation. Manual expansion of nested groups is where reviews become inaccurate and where they become unaffordable.
- Automate usage collection so every entry carries a last-used date.
- Automate event triggers — team change, role change, contract end — so reviews are driven by what actually changed rather than by a quarter boundary.
- Automate detection of the specific high-risk shapes: wildcard policies, standing admin, accounts with no recent activity, credentials older than a rotation period (Policy as Code).
- Do not automate revocation from usage data alone. Seasonal and emergency permissions look unused right up until the day they are the only thing that works.
- Do not automate approval. A review where the approval step is automatic has removed the only judgement in the process.
- Reviews cost the time of the people with the most context, recurrently, on work with no visible output. That is a genuine cost and the reason cadences slip.
- Aggressive removal occasionally breaks something. Staged revocation reduces that and adds elapsed time to every removal.
- Frequent reviews are more accurate and more fatiguing. Event-driven triggers plus a longer periodic cadence is usually the better trade than a short cadence applied to everything.
Where this applies
This domain is unusually tool- and organisation-dependent. These labels say what each claim is specific to, and what a different platform, provider or organisation does instead.
- ORG-SPECIFICCadence, who reviews, and whether attestation is required are set by size and regulation. Some regimes mandate quarterly attested reviews with retained evidence; most organisations choose. An event-driven process with a long periodic backstop is usually more effective than a short calendar cadence, where the regulator permits it.
- SCALE-SPECIFICUnder about twenty people, the review is a conversation and takes an hour. Above that, effective-permission computation has to be automated or the review will be inaccurate in ways nobody can see.
- CLOUD-SPECIFICEffective permission is computed differently per provider — inheritance, deny precedence, resource-attached policies and service-linked roles all differ. A review tool built for one provider will systematically miss grants on another (§178).
Where the depth lives
This domain teaches delivery and operation, and hands the mechanism off to the domain that owns it.
- — System Design — access as part of a system's interface, which decays like any other undocumented interface when nobody owns it.