identity access management

Performing Access Review and Certification

Conduct systematic access reviews and certifications to ensure users have appropriate access rights aligned with their roles. This skill covers review campaign design, reviewer selection, risk-based prioritization, micro-certification strategies, and remediation tracking for compliance with SOX, HIPAA, and PCI DSS requirements.

access-controlaccess-reviewcertificationcompliancegovernanceiamidentity
Install this skill
npx skills add mukul975/Anthropic-Cybersecurity-Skills
Framework mappings

Overview

Conduct systematic access reviews and certifications to ensure users have appropriate access rights aligned with their roles. This skill covers review campaign design, reviewer selection, risk-based prioritization, micro-certification strategies, and remediation tracking for compliance with SOX, HIPAA, and PCI DSS requirements.

When to Use

  • When conducting security assessments that involve performing access review and certification
  • When following incident response procedures for related security events
  • When performing scheduled security testing or auditing activities
  • When validating security controls through hands-on testing

Prerequisites

  • Familiarity with identity access management concepts and tools
  • Access to a test or lab environment for safe execution
  • Python 3.8+ with required dependencies installed
  • Appropriate authorization for any testing activities

Objectives

  • Design and execute access review campaigns across enterprise applications
  • Implement risk-based prioritization for review scope
  • Configure reviewer selection (manager, application owner, hybrid)
  • Automate entitlement data collection and presentation
  • Track remediation of inappropriate access findings
  • Generate compliance evidence for auditors

Key Concepts

Access Review Types

  1. User Access Review: Manager certifies all entitlements for their direct reports
  2. Entitlement Review: Application owner certifies all users with specific entitlement
  3. Role Review: Role owner certifies role membership and permissions
  4. Privileged Access Review: Security team reviews high-risk/privileged access
  5. SOD Review: Verify no users have conflicting separation-of-duty violations

Risk-Based Prioritization

  • High Risk: Privileged access, financial systems, PII/PHI systems, external-facing apps
  • Medium Risk: Internal business applications, shared drives, collaboration tools
  • Low Risk: Standard employee tools, read-only access, public information systems

Review Campaign Lifecycle

  1. Planning: Define scope, reviewers, timeline, escalation
  2. Data Collection: Aggregate entitlements from all identity sources
  3. Distribution: Assign review items to appropriate certifiers
  4. Certification: Reviewers approve or revoke each entitlement
  5. Remediation: Revoke inappropriate access, enforce timeline
  6. Reporting: Generate compliance evidence and metrics
  7. Closure: Archive campaign, feed findings into next cycle

Workflow

Step 1: Define Review Scope and Schedule

  • Identify in-scope applications and systems
  • Determine review frequency: quarterly (SOX), semi-annual, annual
  • Define campaign timeline: review period, escalation dates, hard close
  • Establish escalation chain for non-responsive reviewers

Step 2: Data Collection and Aggregation

  • Extract user-entitlement mappings from each application
  • Correlate with HR data (active employees, role, department, manager)
  • Identify terminated/transferred users still holding access
  • Flag high-risk entitlements (admin, DBA, system, privileged)
  • Calculate risk scores based on entitlement sensitivity and user role

Step 3: Reviewer Assignment

  • Manager Reviews: Direct manager certifies subordinate access
  • Application Owner Reviews: App owner certifies all users of their application
  • Hybrid Model: Manager reviews standard access, app owner reviews privileged
  • Delegate Management: Allow reviewers to delegate with audit trail

Step 4: Execute Certification Campaign

  • Send notifications to reviewers with clear instructions
  • Present entitlements with context (last used date, risk level, role justification)
  • Require reviewers to explicitly approve or revoke each item
  • Track completion percentage and send reminders
  • Escalate to management after deadline

Step 5: Remediation and Tracking

  • Automatically ticket revocations to IT operations
  • Set SLA for revocation execution (24-48 hours for high-risk)
  • Verify revocation completed (re-check entitlement)
  • Exception management for business-justified deviations
  • Document all exceptions with expiration dates

Step 6: Reporting and Evidence

  • Generate campaign completion metrics
  • Produce per-application compliance reports
  • Create audit-ready evidence packages
  • Track trends across review cycles
  • Feed findings into risk assessment process

Security Controls

Control NIST 800-53 Description
Access Review AC-2(3) Periodic review of account privileges
Account Management AC-2 Account lifecycle management
Least Privilege AC-6 Minimum necessary access enforcement
Separation of Duties AC-5 SOD conflict identification
Audit Logging AU-6 Review of access audit records

