Skip to main content

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.

Policy-based access is working. Life is good. 95% of access provisions automatically based on role, department, and team. Then a ticket arrives:
“I need temporary access to the finance-reports group for a cross-functional project analyzing sales commission structure. I’ll need it for about 6 weeks.”
This doesn’t fit any existing policies. The requestor is a Sales Engineer. Sales Engineers don’t get finance access. But the business need is legitimate. Reject the request because it doesn’t fit policy? That turns IT into blockers, not enablers. Manually grant access outside the policy system? That defeats the purpose of policy-based access. Create a new Ruleset for “Sales Engineer with Finance Access”? Role explosion follows. 147 Rulesets within a year. Handle it as an exception—a first-class object in the access management system with explicit justification, approval, and expiration. This is exception management.

Why Exceptions Matter

Not all access fits into neat policy boxes.
1

Temporary needs arise

Cross-functional project access for a defined period. The project ends, the access ends.
2

Unique situations occur

A one-off requirement that won’t repeat. Creating permanent policy for a single instance wastes everyone’s time.
3

Sensitive access requires explicit approval

Even if policy could grant it, some access needs human sign-off.
4

Transitions overlap

Someone changing roles needs access from both roles during handoff.
If the policy-based system can’t handle exceptions gracefully, people work around it. They request manual access grants directly in systems, bypassing policy. They create shadow IT processes—spreadsheets tracking “temporary” access. They abuse existing Rulesets, adding people to groups they don’t belong in just to get one permission. A good exception system is the difference between policy-based access that people trust and policy-based access that people circumvent.
Explicit exception rules with documented justification and expiration dates satisfy auditor requirements for access outside standard policy. This creates a defensible audit trail: who approved the exception, why, and when it expires—addressing SOC 2 CC6.1 and ISO 27001 A.9.2.6 (removal or adjustment of access rights).

Exception Lifecycle

1. Request with Justification

Sarah (Sales Engineer) needs finance access for a project. Exception request:
exception_request:
  requestor: "sarah.chen@company.com"
  access: "google:group:finance-reports@company.com"
  justification: "Q4 sales commission analysis project. Working with Finance team to validate commission calculations against sales data."
  duration: "6 weeks"
  project: "Commission Transparency Initiative"
  approver: "cfo@company.com"
Key elements: What access (specific group/role/permission). Why (clear business justification). How long (defined timeframe, not permanent). Who approves (appropriate authority—CFO for finance data).

2. Approval Workflow

The CFO receives an approval request:
Exception Request: Finance Reports Access

Requestor: Sarah Chen (Sales Engineer)
Access: finance-reports@company.com
Justification: Q4 sales commission analysis project
Duration: 6 weeks (expires 2025-01-06)
Project: Commission Transparency Initiative

This access is NOT in Sarah's role policy.
Exception requires explicit approval.

[ Approve ] [ Deny ] [ Request More Info ]
CFO approves. System logs:
Exception approved:
- Approved by: cfo@company.com
- Approved at: 2024-11-24T14:30:00Z
- Approval note: "Approved for commission analysis. Ensure data is handled per privacy policy."

3. Provisioning

The orchestration layer provisions access:
def provision_exception(exception):
    # Grant the access
    adapter = get_adapter(exception.system)
    adapter.grant_access(exception.user, exception.resource)

    # Set expiration
    schedule_removal(
        user=exception.user,
        resource=exception.resource,
        removal_date=exception.expires_at
    )

    # Tag as exception
    tag_access_as_exception(
        user=exception.user,
        resource=exception.resource,
        exception_id=exception.id
    )

    # Log everything
    log_exception_granted(exception)
Critical: The system knows this is an exception. It’s tracked separately from policy-based access.

4. Monitoring

While the exception is active: For the user:
You have temporary access:
- finance-reports@company.com (expires in 38 days)

