<!-- Copyright (c) 2026 defconxt. All rights reserved. -->
<!-- Licensed under AGPL-3.0 — see LICENSE file for details. -->
---
name: automating-user-access-reviews
description: >-
  Automate user access review (UAR) workflows including privilege enumeration,
  entitlement comparison against role baselines, orphaned account detection,
  SoD violation identification, and certification report generation for
  compliance with SOX, HIPAA, and ISO 27001.
domain: cybersecurity
subdomain: automation-scripting
tags:
  - access-review
  - iam
  - rbac
  - sod-violations
  - compliance
  - sox
  - identity-governance
version: "1.0"
author: defconxt
license: AGPL-3.0
metadata:
  mitre-attack: ["T1087"]
---

# Automating User Access Reviews

## Overview

Quarterly access reviews are tedious and error-prone when done manually. This
skill covers automating the entire UAR lifecycle: pull entitlements from IAM
sources, compare against approved role baselines, flag excessive privileges,
detect orphaned accounts, identify SoD violations, and generate certification
reports for auditors.

Mode: `[MODE: BLUE]` — Defensive identity governance with compliance focus.

## Prerequisites

| Requirement | Details |
|---|---|
| Python 3.10+ with `ldap3`, `requests` | Required |
| LDAP/AD access for entitlement enumeration | Required |
| HR system API for employee status validation | Required |
| Role baseline definitions in JSON/YAML | Required |

## Key Concepts

### Entitlement Extraction from AD

```python
from ldap3 import Server, Connection, ALL

def get_user_groups(ldap_host: str, base_dn: str, bind_dn: str, password: str) -> list[dict]:
    """Extract all user-to-group mappings from Active Directory."""
    server = Server(ldap_host, get_info=ALL)
    conn = Connection(server, bind_dn, password, auto_bind=True)
    conn.search(
        base_dn,
        "(objectClass=user)",
        attributes=["sAMAccountName", "memberOf", "userAccountControl", "lastLogonTimestamp"],
    )
    users = []
    for entry in conn.entries:
        groups = [str(g).split(",")[0].replace("CN=", "") for g in (entry.memberOf or [])]
        users.append({
            "username": str(entry.sAMAccountName),
            "groups": groups,
            "disabled": bool(int(str(entry.userAccountControl or 0)) & 0x2),
        })
    conn.unbind()
    return users
```

### Separation of Duties Check

```python
SOD_MATRIX = {
    "Accounts Payable": ["Accounts Receivable", "Treasury"],
    "System Admin": ["Security Admin", "Audit"],
    "Developer": ["Production Deploy", "DBA"],
}

def check_sod_violations(user: str, groups: list[str]) -> list[dict]:
    """Check user entitlements against SoD conflict matrix."""
    violations = []
    for group in groups:
        conflicts = SOD_MATRIX.get(group, [])
        for conflict in conflicts:
            if conflict in groups:
                violations.append({
                    "user": user,
                    "role_a": group,
                    "role_b": conflict,
                    "severity": "high",
                })
    return violations
```

### Orphaned Account Detection

```python
def find_orphaned_accounts(
    ad_users: list[dict], hr_active: set[str]
) -> list[dict]:
    """Find AD accounts without corresponding active HR records."""
    orphaned = []
    for user in ad_users:
        username = user["username"].lower()
        if username not in hr_active and not user.get("disabled"):
            orphaned.append({
                "username": user["username"],
                "groups": user["groups"],
                "risk": "high" if any(g in user["groups"] for g in ["Domain Admins", "Enterprise Admins"]) else "medium",
            })
    return orphaned
```

## Workflow

### Step 1: Extract and Analyze Entitlements

```bash
node scripts/agent.js --action enumerate --entitlements-file /tmp/ad_export.json
```

### Step 2: Check SoD Violations

```bash
node scripts/agent.js --action sod-check --entitlements-file /tmp/ad_export.json
```

### Step 3: Detect Orphaned Accounts

```bash
node scripts/agent.js --action orphan-check --entitlements-file /tmp/ad_export.json --hr-file /tmp/hr_active.json
```

## Verification

- [ ] Entitlement extraction captures all user-group mappings
- [ ] SoD matrix correctly flags conflicting role pairs
- [ ] Orphaned account detection compares AD against HR roster
- [ ] Certification report includes remediation recommendations
- [ ] Exit code 0 on clean review, 1 on violations found, 2 on error

## References

- [NIST SP 800-53 AC-2 — Account Management](https://csrc.nist.gov/publications/detail/sp/800-53/rev-5/final)
- [CIS Control 5 — Account Management](https://www.cisecurity.org/controls/account-management)
- [ISO 27001 A.9.2.5 — Review of User Access Rights](https://www.iso.org/standard/27001)
- [SOX Section 404 — Internal Controls](https://www.sec.gov/spotlight/sarbanes-oxley.htm)