Common Pitfalls

  • Rubber-stamping: reviewers approving all access without examination
  • Incomplete scope: missing critical applications from review campaigns
  • No remediation tracking: revoking access on paper but not in systems
  • Inconsistent reviewer assignment causing gaps in coverage
  • Not including service accounts and non-human identities

Verification

  • All in-scope applications included in campaign
  • Reviewers assigned for 100% of entitlements
  • Campaign completion rate exceeds 95%
  • Revocations executed within SLA
  • Audit evidence package complete and archived
  • SOD violations identified and documented
  • Exceptions documented with business justification and expiry
Source materials

References and resources

Everything below is rendered for inspection. Script files are read-only and never run.

References 3

api-reference.md1.4 KB

API Reference: Access Review and Certification

CSV Input Format

username,entitlement,application,manager,status,last_used,risk_score
jsmith,Admin,SAP,mjones,active,2025-01-15T00:00:00Z,8

SoD Rules JSON Format

[{"name": "Finance SoD", "role_a": "AP_Approver", "role_b": "AP_Creator"}]

Key Review Checks

Check Description Severity
Orphaned accounts No manager or terminated status HIGH
SoD violations Conflicting entitlements held CRITICAL
Excessive access Entitlement count above threshold MEDIUM
Stale entitlements Unused beyond retention period MEDIUM

Compliance Frameworks

Framework Requirement
SOX Section 404 Periodic access reviews for financial systems
SOC 2 CC6.1 Logical access controls and reviews
HIPAA 164.312(a) Access authorization and review
PCI DSS 7.2 Restrict access based on need-to-know

Review Campaign Design

Parameter Best Practice
Frequency Quarterly for privileged, semi-annual for standard
Reviewer Direct manager + application owner
Escalation Auto-revoke if no response within 14 days
Evidence Export decisions with timestamps and reviewer ID

References

standards.md1.0 KB

Standards and References - Access Review and Certification

NIST Standards

  • NIST SP 800-53 Rev 5:
    • AC-2: Account Management (periodic review requirement)
    • AC-2(3): Disable accounts after inactivity period
    • AC-5: Separation of Duties
    • AC-6: Least Privilege
    • AC-6(7): Review of User Privileges
    • AU-6: Audit Record Review, Analysis, and Reporting
  • NIST SP 800-171: 3.1.1 Authorized Access Control, 3.1.2 Transaction Control

Compliance Requirements

  • SOX Section 404: Quarterly access reviews for financial systems
  • PCI DSS 4.0: Requirement 7.2.5 - Review all access at least every six months
  • HIPAA Security Rule: 45 CFR 164.312(a)(1) - Access control review
  • ISO 27001: A.9.2.5 Review of user access rights
  • GDPR Article 5(1)(f): Integrity and confidentiality of processing

Industry Frameworks

  • CIS Controls v8: Control 6.2 - Establish an Access Revoking Process
  • COBIT 2019: DSS05.04 - Manage user identity and logical access
  • IGA Market: SailPoint, Saviynt, One Identity, Omada
workflows.md2.3 KB

Access Review and Certification Workflows

Workflow 1: Quarterly Access Review Campaign

Timeline:

  • Week 1: Data collection and campaign configuration
  • Week 2-4: Active review period
  • Week 5: Escalation for non-responsive reviewers
  • Week 6: Hard close and remediation initiation
  • Week 7-8: Remediation execution and verification
  • Week 8: Campaign closure and reporting

Steps:

  1. Extract entitlement data from all in-scope systems
  2. Correlate with HR data for active/inactive status
  3. Calculate risk scores for each user-entitlement pair
  4. Assign reviewers based on reviewer model
  5. Launch campaign with notifications
  6. Monitor completion daily, send reminders at 50% and 75% of timeline
  7. Escalate to VP level at deadline for incomplete reviews
  8. Force-close with auto-revoke or manager-override at hard deadline
  9. Process revocations through ticketing system
  10. Verify revocations completed in target systems
  11. Generate compliance report and evidence package

Workflow 2: Triggered Access Review (Role Change)

Steps:

  1. HR system notifies of employee role change (transfer, promotion)
  2. System identifies current access vs. new role entitlements
  3. Birthright access for new role automatically provisioned
  4. Legacy access flagged for new manager review
  5. New manager certifies which legacy access to retain/revoke
  6. Retained access documented with justification
  7. Revoked access removed within SLA

