Quarterly access reviews at most mid-market companies run the same way: someone exports a user list from each system into a spreadsheet, tags a manager on each row, and chases down attestations over Slack for three weeks. The auditor doesn't just want the spreadsheet — they want to know the review actually caught something, and most spreadsheet-based reviews can't prove that.
Why Spreadsheet Reviews Fail Audits
Auditors evaluating SOC 2 CC6.1-6.3 controls aren't checking whether a review happened — they're checking whether it was effective. A spreadsheet review typically fails on a few specific points:
- No timestamped evidence trail — a spreadsheet edited in place doesn't prove who reviewed what, or when
- Stale entitlement snapshots — by the time reviewers get to row 40, the access list from row 1 may already be outdated
- No remediation loop — flagging "this contractor shouldn't have prod access" in a spreadsheet doesn't actually revoke it; someone has to remember to act
- Reviewer fatigue on large systems — a manager reviewing 80 rows of raw permission strings rubber-stamps them, which auditors increasingly catch and flag as an ineffective control
What an Automated Review Pipeline Actually Does
We build access review automation as an ingest-normalize-review-remediate pipeline that sits in front of whatever GRC platform the client already runs (Vanta, Drata, Secureframe), not as a replacement for it.
1. Entitlement ingest. Pull current access state directly from source systems via API — AWS IAM (users, roles, group memberships, attached policies), Okta or Google Workspace group membership, database role grants, and application-level RBAC tables for internal tools that don't expose a standard API.
def ingest_aws_entitlements(account_id: str) -> list[Entitlement]:
iam = boto3.client("iam")
entitlements = []
for user in iam.list_users()["Users"]:
policies = iam.list_attached_user_policies(UserName=user["UserName"])
groups = iam.list_groups_for_user(UserName=user["UserName"])
entitlements.append(Entitlement(
principal=user["UserName"],
source_system="aws-iam",
policies=[p["PolicyName"] for p in policies["AttachedPolicies"]],
groups=[g["GroupName"] for g in groups["Groups"]],
last_used=get_last_activity(user["UserName"]),
))
return entitlements
2. Normalization against a role model. Raw IAM policy names or database grants mean nothing to a business owner reviewing access. We map each entitlement to a human-readable capability ("can read customer PII," "can deploy to production") using a role taxonomy built once per client, so reviewers see plain-language risk, not JSON policy documents.
3. Owner-routed attestation. Instead of one giant spreadsheet, each system or business owner gets a scoped review — only the entitlements relevant to their team — delivered through a lightweight review UI or, when the GRC platform supports it, pushed as review tasks directly into that tool.
4. Automated flagging before human review even starts. Access with no login activity in 90+ days, orphaned accounts (no matching HR record), and privilege combinations that violate separation-of-duties rules get pre-flagged, so reviewers spend their limited attention on genuine judgment calls, not obvious cleanup.
5. Remediation with a closed loop. A "revoke" decision in the review triggers an actual ticket or, where safe, an automated deprovisioning action — with the before/after state captured as evidence, not just the reviewer's checkbox.
Where This Fits Against Vanta/Drata/Secureframe
Modern GRC platforms are genuinely good at the easy 70%: standard SaaS app access via SSO logs, straightforward SCIM-connected tools. Where they consistently fall short is the other 30% — internal applications with no SCIM support, database-level access, AWS IAM role chains, and legacy systems with homegrown permission models. That's the layer we build, feeding clean, normalized evidence back into whatever platform the client already runs rather than asking them to rip it out.
What Auditors Actually Want to See
CC6.1 (logical access controls) and CC6.2/6.3 (provisioning/deprovisioning) evidence holds up best when it shows: a defined review cadence, a documented reviewer for each access grant, a timestamped decision, and proof that "revoke" decisions were actually executed — not just noted. Reference NIST SP 800-53 AC-2 (Account Management) for the underlying control language most SOC 2 mappings derive from.
Frequently Asked Questions
How long does it take to build an access review automation pipeline?
For a company with 3-5 core systems (AWS, an SSO provider, and one or two internal apps), an initial pipeline covering ingest, normalization, and a basic review UI typically takes a few weeks to stand up, with additional systems added incrementally afterward.
Does this replace our GRC platform?
No — it feeds evidence and review workflows into your existing GRC platform for the systems it can't natively reach (custom internal apps, database roles, complex IAM structures), rather than replacing the platform itself.
Can this work if our internal apps have no SCIM support?
Yes — that's specifically the gap this closes. We build a direct API or database-level integration to pull entitlement data from systems that were never designed with SCIM or standard identity provisioning in mind.
What happens when a reviewer flags access for removal?
The pipeline generates a remediation ticket and, where the source system supports safe automated deprovisioning, can execute the revocation directly — with the before/after state logged as audit evidence.
Will this help with a failed access review finding from a prior audit?
Often yes — a documented, automated review process with a clear remediation trail is exactly what auditors want to see addressing a prior-period finding around access control effectiveness.
See what an Access & Credential Governance Diagnostic finds in your environment → rutagon.com/contact or call 907-841-8407.