This access is temporary for project: Commission Transparency Initiative
Expiration: 2025-01-06
For IT:
Active exceptions (6):
1. sarah.chen@company.com → finance-reports (38 days remaining)
2. john.doe@company.com → aws:prod-readonly (12 days remaining)
3. ...

[ Review ] [ Extend ] [ Revoke ]
For auditors:
Exception log:
- User: sarah.chen@company.com
- Access: finance-reports@company.com
- Granted: 2024-11-24
- Justification: "Q4 sales commission analysis"
- Approved by: cfo@company.com
- Expires: 2025-01-06
- Status: Active

5. Expiration and Renewal

Two weeks before expiration:
Email to sarah.chen@company.com:

Your temporary access to finance-reports@company.com expires in 14 days (2025-01-06).

If you still need this access:
[ Request Extension ]

If you no longer need it:
No action required - access will be automatically removed.

Project: Commission Transparency Initiative
Original justification: Q4 sales commission analysis
Option A: User does nothing. Access auto-revokes on 2025-01-06. Option B: User requests extension:
Extension Request:
- Original expiration: 2025-01-06
- Requested extension: +4 weeks (new expiration: 2025-02-03)
- New justification: "Project extended. Need to analyze Q1 data as well."
- Approver: cfo@company.com
CFO approves or denies. If approved, expiration extends. If denied, access revokes on original date.

6. Removal

On expiration date (or when manually revoked):
def revoke_exception(exception):
    # Remove access
    adapter = get_adapter(exception.system)
    adapter.revoke_access(exception.user, exception.resource)

    # Update exception status
    exception.status = "revoked"
    exception.revoked_at = datetime.now()
    exception.revocation_reason = "expired"

    # Notify user
    notify_user(exception.user, "Your temporary access to {resource} has been removed as planned.")

    # Log
    log_exception_revoked(exception)
Sarah’s access is removed. The exception is closed. Audit trail:
Exception lifecycle:
- Requested: 2024-11-24 14:00:00
- Approved: 2024-11-24 14:30:00 (by cfo@company.com)
- Granted: 2024-11-24 14:35:00
- Extended: 2024-12-20 10:00:00 (+4 weeks, approved by cfo@company.com)
- Revoked: 2025-02-03 00:00:00 (expired)
- Duration: 71 days

Exception Patterns

Different situations need different exception patterns:

Pattern 1: Time-Bound Project Access

Use case: Cross-functional project needs access for defined period.
exception:
  type: "project_access"
  user: "sarah.chen@company.com"
  access: "gitlab:group:billing-system-rewrite"
  justification: "Sales Engineer supporting billing system rewrite to ensure sales workflow integration"
  project_id: "proj-billing-rewrite-2025"
  start_date: "2024-12-01"
  end_date: "2025-03-31"
  approver: "cto@company.com"
Characteristics: Clear start and end dates. Tied to a project. Auto-revoke on end date. Review at project milestones.

Pattern 2: Incremental Privilege Escalation

Use case: User needs higher privilege temporarily—debugging production issue, emergency access.
exception:
  type: "privilege_escalation"
  user: "john.doe@company.com"
  access: "aws:role:production-admin"
  justification: "Critical production incident #1234 - database corruption requiring direct access"
  incident_id: "INC-1234"
  duration: "4 hours"
  approver: "oncall-lead@company.com"
  auto_revoke: true
Characteristics: Very short duration (hours, not weeks). Tied to incident or emergency. Auto-revoke (no manual renewal). Elevated approval (on-call lead, not just manager).

Pattern 3: Learning and Training

Use case: User learning a new skill needs access to practice.
exception:
  type: "training"
  user: "jane.smith@company.com"
  access: "aws:sandbox-account"
  justification: "AWS Solutions Architect certification training - needs sandbox for hands-on practice"
  training_program: "AWS SA Certification"
  duration: "12 weeks"
  approver: "manager@company.com"
