Documentation Index
Fetch the complete documentation index at: https://docs.provisionr.io/llms.txt
Use this file to discover all available pages before exploring further.
The auditor asks: “Can I see evidence that access is appropriate?”
Three options exist:
Option A: Export a spreadsheet of 8,000 rows showing who has access to what. Hand it to the auditor. Hope they’re satisfied.
Option B: Show quarterly access review documentation where managers approved everything without looking.
Option C: Show them the policy engine, continuous compliance monitoring, and complete audit trail of every access decision.
Options A and B: The auditor is skeptical. They ask follow-up questions. The organization scrambles to explain edge cases. The audit extends.
Option C: The auditor is impressed. They understand the model. They see strong controls. The audit goes smoothly.
This is audit-ready compliance—the practice of designing access management systems to produce compliance evidence automatically, not as an afterthought.
What Auditors Actually Want
Auditors don’t care about tools. They care about controls.
Controls answer four questions:
- Who should have access? (Policy)
- Who actually has access? (Reality)
- Does #1 match #2? (Compliance)
- Can the organization prove it? (Evidence)
Clear answers to these questions, with continuous validation, make auditors happy.
Without clear answers, they dig deeper. More questions. More evidence requests. More pain.
The Traditional Approach (And Why It’s Weak)
Traditional compliance:
Quarterly access reviews. Export who has what. Send to managers. Managers approve.
Access request tickets. Every access change has a ticket. Tickets are evidence.
Audit logs. Systems log who accessed what.
Problems:
Quarterly reviews are point-in-time. Access is reviewed on March 31. Sarah gets inappropriate access on April 5. It’s not discovered until June 30 (next review). She had inappropriate access for 86 days. Auditors see this as a control gap.
Managers don’t actually review. Managers receive 200 rows: “Please confirm these people should have this access.” Managers don’t know what half the groups do. They approve everything to avoid breaking something. The review is theater, not governance. Auditors increasingly recognize this.
Tickets don’t explain policy. A ticket says: “Add Sarah to finance-reports group.” The auditor asks: “Why does Sarah need finance reports access?” Someone searches through tickets. A justification may or may not exist. Tickets document actions, not rationale.
Audit logs show activity, not appropriateness. The audit log shows: “Sarah accessed customer database on Oct 15.” The auditor asks: “Should Sarah have access to the customer database?” The log doesn’t answer this. Other documentation must be consulted—policies, role definitions, etc.
Point-in-time reviews create control gaps between review cycles. Continuous validation with daily drift detection eliminates these gaps, providing evidence of ongoing compliance rather than periodic attestation—directly addressing SOC 2 CC4.1 (monitoring activities) and ISO 27001 A.18.2.3 (technical compliance review).
The Audit-Ready Approach
Audit-ready compliance:
Policy documentation
Clear definition of who should have what access based on role.
Continuous validation
Daily comparison of policy to reality.
Exception tracking
Every deviation from policy is logged with justification.
Immutable audit trail
Every access decision is recorded, timestamped, and attributed.
This produces compliance evidence automatically.
Component 1: Policy Documentation
Instead of: Scattered knowledge (“Sales Engineers get Salesforce because… reasons”)
Do this: Documented policies
policy:
name: "Sales Engineer Access"
version: "2.1"
effective_date: "2024-11-24"
owner: "vp-sales@company.com"
approver: "ciso@company.com"
description: "Baseline entitlements for all Sales Engineers"
scope:
applies_to:
job_title: "Sales Engineer"
employment_type: "FTE"
grants:
- system: "salesforce"
resource: "profile:sales-engineer"
permission: "standard"
justification: "Sales Engineers require CRM access to manage customer relationships and track deal progress"
- system: "slack"
resource: "channel:#sales-team"
permission: "member"
justification: "Sales Engineers must coordinate with sales team on customer engagements"
- system: "gitlab"
resource: "group:customer-solutions"
permission: "reporter"
justification: "Sales Engineers need visibility into customer-facing code and demos, but not commit access"
change_history:
- version: "2.1"
date: "2024-11-24"
changed_by: "it-admin@company.com"
changes: "Added GitLab customer-solutions access"
approval: "ciso@company.com"
- version: "2.0"
date: "2024-06-15"
changed_by: "it-admin@company.com"
changes: "Updated Salesforce profile from 'basic' to 'sales-engineer'"
approval: "vp-sales@company.com"
Why this is audit-ready:
Clear scope. “This policy applies to anyone with job_title=‘Sales Engineer’”
Explicit grants. Each access grant is documented with justification.
Change history. Every policy change is versioned and approved.
Ownership. Clear owner and approver for the policy.
When the auditor asks: “Why do Sales Engineers have Salesforce access?”
The answer: “Because the Sales Engineer Access Policy (v2.1) grants it. Here’s the policy document. Here’s when it was approved. Here’s the justification.”
Component 2: Continuous Validation
Instead of: Quarterly reviews (point-in-time snapshots)
Do this: Daily drift detection
def validate_compliance_daily():
"""Run daily - compare policy to reality"""
for user in all_active_users:
# Calculate expected access (from policy)
expected = policy_engine.calculate_access(user)
# Fetch actual access (from systems)
actual = fetch_current_access(user)
# Compare
drift = compare(expected, actual)
if drift:
# Log drift
log_drift(
user=user,
expected=expected,
actual=actual,
drift=drift,
detected_at=datetime.now()
)
# Generate compliance report
generate_compliance_report(user, drift)
Drift report:
Compliance Report - 2024-11-24
User: sarah.chen@company.com
Role: Sales Engineer
Status: DRIFT DETECTED
Expected Access (from policy):
salesforce:profile:sales-engineer
slack:channel:#sales-team
gitlab:group:customer-solutions (reporter)
Actual Access:
salesforce:profile:sales-engineer
slack:channel:#sales-team
gitlab:group:customer-solutions (reporter)
gitlab:group:platform-engineering (developer) ← NOT IN POLICY
Action Required:
- Investigate: Why does Sarah have platform-engineering access?
- Options:
1. Remove access (if inappropriate)
2. Document as exception (if temporary/justified)
3. Update policy (if this should be standard for Sales Engineers)
Why this is audit-ready:
Continuous monitoring. Drift is detected within 24 hours, not 90 days.
Clear expectations. Policy defines expected state.
Explicit deviations. Any access outside policy is flagged.
Audit trail. Every drift detection is logged.
When the auditor asks: “How is access appropriateness ensured?”
The answer: “Access is validated daily via automated policy compliance checks. Here’s the drift detection dashboard. Here’s the log of all drift detected this year. Here’s how each case was remediated.”
Component 3: Exception Tracking
Instead of: Manual access grants that bypass policy (shadow IT)
Do this: Explicit exceptions with justification, approval, and expiration
exception:
id: "exc_789"
user: "sarah.chen@company.com"
resource: "gitlab:group:platform-engineering"
permission: "developer"
justification: "Cross-functional project: Billing system rewrite. Sales Engineer supporting integration between sales workflows and new billing system."
business_need: "project"
project_id: "proj-billing-rewrite-2025"
requested_by: "sarah.chen@company.com"
requested_at: "2024-11-24T10:00:00Z"
approved_by: "cto@company.com"
approved_at: "2024-11-24T14:00:00Z"
approval_note: "Approved for billing system project. Remove access when project completes."
granted_at: "2024-11-24T14:05:00Z"
expires_at: "2025-03-31T00:00:00Z" # 4 months
status: "active"
Why this is audit-ready:
Explicit justification. Clear business reason for access.
Appropriate approval. CTO approved engineering access for non-engineer.
Defined expiration. Temporary access, not permanent.
Complete trail. Request, approval, grant, and expiration are all logged.
When the auditor asks: “Why does a Sales Engineer have developer access to platform-engineering?”
The answer: “It’s a documented exception (exc_789) for a cross-functional project. Here’s the justification. Here’s the approval from the CTO. It expires on March 31.”
Component 4: Immutable Audit Trail
Instead of: Mutable logs (can be modified or deleted)
Do this: Immutable audit log with cryptographic verification
class AuditLog:
def log_event(self, event_type, user, resource, action, metadata):
"""Log an access management event"""
event = {
"id": generate_event_id(),
"timestamp": datetime.now().isoformat(),
"event_type": event_type, # "access_granted", "access_revoked", "policy_updated", etc.
"user": user,
"resource": resource,
"action": action,
"actor": get_current_actor(), # Who made this change
"metadata": metadata,
"system_state": get_system_state_snapshot()
}
# Calculate cryptographic hash
event["hash"] = calculate_hash(event)
# Reference previous event (blockchain-style)
previous_event = get_last_event()
event["previous_hash"] = previous_event["hash"]
# Write to append-only log
audit_log.append(event)
# Also write to immutable storage (S3 with versioning + object lock)
s3.put_object(
Bucket="compliance-audit-logs",
Key=f"events/{event['id']}.json",
Body=json.dumps(event),
ObjectLockMode="GOVERNANCE",
ObjectLockRetainUntilDate=datetime.now() + timedelta(days=2555) # 7 years
)
return event["id"]
Audit trail example:
{
"id": "evt_123456",
"timestamp": "2024-11-24T14:05:23Z",
"event_type": "access_granted",
"user": "sarah.chen@company.com",
"resource": "gitlab:group:platform-engineering",
"action": "add_member",
"permission": "developer",
"actor": "system",
"reason": "exception_approved",
"exception_id": "exc_789",
"metadata": {
"approved_by": "cto@company.com",
"justification": "Cross-functional project: Billing system rewrite",
"expires_at": "2025-03-31T00:00:00Z"
},
"hash": "a3f5b2c8d1e9f4a7b6c3d2e1f9a8b7c6",
"previous_hash": "f9a8b7c6d5e4f3a2b1c9d8e7f6a5b4c3"
}
Why this is audit-ready:
Immutable. Once written, cannot be modified (S3 object lock).
Complete. Every access decision is logged.
Tamper-evident. Cryptographic hashing detects modifications.
Long retention. 7-year retention meets most compliance requirements.
When the auditor asks: “How is log accuracy and tamper-resistance ensured?”
The answer: “The audit log is cryptographically chained and stored in immutable storage. Here’s how integrity is verified. Here’s the retention policy.”
Immutable, cryptographically-chained audit logs satisfy SOC 2 CC7.2 (system monitoring), SOX Section 302 (control certification), and ISO 27001 A.12.4.1 (event logging). The 7-year retention period covers most regulatory requirements including SEC Rule 17a-4 for financial services.
Compliance Reporting
Generate reports automatically:
Report 1: Policy Coverage
Policy Coverage Report - 2024-11-24
Total Users: 847
Total Access Grants: 12,384
Policy-Based Access:
- Covered by policy: 11,789 (95.2%)
- Documented exceptions: 478 (3.9%)
- Drift (under investigation): 117 (0.9%)
Policy Breakdown:
- Base Employee: 847 users (100%)
- Engineering: 234 users
- Sales: 112 users
- Marketing: 87 users
- Finance: 45 users
- [... other departments]
Exception Summary:
- Active exceptions: 478
- Expiring this month: 34
- Extended (this quarter): 12
- Average duration: 38 days
Compliance Status: HEALTHY
- 95%+ coverage by policy (target: >90%)
- <1% drift (target: <5%)
- Exception rate within acceptable range
Report 2: Access Changes
Access Changes Report - November 2024
New Hires: 23
- Average time to full access: 4.2 hours
- Policy-based provisioning: 100%
Terminations: 18
- Average time to full revocation: 1.8 hours
- Policy-based deprovisioning: 100%
Role Changes: 15
- Promotions: 9
- Department transfers: 6
- Average transition time: 8.3 hours
- Graceful deprecation used: 12 (80%)
Exceptions Granted: 42
- Project access: 28
- Training: 8
- Role transitions: 6
- Average approval time: 6.2 hours
Exceptions Expired: 37
- Auto-revoked on expiration: 34 (92%)
- Extended: 2
- Manually revoked early: 1
Drift Remediation Report - November 2024
Drift Incidents: 23
Resolved: 21 (91%)
- Removed inappropriate access: 12
- Documented as exception: 6
- Updated policy (access should be standard): 3
Open (under investigation): 2
- User: john.doe@company.com
Resource: aws:prod-admin
Detected: 2024-11-22
Status: Escalated to CISO
- User: jane.smith@company.com
Resource: finance-reports
Detected: 2024-11-23
Status: Awaiting manager approval for exception
Average Time to Resolution: 18 hours
Target: <24 hours
Compliance Status: GOOD
Audit Presentation
When auditors arrive, show them:
1. Policy Documentation. “Here are the access policies. Each role has a defined policy. Policies are version-controlled and require CISO approval for changes.”
2. Continuous Compliance Dashboard. “Access is validated daily. This dashboard shows policy coverage, active exceptions, and any drift.”
3. Audit Trail. “Every access decision is logged immutably. Here’s the complete trail for any user or resource.”
4. Exception Management. “When access doesn’t fit policy, it’s documented explicitly as an exception with justification, approval, and expiration.”
5. Drift Remediation Process. “When drift is detected—access that doesn’t match policy—it’s investigated and remediated within 24 hours.”
6. Metrics and Trends. “Here are the compliance metrics over the past year. Policy coverage is 95%+. Drift is under 1%. Exception rate is 3-4%.”
Common Audit Questions and Answers
Q: “How is it ensured that only authorized people have access?”
A: “Authorization is defined via policy. The policy specifies what access each role should have. The system validates daily that actual access matches policy. Any deviation is flagged and investigated.”
Q: “How often is access reviewed?”
A: “Access is validated daily via automated policy compliance checks. For exceptions—access outside of policy—review happens quarterly to confirm they’re still needed.”
Q: “Who approves access changes?”
A: “Policy-based access is pre-approved by the CISO when the policy is created. Exception-based access requires approval from the appropriate resource owner—CFO for finance data, CTO for production systems.”
Q: “How are role changes handled?”
A: “When someone’s role changes, the policy engine recalculates required access. Graceful deprecation is used—old access is removed gradually with defined overlap periods for handoffs. Every transition is logged.”
Q: “What happens when someone leaves?”
A: “HRIS marks them inactive. Within hours, all access is automatically revoked. The complete deprovisioning is logged.”
Q: “How is inappropriate access detected?”
A: “Daily drift detection runs. If someone has access not defined in their role policy and not documented as an exception, it’s flagged within 24 hours.”
Q: “Can evidence for a specific user be shown?”
A: “Yes. Here’s the user’s current role, here’s the policy that applies, here’s their actual access, here’s any exceptions, and here’s the complete audit trail of every access change for this user.”
Q: “How is audit log accuracy ensured?”
A: “Audit logs are cryptographically chained and stored in immutable S3 storage with 7-year retention. They cannot be modified or deleted.”
Compliance Frameworks
This model satisfies most compliance requirements:
SOC 2: Access controls (policy-based provisioning). Change management (versioned policies, audit trail). Monitoring (daily drift detection).
ISO 27001: Access control policy (documented policies). Access rights management (policy-based provisioning). Review of user access rights (continuous validation).
GDPR: Access control (policy-based, least privilege). Audit trail (complete logging of access decisions). Right to erasure (automated deprovisioning).
HIPAA: Access management (policy-based provisioning). Audit controls (immutable audit trail). Person or entity authentication (integration with IdP).
PCI DSS: Restrict access (policy-based, least privilege). Unique ID for each person with access (enforced by IdP). Track and monitor access (audit trail, drift detection).
The Bottom Line
Traditional compliance is reactive. Review access quarterly, hope it’s correct, scramble when auditors ask questions.
Audit-ready compliance is proactive. Define policies, validate continuously, track exceptions, log everything.
Components of audit-ready compliance:
Policy documentation
Who should have what, and why.
Continuous validation
Daily comparison of policy to reality.
Exception tracking
Explicit management of deviations.
Immutable audit trail
Every decision is logged permanently.
Automated reporting
Compliance evidence generated automatically.
Benefits:
- Audits go smoother (strong evidence)
- Compliance is continuous (not point-in-time)
- Drift is detected immediately (not 90 days later)
- IT knows what’s supposed to happen (not guessing)
Investment: 2-4 weeks to build audit-ready compliance on top of policy-based access.
Stop treating compliance as an afterthought. Build it in from day one. Future audits will go much more smoothly.
This concludes our series on policy-based access management. We’ve covered the problems (access requests, role transitions), the solutions (policy-first approach, orchestration), and the implementation details (exceptions, graceful deprecation, compliance).