<!-- Copyright (c) 2026 defconxt. All rights reserved. -->
<!-- Licensed under AGPL-3.0 — see LICENSE file for details. -->
---
name: implementing-just-in-time-access
description: >-
  Implement Just-in-Time (JIT) access provisioning to eliminate standing
  privileges. Covers Azure AD PIM activation workflows, AWS IAM session
  policies, HashiCorp Vault dynamic secrets, time-bound role assignments,
  and approval-based elevation with audit trails.
domain: cybersecurity
subdomain: identity-access-management
tags:
  - jit-access
  - privileged-identity-management
  - azure-pim
  - aws-iam
  - zero-standing-privileges
  - least-privilege
  - vault
version: "1.0"
author: defconxt
license: AGPL-3.0
metadata:
  mitre-attack: ["T1078"]
---

# Implementing Just-in-Time Access

## Overview

Just-in-Time (JIT) access eliminates standing privileges by granting elevated
permissions only when needed, for a bounded duration, with approval and audit.
This reduces the attack window for compromised accounts from indefinite to
minutes/hours. JIT is a core zero trust control — if standing admin access
exists, assume it will be abused.

Mode: `[MODE: ARCHITECT]` for JIT design; `[MODE: BLUE]` for monitoring JIT activation.

MITRE ATT&CK: T1078.004 (Cloud Accounts), T1098 (Account Manipulation)

## Prerequisites

- Azure AD P2 license (Privileged Identity Management)
- AWS IAM with STS and session policies
- HashiCorp Vault (for dynamic secrets)
- PowerShell with Microsoft.Graph module
- Python 3.10+ for agent tooling

## Key Concepts

### JIT Access Patterns

| Pattern | Description | Duration |
|---------|-------------|----------|
| Azure PIM Eligible | Role assigned as eligible, requires activation | 1-8 hours |
| AWS STS AssumeRole | Temporary credentials with session policy | 15 min-12 hours |
| Vault Dynamic Secrets | Credentials generated on demand, auto-revoked | Configurable TTL |
| Okta Entitlement Mgmt | Group membership granted on approval, auto-expires | 1-24 hours |
| ServiceNow + SCIM | Ticket-driven provisioning with auto-deprovision | Ticket duration |

### Azure AD PIM Configuration

```powershell
# Connect to Microsoft Graph
Connect-MgGraph -Scopes "RoleManagement.ReadWrite.Directory"

# List eligible role assignments
Get-MgRoleManagementDirectoryRoleEligibilityScheduleInstance |
  Select-Object PrincipalId, RoleDefinitionId, StartDateTime, EndDateTime

# Create eligible assignment (not active — requires activation)
$params = @{
    Action = "adminAssign"
    PrincipalId = "user-object-id"
    RoleDefinitionId = "role-definition-id"
    DirectoryScopeId = "/"
    Justification = "JIT eligible assignment for incident response"
    ScheduleInfo = @{
        StartDateTime = (Get-Date).ToUniversalTime()
        Expiration = @{
            Type = "AfterDuration"
            Duration = "P90D"
        }
    }
}
New-MgRoleManagementDirectoryRoleEligibilityScheduleRequest -BodyParameter $params

# Configure PIM role settings (require approval, MFA, justification)
$settingsParams = @{
    RoleDefinitionId = "role-definition-id"
    Rules = @(
        @{
            Id = "Approval_EndUser_Assignment"
            RuleType = "#microsoft.graph.unifiedRoleManagementPolicyApprovalRule"
            Setting = @{
                IsApprovalRequired = $true
                ApprovalStages = @(@{
                    PrimaryApprovers = @(@{
                        OdataType = "#microsoft.graph.singleUser"
                        UserId = "approver-object-id"
                    })
                })
            }
        }
    )
}
```

### AWS JIT with STS

```bash
# Create role with session duration limit
aws iam create-role \
  --role-name JIT-IncidentResponder \
  --max-session-duration 3600 \
  --assume-role-policy-document '{
    "Version": "2012-10-17",
    "Statement": [{
      "Effect": "Allow",
      "Principal": {"AWS": "arn:aws:iam::ACCOUNT:root"},
      "Action": "sts:AssumeRole",
      "Condition": {
        "Bool": {"aws:MultiFactorAuthPresent": "true"},
        "NumericLessThan": {"aws:MultiFactorAuthAge": "300"}
      }
    }]
  }'

# Assume role with inline session policy (further restrict)
aws sts assume-role \
  --role-arn arn:aws:iam::ACCOUNT:role/JIT-IncidentResponder \
  --role-session-name "incident-$(date +%s)" \
  --duration-seconds 3600 \
  --policy '{
    "Version": "2012-10-17",
    "Statement": [{
      "Effect": "Allow",
      "Action": ["ec2:DescribeInstances", "ec2:StopInstances"],
      "Resource": "*",
      "Condition": {"StringEquals": {"ec2:ResourceTag/Environment": "production"}}
    }]
  }'
```

### Vault Dynamic Secrets

```bash
# Enable database secrets engine
vault secrets enable database

# Configure dynamic credentials with 1-hour TTL
vault write database/config/prod-db \
  plugin_name=mysql-database-plugin \
  connection_url="{{username}}:{{password}}@tcp(db.internal:3306)/" \
  allowed_roles="readonly" \
  username="vault-admin" \
  password="VAULT_DB_PASSWORD"

vault write database/roles/readonly \
  db_name=prod-db \
  creation_statements="CREATE USER '{{name}}'@'%' IDENTIFIED BY '{{password}}'; \
    GRANT SELECT ON prod.* TO '{{name}}'@'%';" \
  default_ttl="1h" \
  max_ttl="4h"

# Request JIT credentials (auto-revoked after TTL)
vault read database/creds/readonly
```

## Workflow

1. **Inventory** — Identify all standing privileged access across IdPs
2. **Classify** — Map roles by blast radius (Global Admin > Resource Admin > Reader)
3. **Convert** — Move permanent assignments to eligible/JIT assignments
4. **Configure** — Set activation requirements (MFA, approval, justification, duration)
5. **Monitor** — Alert on activations, track usage, flag unused activations
6. **Review** — Quarterly access review of eligible assignments

## Detection

```yaml
title: Just In Time Access Detection
id: bd009214-1d90-4569-a148-b33df884f020
status: experimental
description: Detects suspicious activity related to implementing just in time access techniques in identity access management context
logsource:
  category: authentication
  product: windows
detection:
  selection:
    EventType: authentication
    Status: failure
  condition: selection
level: medium
tags:
  - attack.t1078
  - attack.credential_access
falsepositives:
  - Automated password rotation by privileged access management tools
```

## Verification

- [ ] Zero standing Global Administrator assignments in Azure AD
- [ ] PIM activation requires MFA + justification for all privileged roles
- [ ] Maximum activation duration ≤ 8 hours for sensitive roles
- [ ] AWS privileged roles require MFA for AssumeRole
- [ ] Vault dynamic secrets configured with appropriate TTLs
- [ ] Activation logs forwarded to SIEM with < 5 min latency
- [ ] Quarterly access review process documented and scheduled
- [ ] Emergency break-glass procedure documented and tested

## References

- [Azure AD Privileged Identity Management](https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/)
- [AWS STS AssumeRole](https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRole.html)
- [HashiCorp Vault Dynamic Secrets](https://developer.hashicorp.com/vault/docs/secrets/databases)
- [NIST SP 800-53 AC-2 — Account Management](https://csf.tools/reference/nist-sp-800-53/r5/ac/ac-2/)
- [MITRE ATT&CK T1078.004](https://attack.mitre.org/techniques/T1078/004/)