Characteristics: Medium duration (weeks to months). Tied to training program. Lower-risk access (sandbox, not production). May convert to permanent if role changes.

Pattern 4: Onboarding Overlap

Use case: New role needs old role access temporarily during transition.
exception:
  type: "role_transition"
  user: "sarah.chen@company.com"
  access: "salesforce:profile:sales-engineer"
  justification: "Recently promoted to Engineering Manager. Need Salesforce access for 30 days to hand off customer accounts."
  old_role: "Sales Engineer"
  new_role: "Engineering Manager"
  transition_period: "30 days"
  auto_approved: true  # Policy allows 30-day overlap
Characteristics: Automatically granted during role transitions. Defined overlap period (policy-based). No manual approval needed (pre-approved pattern). Hard expiration (no extension).

Pattern 5: Vendor/Contractor Access

Use case: External person needs temporary access.
exception:
  type: "vendor_access"
  user: "consultant@external.com"
  access: "aws:role:security-audit-readonly"
  justification: "Annual security audit by Acme Security Consulting"
  vendor: "Acme Security Consulting"
  contract_id: "CTR-2024-089"
  duration: "2 weeks"
  approver: "ciso@company.com"
  restrictions:
    - ip_allowlist: ["203.0.113.0/24"]
    - mfa_required: true
    - session_duration: "8 hours"
Characteristics: Tied to contract. Additional restrictions (IP allowlist, MFA, session limits). High-level approval (CISO). Strict monitoring.

Exception Anti-Patterns

Anti-Pattern 1: Exceptions Without Expiration

Bad:
exception:
  user: "sarah.chen@company.com"
  access: "finance-reports"
  justification: "Commission analysis project"
  expires_at: null  # No expiration!
Problem: This isn’t an exception. It’s a permanent access grant disguised as an exception. It will never be reviewed. It will accumulate. This defeats the purpose. Fix: All exceptions must have expiration dates. If access is permanent, update the policy.

Anti-Pattern 2: Creating Rulesets for Exceptions

Bad:
User needs finance access temporarily.
→ IT creates "Sales Engineer with Finance Access" Ruleset
→ User added to new Ruleset
→ Project ends, user never removed from Ruleset
→ Ruleset persists forever
Problem: Role explosion. 200 Rulesets within a year. Fix: Use exceptions with expiration. Don’t create permanent Rulesets for temporary needs.

Anti-Pattern 3: Manual Tracking in Spreadsheets

Bad:
IT maintains "Temporary Access Tracker.xlsx"
- User | Access | Granted | Expires | Notes
- Sarah | finance-reports | 11/24 | 1/6 | Commission project
Problem: Spreadsheet isn’t enforced. Sarah’s access doesn’t auto-revoke on 1/6. IT has to remember to manually remove it. This is manual exception management—it doesn’t work. Fix: Build exception management into the access system. Auto-revoke on expiration.

Anti-Pattern 4: No Approval Required

Bad:
User submits exception request.
System auto-grants. No approval.
Problem: Exceptions bypass policy for a reason. They need explicit approval to ensure they’re justified. Fix: Require approval. Even for low-risk access.

Anti-Pattern 5: Extending Exceptions Forever