Workflow 3: Privileged Access Micro-Certification

Steps:

  1. Weekly extraction of privileged entitlements
  2. Privileged access grouped by system owner
  3. System owner reviews new privileged access grants since last certification
  4. Each privileged entitlement requires explicit approval with justification
  5. Non-certified privileged access auto-revoked after 48 hours
  6. Results forwarded to security team for trending

Workflow 4: SOD Violation Detection and Resolution

Steps:

  1. Define SOD rule matrix (e.g., AP create vs. AP approve)
  2. Scan entitlements against SOD rules
  3. Flag violations with risk level
  4. Route violations to compliance team
  5. Compliance team evaluates: revoke access or approve compensating control
  6. If compensating control: document control, set review frequency, assign monitor
  7. If revoke: process access removal and verify

Scripts 2

agent.py5.4 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""Agent for conducting access review and certification using identity governance APIs."""

import json
import argparse
import csv
from datetime import datetime, timezone, timedelta


def load_access_data(csv_path):
    """Load access entitlement data from CSV export."""
    with open(csv_path) as f:
        reader = csv.DictReader(f)
        data = list(reader)
    print(f"[*] Loaded {len(data)} entitlement records from {csv_path}")
    return data


def identify_orphaned_accounts(records):
    """Find accounts with no manager or terminated status."""
    findings = []
    for r in records:
        if not r.get("manager") or r.get("status", "").lower() == "terminated":
            findings.append({"user": r.get("username"), "status": r.get("status"),
                             "manager": r.get("manager", "NONE"), "severity": "HIGH",
                             "issue": "Orphaned/terminated account with active access"})
    print(f"\n[*] Orphaned/terminated accounts: {len(findings)}")
    for f in findings[:10]:
        print(f"  [!] {f['user']} (status={f['status']}, manager={f['manager']})")
    return findings


def check_sod_violations(records, sod_rules):
    """Check for separation of duties violations."""
    user_entitlements = {}
    for r in records:
        user = r.get("username", "")
        ent = r.get("entitlement", "")
        user_entitlements.setdefault(user, set()).add(ent)
    findings = []
    for user, ents in user_entitlements.items():
        for rule in sod_rules:
            if rule["role_a"] in ents and rule["role_b"] in ents:
                findings.append({"user": user, "conflict": f"{rule['role_a']} + {rule['role_b']}",
                                 "severity": "CRITICAL", "rule": rule.get("name", "")})
    print(f"\n[*] SoD violations: {len(findings)}")
    for f in findings[:10]:
        print(f"  [!] {f['user']}: {f['conflict']}")
    return findings


def identify_excessive_access(records, threshold=10):
    """Find users with entitlement counts above threshold."""
    user_counts = {}
    for r in records:
        user = r.get("username", "")
        user_counts[user] = user_counts.get(user, 0) + 1
    excessive = [{"user": u, "count": c, "severity": "MEDIUM"}
                 for u, c in user_counts.items() if c > threshold]
    excessive.sort(key=lambda x: -x["count"])
    print(f"\n[*] Users with >{threshold} entitlements: {len(excessive)}")
    for e in excessive[:10]:
        print(f"  [!] {e['user']}: {e['count']} entitlements")
    return excessive


def check_last_used(records, stale_days=90):
    """Find entitlements not used within the stale period."""
    cutoff = datetime.now(timezone.utc) - timedelta(days=stale_days)
    stale = []
    for r in records:
        last_used = r.get("last_used", "")
        if last_used:
            try:
                lu_dt = datetime.fromisoformat(last_used.replace("Z", "+00:00"))
                if lu_dt < cutoff:
                    stale.append({"user": r.get("username"), "entitlement": r.get("entitlement"),
                                  "last_used": last_used, "severity": "MEDIUM"})
            except ValueError:
                pass
    print(f"\n[*] Stale entitlements (>{stale_days} days unused): {len(stale)}")
    return stale


def generate_report(orphaned, sod, excessive, stale, output_path):
    """Generate access review report."""
    report = {"review_date": datetime.now(timezone.utc).isoformat(),
              "summary": {"orphaned_accounts": len(orphaned), "sod_violations": len(sod),
                          "excessive_access": len(excessive), "stale_entitlements": len(stale)},
              "orphaned": orphaned, "sod_violations": sod,
              "excessive_access": excessive[:50], "stale_entitlements": stale[:50]}
    with open(output_path, "w") as f:
        json.dump(report, f, indent=2, default=str)
    total = len(orphaned) + len(sod) + len(excessive) + len(stale)
    print(f"\n[*] Report saved to {output_path} | Total findings: {total}")


def main():
    parser = argparse.ArgumentParser(description="Access Review and Certification Agent")
    parser.add_argument("action", choices=["orphaned", "sod", "excessive", "stale", "full-review"])
    parser.add_argument("--data", required=True, help="CSV file with access entitlements")
    parser.add_argument("--sod-rules", help="JSON file with SoD rules")
    parser.add_argument("--threshold", type=int, default=10, help="Excessive access threshold")
    parser.add_argument("--stale-days", type=int, default=90)
    parser.add_argument("-o", "--output", default="access_review.json")
    args = parser.parse_args()

    records = load_access_data(args.data)
    sod_rules = []
    if args.sod_rules:
        with open(args.sod_rules) as f:
            sod_rules = json.load(f)

    if args.action == "orphaned":
        identify_orphaned_accounts(records)
    elif args.action == "sod":
        check_sod_violations(records, sod_rules)
    elif args.action == "excessive":
        identify_excessive_access(records, args.threshold)
    elif args.action == "stale":
        check_last_used(records, args.stale_days)
    elif args.action == "full-review":
        o = identify_orphaned_accounts(records)
        s = check_sod_violations(records, sod_rules)
        e = identify_excessive_access(records, args.threshold)
        st = check_last_used(records, args.stale_days)
        generate_report(o, s, e, st, args.output)


if __name__ == "__main__":
    main()
process.py12.1 KB
Display-only source. This catalog never executes bundled scripts.
#!/usr/bin/env python3
"""
Access Review and Certification Engine

