CC6.1 is the SOC 2 control most people conflate with access reviews, and it isn't the same thing. CC6.1 asks whether the entity implements logical access security measures to protect against unauthorized access — provisioning, not periodic review. It's the control that governs how someone gets access in the first place: was the grant approved, was it scoped to what the role actually needs, and is there a record of who approved it and when.
Access reviews (CC6.2, CC6.3) catch what CC6.1 misses after the fact. A strong CC6.1 implementation means there's less for the review to catch in the first place, because access was scoped correctly at grant time instead of granted broadly and cleaned up quarterly.
Why Provisioning Automation Beats Ticket-Based Provisioning
The typical manual provisioning flow — an IT ticket requesting access, an approver clicking approve, IT manually granting the requested permission in each system — has two structural weaknesses that show up in audits repeatedly. First, approvers routinely approve whatever was requested without evaluating whether it matches the role, because evaluating role-appropriateness requires knowledge the approver often doesn't have. Second, the granted permission and the ticket describing it can drift — someone requests read access to a database and gets granted write, and nobody notices until a review months later.
Role-based provisioning automation removes both failure points by defining the entitlement set per role up front, so a request isn't "grant this specific permission," it's "provision this person into this role," with the actual permission set derived automatically and consistently every time.
# role_provisioning.py — role-to-entitlement mapping drives automated grants
ROLE_ENTITLEMENTS = {
"backend_engineer": {
"github": {"team": "engineering", "repo_access": "write"},
"aws": {"role": "arn:aws:iam::123456789012:role/EngineerReadWrite"},
"database": {"schema": "app", "privileges": ["SELECT", "INSERT", "UPDATE"]},
},
"engineering_manager": {
"github": {"team": "engineering", "repo_access": "admin"},
"aws": {"role": "arn:aws:iam::123456789012:role/EngineerReadWrite"},
"database": {"schema": "app", "privileges": ["SELECT", "INSERT", "UPDATE"]},
# note: no production DELETE or admin AWS role — matches the "manager,
# not on-call ops" distinction most companies get wrong by defaulting
# to broader access for more senior titles
},
}
def provision_new_hire(employee_id: str, role: str, approver_id: str, request_ticket: str):
entitlements = ROLE_ENTITLEMENTS.get(role)
if not entitlements:
raise ValueError(f"No entitlement mapping defined for role: {role}")
evidence_record = {
"employee_id": employee_id,
"role": role,
"approver_id": approver_id,
"request_ticket": request_ticket,
"entitlements_granted": entitlements,
"provisioned_at": "2026-01-01T00:00:00Z", # actual timestamp at runtime
}
# fan out grants to each system, log evidence_record as immutable CC6.1 evidence
return evidence_record
The evidence record this produces answers exactly what a CC6.1 sample asks for: who was granted access, what specifically was granted, who approved it, and does the granted entitlement match the documented role definition — all captured at grant time instead of reconstructed after the fact from scattered tickets and manual system checks.
The Trap: Role Definitions That Don't Match Reality
Provisioning automation is only as good as the role-to-entitlement mapping behind it, and the most common failure mode is a mapping that was accurate on day one and never updated as the role's actual needs changed. An engineer who genuinely needs temporary elevated access for an incident gets a manual, undocumented grant outside the automated flow "just this once," and that exception becomes permanent because nobody circles back to either formalize it in the role definition or revoke it.
The fix is treating manual exceptions as first-class, time-boxed grants with an explicit expiration — not a separate, invisible parallel path to the automated system, but a tracked exception type within it that expires automatically unless explicitly renewed.
Separation of Duties Lives in the Same Control
CC6.1 also covers separation of duties — the same person shouldn't be able to both request and approve their own access change, and certain sensitive combinations (deploy access plus production database write access, for example) may need to be explicitly restricted or flagged for additional review depending on the company's risk tolerance. Provisioning automation is where this gets enforced structurally: a request from someone who is also the designated approver for their own team should route to a secondary approver automatically, not rely on the approver remembering to recuse themselves.
Frequently Asked Questions
What's the difference between CC6.1 and CC6.2 in practice?
CC6.1 covers provisioning — the controls around granting access in the first place. CC6.2 covers modification and removal of access based on role changes and terminations. An auditor testing CC6.1 samples new-hire and role-change grants; testing CC6.2 samples deprovisioning events and periodic reviews. Both matter, and strong CC6.1 controls reduce the volume of findings CC6.2 review would otherwise catch.
Does automating provisioning eliminate the need for approval workflows?
No — it structures and enforces the approval workflow rather than removing it. The automation ensures the entitlement granted matches what was actually approved and matches the role definition; a human approver is still deciding whether the request itself should be approved in the first place.
How do we handle temporary or emergency access that doesn't fit a defined role?
Build it as an explicit, time-boxed exception type within the provisioning system rather than a manual workaround outside it — same evidence logging, same approval requirement, with an automatic expiration that forces a renewal decision rather than letting temporary access become permanent by default.
What evidence does a CC6.1 sample actually require?
For a sampled set of new hires or role changes during the audit period: the access request, the approval record with approver identity and timestamp, the entitlements actually granted in each system, and confirmation the granted entitlements match the role's documented access requirements — all four pieces, not just the ticket.
Can this work without a dedicated IGA platform?
Yes, for companies with a manageable number of systems and reasonably standardized roles — the role-to-entitlement mapping and evidence logging can be built directly against each system's API. Once role complexity and system count grow past what a maintained mapping table can reasonably handle, a dedicated IGA platform's workflow and connector library starts to pay for itself.
Rutagon builds role-based provisioning automation that generates CC6.1 evidence at grant time — not reconstructed later from scattered tickets.
See what an Access & Credential Governance Diagnostic finds in your environment → rutagon.com/contact | 907-841-8407 | contact@rutagon.com
Related reading: User Access Review Automation · Privileged Access Review Automation for AWS Admin Paths · Security Automation Capability
External reference: AICPA Trust Services Criteria