Bad:
Exception expires.
User requests extension.
IT auto-approves (don't want to block work).
Exception extended.
Repeat every 30 days forever.
Problem: The exception has become permanent. If it’s permanent, update the policy or create a proper Ruleset. Fix: Limit extensions (max 2) or require escalating approval for extensions beyond original duration.

Integrating Exceptions with Policy-Based Access

Policy-based access answers: “What should this person have based on their role?” Exception management answers: “What does this person have that’s outside their role, and why?”

Architecture:

┌─────────────────────────────────────┐
│ User Attributes (from HRIS)         │
│ - job_title: Sales Engineer         │
│ - department: Sales                 │
└──────────────┬──────────────────────┘


┌─────────────────────────────────────┐
│ Policy Engine                        │
│ "Sales Engineer" → Required Access  │
└──────────────┬──────────────────────┘


┌─────────────────────────────────────┐
│ Expected Access (from Policy)        │
│ - salesforce:sales-engineer          │
│ - gitlab:customer-solutions          │
│ - slack:#sales-team                  │
└──────────────┬──────────────────────┘


┌─────────────────────────────────────┐
│ Active Exceptions                    │
│ + finance-reports (temp, expires 1/6)│
└──────────────┬──────────────────────┘


┌─────────────────────────────────────┐
│ Actual Provisioned Access            │
│ = Policy Access + Exception Access   │
└─────────────────────────────────────┘
When calculating what someone should have:
def calculate_total_access(user):
    # Policy-based access
    policy_access = policy_engine.calculate_access(user)

    # Exception-based access
    exception_access = get_active_exceptions(user)

    # Combine
    total_access = policy_access + exception_access

    return total_access
When detecting drift:
def detect_drift(user):
    expected = calculate_total_access(user)  # Policy + Exceptions
    actual = fetch_current_access(user)

    drift = compare(expected, actual)

    if drift:
        # User has access not in policy AND not in exceptions
        report_drift(user, drift)
The separation between policy-based and exception-based access creates clear audit categories. Policy access demonstrates baseline controls; exception access demonstrates controlled deviation with documented justification. This structure satisfies SOC 2 CC6.3 (role-based access) while maintaining the flexibility auditors understand is necessary for business operations.

Exception Metrics and Reporting

Track these metrics:
1

Exception Volume

How many active exceptions? How many new exceptions per month? Trend: increasing or decreasing? Target: Exceptions should be less than 5% of total access. If higher, policies are too narrow.
2

Exception Duration

Average duration. Distribution (1 week vs. 12 weeks vs. 6 months). Target: Most exceptions under 30 days. If many exceed 90 days, consider updating policies.
3

Exception Approval Time

Time from request to approval. Approval rate (% approved vs. denied). Target: Under 24 hours for approval. Over 90% approval rate (if lower, requests aren’t justified or approvers are too strict).
4

Exception Expiration Compliance

Percentage of exceptions that expire on time. Percentage extended. Percentage manually revoked. Target: Over 95% expire on time. Under 20% extended. Under 5% manually revoked.
5

Most Common Exceptions

Which resources are requested most often? Which users request exceptions most often? Insight: If the same exception is requested repeatedly, consider adding it to policy.
Example report:
Exception Report - November 2024

Active Exceptions: 23
New This Month: 14
Expired This Month: 18

Most Requested Resources:
1. finance-reports (5 requests)
2. aws:prod-readonly (4 requests)
3. gitlab:platform-engineering (3 requests)

Recommendation:
- finance-reports is frequently requested by Sales for commission analysis.
  Consider creating "Sales with Finance Reporting" policy.

- aws:prod-readonly is requested by Engineers for debugging.
  Consider adding prod-readonly to Senior Engineer policy.

Exception Review Cadence

Monthly: Review active exceptions expiring in next 30 days. Confirm they’re still needed. Quarterly: Review all exceptions granted in past 90 days. Identify patterns. Update policies where appropriate. Annually: Audit exception history. Calculate metrics. Identify trends. Present to leadership.

The Bottom Line

Policy-based access is powerful but rigid. Exceptions provide the flexibility organizations need without sacrificing governance. Good exception management: Explicit justification. Appropriate approval. Defined expiration. Auto-revocation. Clear audit trail. Trackable metrics. Bad exception management: Manual tracking (spreadsheets). No expiration. Auto-approval. Creating Rulesets for temporary access. Extensions without review. If 95% of access is policy-based and 5% is exceptions, the organization is in a good place. If 20%+ is exceptions, policies are too narrow or common patterns aren’t being converted to policy. Exceptions aren’t a failure of policy-based access. They’re a necessary component. Build them properly from day one.