Automates access review campaigns by collecting entitlement data,
assigning reviewers, tracking certification decisions, generating
compliance reports, and identifying SOD violations.
"""

import json
import datetime
import csv
import io
from typing import Dict, List, Optional, Set, Tuple
from dataclasses import dataclass, field
from collections import defaultdict


@dataclass
class UserEntitlement:
    """A user-to-entitlement mapping for review."""
    user_id: str
    user_name: str
    department: str
    manager: str
    application: str
    entitlement: str
    risk_level: str  # critical, high, medium, low
    last_used: Optional[str] = None
    granted_date: Optional[str] = None
    review_status: str = "pending"  # pending, approved, revoked, escalated
    reviewer: str = ""
    decision_date: Optional[str] = None
    justification: str = ""


@dataclass
class SODRule:
    """Separation of Duties conflict rule."""
    rule_id: str
    description: str
    entitlement_a: str
    application_a: str
    entitlement_b: str
    application_b: str
    severity: str  # critical, high, medium


@dataclass
class CampaignConfig:
    """Access review campaign configuration."""
    campaign_id: str
    name: str
    start_date: str
    end_date: str
    review_model: str  # manager, app_owner, hybrid
    scope_applications: List[str] = field(default_factory=list)
    escalation_days: int = 21
    auto_revoke_unreviewed: bool = False


class AccessReviewEngine:
    """Manages access review and certification campaigns."""

    def __init__(self, config: CampaignConfig):
        self.config = config
        self.entitlements: List[UserEntitlement] = []
        self.sod_rules: List[SODRule] = []
        self.sod_violations: List[Dict] = []

    def load_entitlements(self, entitlements: List[Dict]):
        """Load user-entitlement data for review."""
        for e in entitlements:
            ue = UserEntitlement(**e)
            if not self.config.scope_applications or \
               ue.application in self.config.scope_applications:
                self.entitlements.append(ue)

    def load_sod_rules(self, rules: List[Dict]):
        """Load SOD conflict rules."""
        for r in rules:
            self.sod_rules.append(SODRule(**r))

    def assign_reviewers(self):
        """Assign reviewers based on campaign review model."""
        for ent in self.entitlements:
            if ent.review_status != "pending":
                continue
            if self.config.review_model == "manager":
                ent.reviewer = ent.manager
            elif self.config.review_model == "app_owner":
                ent.reviewer = f"owner_{ent.application}"
            elif self.config.review_model == "hybrid":
                if ent.risk_level in ("critical", "high"):
                    ent.reviewer = f"owner_{ent.application}"
                else:
                    ent.reviewer = ent.manager

    def detect_sod_violations(self) -> List[Dict]:
        """Detect separation of duties violations."""
        self.sod_violations = []
        user_entitlements = defaultdict(list)

        for ent in self.entitlements:
            user_entitlements[ent.user_id].append(ent)

        for user_id, ents in user_entitlements.items():
            for rule in self.sod_rules:
                has_a = any(
                    e.application == rule.application_a and e.entitlement == rule.entitlement_a
                    for e in ents
                )
                has_b = any(
                    e.application == rule.application_b and e.entitlement == rule.entitlement_b
                    for e in ents
                )
                if has_a and has_b:
                    user_name = next(e.user_name for e in ents)
                    self.sod_violations.append({
                        "user_id": user_id,
                        "user_name": user_name,
                        "rule_id": rule.rule_id,
                        "description": rule.description,
                        "severity": rule.severity,
                        "entitlement_a": f"{rule.application_a}:{rule.entitlement_a}",
                        "entitlement_b": f"{rule.application_b}:{rule.entitlement_b}"
                    })

        return self.sod_violations

    def identify_stale_access(self, days_threshold: int = 90) -> List[UserEntitlement]:
        """Identify entitlements not used within threshold."""
        stale = []
        now = datetime.datetime.now()

        for ent in self.entitlements:
            if ent.last_used:
                try:
                    last = datetime.datetime.fromisoformat(ent.last_used)
                    if (now - last).days > days_threshold:
                        stale.append(ent)
                except ValueError:
                    pass
            else:
                stale.append(ent)

        return stale

    def identify_orphaned_access(self, active_users: Set[str]) -> List[UserEntitlement]:
        """Identify entitlements belonging to inactive/terminated users."""
        return [e for e in self.entitlements if e.user_id not in active_users]

    def process_decision(self, user_id: str, application: str, entitlement: str,
                         decision: str, justification: str = ""):
        """Process a reviewer's certification decision."""
        for ent in self.entitlements:
            if (ent.user_id == user_id and ent.application == application and
                    ent.entitlement == entitlement):
                ent.review_status = decision
                ent.decision_date = datetime.datetime.now().isoformat()
                ent.justification = justification
                break

    def get_campaign_metrics(self) -> Dict:
        """Calculate campaign progress metrics."""
        total = len(self.entitlements)
        if total == 0:
            return {"total": 0, "completion_rate": 0}

        by_status = defaultdict(int)
        by_risk = defaultdict(lambda: defaultdict(int))
        by_reviewer = defaultdict(lambda: {"total": 0, "completed": 0})

        for ent in self.entitlements:
            by_status[ent.review_status] += 1
            by_risk[ent.risk_level][ent.review_status] += 1
            by_reviewer[ent.reviewer]["total"] += 1
            if ent.review_status in ("approved", "revoked"):
                by_reviewer[ent.reviewer]["completed"] += 1

        completed = by_status.get("approved", 0) + by_status.get("revoked", 0)
        revocation_rate = by_status.get("revoked", 0) / max(completed, 1) * 100

        return {
            "total": total,
            "pending": by_status.get("pending", 0),
            "approved": by_status.get("approved", 0),
            "revoked": by_status.get("revoked", 0),
            "escalated": by_status.get("escalated", 0),
            "completion_rate": round(completed / total * 100, 1),
            "revocation_rate": round(revocation_rate, 1),
            "by_risk": dict(by_risk),
            "sod_violations": len(self.sod_violations),
            "reviewer_progress": {k: v for k, v in by_reviewer.items()}
        }

    def generate_compliance_report(self) -> str:
        """Generate compliance-ready access review report."""
        metrics = self.get_campaign_metrics()
        stale = self.identify_stale_access()

        lines = [
            "=" * 70,
            "ACCESS REVIEW AND CERTIFICATION REPORT",
            "=" * 70,
            f"Campaign: {self.config.name} ({self.config.campaign_id})",
            f"Period: {self.config.start_date} to {self.config.end_date}",
            f"Review Model: {self.config.review_model}",
            f"Report Generated: {datetime.datetime.now().isoformat()}",
            "-" * 70,
            "",
            "CAMPAIGN METRICS",
            f"  Total Entitlements Reviewed: {metrics['total']}",
            f"  Completion Rate: {metrics['completion_rate']}%",
            f"  Approved: {metrics['approved']}",
            f"  Revoked: {metrics['revoked']}",
            f"  Pending: {metrics['pending']}",
            f"  Escalated: {metrics['escalated']}",
            f"  Revocation Rate: {metrics['revocation_rate']}%",
            f"  Stale Access Items: {len(stale)}",
            f"  SOD Violations: {metrics['sod_violations']}",
            ""
        ]

        if self.sod_violations:
            lines.append("SOD VIOLATIONS:")
            lines.append("-" * 40)
            for v in self.sod_violations:
                lines.append(f"  [{v['severity'].upper()}] {v['user_name']} ({v['user_id']})")
                lines.append(f"    Rule: {v['description']}")
                lines.append(f"    Conflict: {v['entitlement_a']} <-> {v['entitlement_b']}")
            lines.append("")

        # Reviewer progress
        lines.append("REVIEWER PROGRESS:")
        lines.append("-" * 40)
        for reviewer, progress in metrics["reviewer_progress"].items():
            pct = round(progress["completed"] / max(progress["total"], 1) * 100, 1)
            lines.append(f"  {reviewer}: {progress['completed']}/{progress['total']} ({pct}%)")
        lines.append("")

        # Revoked access details
        revoked = [e for e in self.entitlements if e.review_status == "revoked"]
        if revoked:
            lines.append("REVOKED ACCESS:")
            lines.append("-" * 40)
            for e in revoked:
                lines.append(f"  {e.user_name} - {e.application}:{e.entitlement} [{e.risk_level}]")
            lines.append("")

        lines.append("=" * 70)
        overall = "COMPLIANT" if metrics["completion_rate"] >= 95 else "NON-COMPLIANT"
        lines.append(f"COMPLIANCE STATUS: {overall}")
        lines.append("=" * 70)

        return "\n".join(lines)


