Skip to main content

User access reviews: design, evidence and the commands to start

How to run an access review a manager can actually complete, with read-only commands for Windows, Linux and AWS and the evidence an auditor expects.

Who this is for: IT and security managers who have to run, or evidence, periodic reviews of who has access to what. It suits a small or mid-sized organisation with a directory service and several business applications, and it assumes you can run read-only reports against your own systems.

What an access review is meant to catch

An access review asks, on a schedule, whether each person who can do something in a system should still be able to. It exists because access accumulates. People change roles and keep old permissions, contractors finish and their accounts remain, an administrator right granted for a project outlives the project, and nobody is ever asked to hand permissions back.

The review is a detective control. It does not stop inappropriate access being granted; it finds what slipped through joiner, mover and leaver processes. That is why auditors and insurers ask about it: it is the check on whether your other access controls work.

A review has failed if it produces a signed spreadsheet but removes no access and finds no errors in a year. Real populations always contain something to correct. A clean result every time suggests the reviewers are approving without looking.

Scope: decide which systems and which access

You cannot review everything on the same cycle. Rank systems by what damage excess access could do, and set a frequency by tier.

TierWhat it coversSuggested cadence
PrivilegedDomain or tenant administrators, root and sudo, cloud console administrators, database administrators, backup administrators, anything that can change other people’s accessQuarterly
Sensitive dataFinance, HR, customer data, source code, systems holding regulated dataTwice a year
General business appsEveryday SaaS and file sharesAnnually
Shared and non-humanService accounts, API keys, shared mailboxes, break-glass accountsQuarterly, owner-confirmed

The cadences are starting points. Pick ones you can sustain, write them down and keep to them. A quarterly review you actually complete is worth more than a monthly one you abandon.

Who should review: the person who knows the need

The most common design flaw is asking IT to review access. IT can tell you what an account *can* do, but not whether the person *should*. The reviewer should be someone who knows the business need:

  • For user access to an application: the line manager, who knows the person’s role, and the application owner, who knows what each role grants.
  • For privileged access: the security lead and the system owner together, since neither alone has the full picture.
  • For service accounts: the named owner of the service.

Reviewers must not review their own access. Where a manager’s access is in the list, a peer or their own manager reviews it.

Getting an accurate list

The review is only as good as the list. Auditors call this the completeness and accuracy of the information you give them: if the user list you export is missing accounts, the reviewer cannot catch what is not shown.

A few read-only commands that help. They are safe to run as written because they only read; adapt group names and paths to your environment.

On Windows with the Active Directory PowerShell module, list the members of a privileged group with last-logon details and save them to a dated file:

Get-ADGroupMember -Identity 'Domain Admins' -Recursive |
    Where-Object objectClass -eq 'user' |
    Get-ADUser -Properties Enabled, LastLogonDate, PasswordLastSet |
    Select-Object SamAccountName, Enabled, LastLogonDate, PasswordLastSet |
    Sort-Object SamAccountName |
    Export-Csv -Path .\domain-admins-2026-10.csv -NoTypeInformation

To find enabled user accounts that have not signed in for 90 days:

Search-ADAccount -AccountInactive -UsersOnly -TimeSpan 90.00:00:00 |
    Where-Object Enabled |
    Select-Object SamAccountName, LastLogonDate, DistinguishedName |
    Export-Csv -Path .\inactive-90d-2026-10.csv -NoTypeInformation

Be aware that LastLogonDate is derived from an attribute that is replicated lazily between domain controllers, so it can lag real activity by up to about two weeks. It is good for finding accounts untouched for months, not for proving a person logged in last Tuesday.

On a Linux server, three quick checks:

awk -F: '$3 == 0 { print $1 }' /etc/passwd     # accounts with UID 0 (should normally be only root)
getent group sudo wheel                           # members of administrator groups (name varies by distribution)
lastlog -b 90                                     # accounts whose last login was more than 90 days ago

For an AWS account, the IAM credential report lists every user with password and access-key ages:

aws iam generate-credential-report
aws iam get-credential-report --query Content --output text | base64 --decode > credential-report-2026-10.csv

Each command only reads or generates a report. Keep the output files with the review evidence, with the date in the file name. For SaaS applications, use the application’s own user export and note that it came from the system, not from a hand-typed list.

Running the review

  1. Extract the population on a stated date and record how you did it (command, report name, who ran it).
  2. Enrich it: add job title, manager, employment status from HR, and last sign-in. An account whose owner left the company three months ago is obvious once the HR status is next to it.
  3. Send each reviewer only their portion, with a clear question: for each person, keep, change or remove, and a reason if changed.
  4. Set a deadline and chase. Without chasing, response rates are poor.
  5. Act on the decisions. Raise tickets for every removal or change and record the ticket numbers against the line.
  6. Verify that the removals happened by re-extracting and comparing.
  7. Record the sign-off: who reviewed, when, what was changed, what exceptions were accepted and by whom.
  8. Feed the findings to the register: a pattern of stale privileged accounts is a risk entry, not just a cleanup task.

A worked example of what a good record looks like for one line:

account:        svc-reporting
population:     enabled accounts in group "Finance-Readers", extracted 2026-10-05
reviewer:       Finance Director
decision:       REMOVE
reason:         Reporting tool decommissioned in July; account unused since 2026-07-21
ticket:         CHG-2291, completed 2026-10-07
verified:       2026-10-12, account no longer present in group

Special cases

Leavers. The review is the second line of defence, not the first. The first is a leaver process that disables accounts on the last day. When the review finds ex-employees with active accounts, count them: the number tells you how well the process works, and each one is a finding.

Movers. People who change roles often keep access from the old role. Review the list for people with permission sets that do not match any single job.

Service accounts. They have no manager, so they are skipped. Assign each one an owner, a stated purpose and a rotation date for its credentials. Accounts with interactive logon rights and password-never-expires settings deserve a second look.

Shared accounts. Where they exist, record who knows the credential and rotate it when people leave. Better still, remove the sharing.

Break-glass accounts. Emergency administrator accounts should be few, documented, stored securely and tested. Review who can retrieve the credentials, and alert when they are used.

Contractors and suppliers. Include them. Supplier staff with remote access are in scope for both this review and your vendor risk work.

Review roles, not just individual permissions

A reviewer asked to judge 40 separate permissions per person will approve them all. Where the application supports roles or groups, review at that level in two passes. First, once a year, have the application owner confirm that each role still grants only what its description says and that nobody has been given a role that does not match their job. Second, in each periodic review, have the manager confirm that each person holds the right *role*, rather than inspecting every underlying permission. Individual permissions outside any role, often called direct grants, are the part to review line by line, because they are where exceptions hide.

Keep the evidence of the first pass too. An auditor who sees only managers confirming roles will ask who confirmed that the roles themselves were sensible.

How access reviews go wrong

  • Rubber-stamping. A manager receiving 400 rows approves them all in a minute. Reduce the volume (review roles, not every entitlement), highlight exceptions and ask for a reason on every “keep” that is flagged as unusual.
  • Reviewing a list you cannot trust. An export that omits disabled-but-not-deleted accounts, local application users or nested groups gives a false sense of coverage.
  • No follow-through. Decisions made, tickets never closed. Always verify.
  • Evidence by screenshot. Screenshots are hard to reproduce and easy to challenge. A system-generated export with a timestamp is stronger.
  • Reviewer conflicts. People approving their own or their team’s access with no independent check.
  • One-off. A single annual push with nothing in between. Pair it with joiner-mover-leaver controls and alerts on privileged group changes.

What to do next

Pick the privileged tier first. Export the administrator groups across your directory and main business systems, ask the security lead and each system owner to confirm every entry, and record the outcome as above. Turn any systemic finding, such as many stale administrator accounts, into an entry in your risk register and score it on the scale. The completed review, with the extraction method and ticket references, is the kind of operating evidence that audit preparation depends on.