def main():
    """Run access review with sample data."""
    config = CampaignConfig(
        campaign_id="AR-2026-Q1",
        name="Q1 2026 Quarterly Access Review",
        start_date="2026-01-01",
        end_date="2026-03-31",
        review_model="hybrid",
        scope_applications=["SAP", "Salesforce", "AWS", "GitHub"]
    )

    engine = AccessReviewEngine(config)

    sample_entitlements = [
        {"user_id": "U001", "user_name": "Alice Johnson", "department": "Finance",
         "manager": "Bob Smith", "application": "SAP", "entitlement": "AP_Create",
         "risk_level": "high", "last_used": "2026-02-20", "granted_date": "2024-06-15"},
        {"user_id": "U001", "user_name": "Alice Johnson", "department": "Finance",
         "manager": "Bob Smith", "application": "SAP", "entitlement": "AP_Approve",
         "risk_level": "critical", "last_used": "2026-02-18", "granted_date": "2025-01-10"},
        {"user_id": "U002", "user_name": "Charlie Brown", "department": "Engineering",
         "manager": "Diana Prince", "application": "AWS", "entitlement": "AdminAccess",
         "risk_level": "critical", "last_used": "2025-10-01", "granted_date": "2024-03-20"},
        {"user_id": "U003", "user_name": "Eve Wilson", "department": "Sales",
         "manager": "Frank Castle", "application": "Salesforce", "entitlement": "Standard_User",
         "risk_level": "low", "last_used": "2026-02-22", "granted_date": "2025-08-01"},
        {"user_id": "U004", "user_name": "Grace Lee", "department": "Engineering",
         "manager": "Diana Prince", "application": "GitHub", "entitlement": "Org_Admin",
         "risk_level": "high", "last_used": "2026-02-21", "granted_date": "2025-05-15"},
    ]

    sod_rules = [
        {"rule_id": "SOD-001", "description": "AP Create and AP Approve conflict",
         "entitlement_a": "AP_Create", "application_a": "SAP",
         "entitlement_b": "AP_Approve", "application_b": "SAP",
         "severity": "critical"}
    ]

    engine.load_entitlements(sample_entitlements)
    engine.load_sod_rules(sod_rules)
    engine.assign_reviewers()
    engine.detect_sod_violations()

    # Simulate some decisions
    engine.process_decision("U001", "SAP", "AP_Create", "approved", "Required for daily AP processing")
    engine.process_decision("U002", "AWS", "AdminAccess", "revoked", "Stale access - user no longer needs admin")
    engine.process_decision("U003", "Salesforce", "Standard_User", "approved", "Active sales team member")

    report = engine.generate_compliance_report()
    print(report)


if __name__ == "__main__":
    main()

Assets 1

template.mdtext/markdown · 1.3 KB
Keep exploring