Initial commit - 611 cybersecurity skills across all subdomains

This commit is contained in:
mukul975
2026-02-25 10:47:44 +01:00
commit 22a7ab1462
1765 changed files with 280648 additions and 0 deletions
@@ -0,0 +1,98 @@
---
name: None
description: Implement Just-In-Time (JIT) access provisioning to eliminate standing privileges by granting temporary, time-bound access only when needed. This skill covers JIT architecture design, approval workflo
domain: cybersecurity
subdomain: identity-access-management
tags: [iam, identity, access-control, jit, provisioning, zero-trust, least-privilege]
version: "1.0"
author: mahipal
license: MIT
---
# Implementing Just-In-Time Access Provisioning
## Overview
Implement Just-In-Time (JIT) access provisioning to eliminate standing privileges by granting temporary, time-bound access only when needed. This skill covers JIT architecture design, approval workflows, automatic expiration, integration with PAM and IGA platforms, and alignment with zero trust principles.
## Objectives
- Design JIT access request and approval workflows
- Implement time-bound access grants with automatic expiration
- Configure risk-based approval routing (auto-approve low-risk, multi-approval for high-risk)
- Integrate JIT with PAM for privileged access elevation
- Monitor and audit all JIT access grants and usage
- Reduce attack surface by eliminating standing privileges
## Key Concepts
### JIT Access Models
1. **Broker and Remove**: Grant access through approval, auto-remove after time window
2. **Elevation on Demand**: User has base access, elevates to privileged upon request
3. **Account Creation/Deletion**: Temporary account created, destroyed after use
4. **Group Membership Toggle**: Add to privileged group temporarily, auto-remove
### Zero Standing Privilege (ZSP) Principle
- No user has permanent privileged access
- All privileged access requires explicit request with business justification
- Access automatically expires after defined time window
- All access events logged and auditable
## Implementation Steps
### Step 1: Identify Eligible Access Types
- Privileged admin access (domain admin, root, DBA)
- Production environment access
- Sensitive data access (PII, financial, healthcare)
- Emergency/break-glass access
- Third-party vendor access
### Step 2: Design Approval Workflows
- Self-service request portal with justification requirement
- Auto-approve for pre-authorized low-risk access (< 1 hour)
- Single approver for medium-risk (manager or resource owner)
- Dual approval for high-risk (manager + security team)
- Emergency bypass with post-facto review
### Step 3: Implement Time-Bound Access
- Configure maximum access duration per resource type
- Implement countdown timer with extension request capability
- Auto-revoke at expiration regardless of session state
- Grace period notification (15 min before expiry)
- Automatic session termination on access expiry
### Step 4: Integration Architecture
- Connect to IAM/IGA platform for provisioning/de-provisioning
- Integrate with PAM for privileged credential checkout
- Connect to ITSM for ticket correlation
- Forward events to SIEM for monitoring
- API integration for programmatic access requests
### Step 5: Monitoring and Compliance
- Log all JIT requests, approvals, grants, and revocations
- Alert on access used beyond approved scope
- Track access not used (request but never connected)
- Measure mean time to access (request to grant)
- Report on access patterns for baseline optimization
## Security Controls
| Control | NIST 800-53 | Description |
|---------|-------------|-------------|
| Temporary Access | AC-2(2) | Automated temporary account management |
| Least Privilege | AC-6 | Time-bound minimum access |
| Access Enforcement | AC-3 | Automated access grant/revoke |
| Audit | AU-3 | Complete JIT access audit trail |
| Risk Assessment | RA-3 | Risk-based approval routing |
## Common Pitfalls
- Setting time windows too long, negating JIT benefits
- Not implementing automatic revocation at expiration
- Complex approval workflows causing access delays for legitimate needs
- Not providing emergency bypass for critical incidents
- Failing to audit approved but unused JIT access
## Verification
- [ ] JIT request workflow functional end-to-end
- [ ] Access automatically revoked at expiration
- [ ] Approval routing correct for all risk levels
- [ ] Emergency access bypass works with post-review
- [ ] All JIT events logged to SIEM
- [ ] Standing privileges reduced by measurable percentage
- [ ] Mean time to access meets business SLA
@@ -0,0 +1,46 @@
# JIT Access Provisioning Policy Template
## Resource Classification
| Resource Type | Risk Level | Max Duration | Auto-Approve | Approvals Required |
|---------------|------------|--------------|--------------|-------------------|
| Read-only access | Low | 1 hour | Yes | 0 |
| Standard application | Medium | 4 hours | No | 1 (manager) |
| Production server | High | 4 hours | No | 2 (manager + security) |
| Database admin | Critical | 2 hours | No | 2 (DBA lead + security) |
| Domain admin | Critical | 1 hour | No | 2 (security + CISO) |
| Cloud admin | Critical | 2 hours | No | 2 (cloud team + security) |
## Approval Workflow Matrix
| Risk Level | Standard Request | Emergency Request |
|------------|-----------------|-------------------|
| Low | Auto-approve | Auto-approve |
| Medium | 1 approval | Auto-approve + post-review |
| High | 2 approvals | Immediate grant + post-review |
| Critical | 2 approvals + MFA | Immediate grant + incident review |
## Request Form Fields
- Requester name and ID
- Target resource/system
- Access level requested
- Duration requested (within policy maximum)
- Business justification
- Related ticket/incident number
- Emergency flag (yes/no)
## SLA Targets
| Metric | Target |
|--------|--------|
| Mean time to access (low risk) | < 1 minute |
| Mean time to access (medium risk) | < 15 minutes |
| Mean time to access (high risk) | < 30 minutes |
| Emergency access grant | < 2 minutes |
| Access revocation at expiry | Immediate (< 1 minute) |
| Post-emergency review | Within 24 hours |
## Monitoring Alerts
- [ ] Emergency access granted
- [ ] Access duration extended
- [ ] Approved access not used within 30 minutes
- [ ] Unusual access patterns detected
- [ ] Approval SLA breached
- [ ] Revocation failure
@@ -0,0 +1,27 @@
# Standards and References - Just-In-Time Access Provisioning
## NIST Standards
- **NIST SP 800-207**: Zero Trust Architecture - Section 3 (Logical Components)
- **NIST SP 800-53 Rev 5**:
- AC-2(2): Automated Temporary and Emergency Account Management
- AC-2(3): Disable Accounts
- AC-6: Least Privilege
- AC-6(5): Privileged Accounts
- **NIST SP 1800-35**: Implementing a Zero Trust Architecture
## Zero Trust Frameworks
- **CISA Zero Trust Maturity Model**: Identity pillar - dynamic access provisioning
- **DoD Zero Trust Reference Architecture**: JIT/JEA requirements
- **Forrester ZTX**: Extended Zero Trust with JIT access
## Tools and Platforms
- **Microsoft Entra PIM**: Privileged Identity Management with JIT elevation
- **CyberArk JIT**: Privileged access on-demand
- **SailPoint**: Identity governance with access request workflows
- **HashiCorp Boundary**: Just-in-time access to infrastructure
- **StrongDM**: Dynamic access management
## Compliance
- **SOX**: Least privilege for financial system access
- **PCI DSS 4.0**: Requirement 7.2 - Access based on need to know
- **HIPAA**: Minimum necessary standard for PHI access
@@ -0,0 +1,55 @@
# Just-In-Time Access Provisioning Workflows
## Workflow 1: Standard JIT Access Request
### Steps:
1. User submits access request via self-service portal
2. Request includes: target resource, duration, business justification
3. System calculates risk score based on resource sensitivity and user context
4. Risk-based routing:
- Low risk (< 1 hr, non-privileged): Auto-approve
- Medium risk: Route to resource owner for approval
- High risk (privileged, production): Dual approval required
5. Approver notified via email/Slack/Teams
6. Approver reviews and approves/denies with comments
7. On approval: system provisions access with time-bound constraint
8. User notified of access grant with expiration time
9. At expiration: system automatically revokes access
10. All events logged for audit trail
## Workflow 2: Emergency JIT Access (Break-Glass)
### Steps:
1. User declares emergency and requests immediate access
2. System grants access immediately without pre-approval
3. Access limited to shorter maximum duration (e.g., 2 hours)
4. Security team notified of emergency access grant
5. User must provide justification within 24 hours
6. Manager and security team perform post-facto review
7. If review finds access unjustified: security incident opened
8. All emergency access events flagged in audit reports
## Workflow 3: Privileged Elevation with PAM Integration
### Steps:
1. User requests privilege elevation through JIT portal
2. Approval obtained per risk-based workflow
3. JIT system triggers PAM credential checkout
4. PSM session initiated with time-bound credential
5. User performs privileged operations via isolated session
6. Session recorded for audit
7. At expiration: session terminated, credential checked in, password rotated
8. JIT access record closed
## Workflow 4: Vendor/Third-Party JIT Access
### Steps:
1. Internal sponsor submits access request on behalf of vendor
2. Request includes: vendor identity, scope, duration, project reference
3. Dual approval required (sponsor manager + security)
4. Temporary account created with MFA enrollment
5. Access restricted to specified resources only
6. Network access limited to authorized segments
7. Session monitoring enabled
8. Account deactivated at expiration
9. Account deleted after 30-day retention period
@@ -0,0 +1,373 @@
#!/usr/bin/env python3
"""
Just-In-Time Access Provisioning Engine
Manages JIT access requests, approval workflows, time-bound grants,
automatic revocation, and audit logging for zero-standing-privilege
implementations.
"""
import json
import datetime
import secrets
from typing import Dict, List, Optional
from dataclasses import dataclass, field
from enum import Enum
class RiskLevel(Enum):
LOW = "low"
MEDIUM = "medium"
HIGH = "high"
CRITICAL = "critical"
class RequestStatus(Enum):
PENDING = "pending"
APPROVED = "approved"
DENIED = "denied"
ACTIVE = "active"
EXPIRED = "expired"
REVOKED = "revoked"
EMERGENCY = "emergency"
@dataclass
class JITAccessRequest:
"""A just-in-time access request."""
request_id: str
requester: str
target_resource: str
resource_type: str # server, database, application, cloud_role
requested_duration_minutes: int
justification: str
risk_level: RiskLevel = RiskLevel.MEDIUM
status: RequestStatus = RequestStatus.PENDING
approvers: List[str] = field(default_factory=list)
approved_by: List[str] = field(default_factory=list)
denied_by: str = ""
created_at: str = ""
granted_at: str = ""
expires_at: str = ""
revoked_at: str = ""
is_emergency: bool = False
ticket_id: str = ""
@dataclass
class ResourcePolicy:
"""Policy for a protected resource."""
resource_pattern: str
resource_type: str
max_duration_minutes: int
risk_level: RiskLevel
auto_approve: bool = False
required_approvals: int = 1
approver_roles: List[str] = field(default_factory=list)
mfa_required: bool = True
session_recording: bool = False
class JITAccessEngine:
"""Manages the full JIT access lifecycle."""
def __init__(self):
self.requests: Dict[str, JITAccessRequest] = {}
self.policies: List[ResourcePolicy] = []
self.audit_log: List[Dict] = []
def add_policy(self, policy: ResourcePolicy):
"""Register a resource access policy."""
self.policies.append(policy)
def _get_policy(self, resource: str, resource_type: str) -> Optional[ResourcePolicy]:
"""Find matching policy for a resource."""
for policy in self.policies:
if policy.resource_type == resource_type:
if policy.resource_pattern == "*" or policy.resource_pattern in resource:
return policy
return None
def _generate_request_id(self) -> str:
return f"JIT-{datetime.datetime.now().strftime('%Y%m%d')}-{secrets.token_hex(4).upper()}"
def _log_event(self, event_type: str, request_id: str, details: Dict):
"""Record audit event."""
self.audit_log.append({
"timestamp": datetime.datetime.now().isoformat(),
"event_type": event_type,
"request_id": request_id,
**details
})
def submit_request(self, requester: str, target_resource: str,
resource_type: str, duration_minutes: int,
justification: str, is_emergency: bool = False,
ticket_id: str = "") -> JITAccessRequest:
"""Submit a new JIT access request."""
policy = self._get_policy(target_resource, resource_type)
if not policy:
raise ValueError(f"No policy found for resource type: {resource_type}")
# Enforce maximum duration
actual_duration = min(duration_minutes, policy.max_duration_minutes)
if is_emergency:
actual_duration = min(actual_duration, 120) # 2-hour max for emergency
request = JITAccessRequest(
request_id=self._generate_request_id(),
requester=requester,
target_resource=target_resource,
resource_type=resource_type,
requested_duration_minutes=actual_duration,
justification=justification,
risk_level=policy.risk_level,
created_at=datetime.datetime.now().isoformat(),
is_emergency=is_emergency,
ticket_id=ticket_id
)
if is_emergency:
# Emergency: grant immediately, require post-facto review
request.status = RequestStatus.EMERGENCY
now = datetime.datetime.now()
request.granted_at = now.isoformat()
request.expires_at = (now + datetime.timedelta(minutes=actual_duration)).isoformat()
self._log_event("EMERGENCY_GRANT", request.request_id, {
"requester": requester,
"resource": target_resource,
"duration_minutes": actual_duration,
"justification": justification
})
elif policy.auto_approve and policy.risk_level == RiskLevel.LOW:
# Auto-approve low-risk
request.status = RequestStatus.APPROVED
request.approved_by = ["AUTO"]
self._log_event("AUTO_APPROVED", request.request_id, {
"requester": requester,
"resource": target_resource,
"reason": "Low-risk auto-approve policy"
})
self._activate_access(request)
else:
# Route for approval
request.approvers = policy.approver_roles
request.status = RequestStatus.PENDING
self._log_event("REQUEST_SUBMITTED", request.request_id, {
"requester": requester,
"resource": target_resource,
"required_approvals": policy.required_approvals,
"approvers": policy.approver_roles
})
self.requests[request.request_id] = request
return request
def approve_request(self, request_id: str, approver: str) -> JITAccessRequest:
"""Approve a JIT access request."""
request = self.requests.get(request_id)
if not request:
raise ValueError(f"Request not found: {request_id}")
if request.status not in (RequestStatus.PENDING,):
raise ValueError(f"Request {request_id} is not pending approval")
request.approved_by.append(approver)
policy = self._get_policy(request.target_resource, request.resource_type)
required = policy.required_approvals if policy else 1
self._log_event("APPROVAL_RECORDED", request_id, {
"approver": approver,
"approvals_count": len(request.approved_by),
"required": required
})
if len(request.approved_by) >= required:
request.status = RequestStatus.APPROVED
self._activate_access(request)
return request
def deny_request(self, request_id: str, denier: str, reason: str = "") -> JITAccessRequest:
"""Deny a JIT access request."""
request = self.requests.get(request_id)
if not request:
raise ValueError(f"Request not found: {request_id}")
request.status = RequestStatus.DENIED
request.denied_by = denier
self._log_event("REQUEST_DENIED", request_id, {
"denied_by": denier,
"reason": reason
})
return request
def _activate_access(self, request: JITAccessRequest):
"""Activate the approved access grant."""
now = datetime.datetime.now()
request.status = RequestStatus.ACTIVE
request.granted_at = now.isoformat()
request.expires_at = (now + datetime.timedelta(
minutes=request.requested_duration_minutes
)).isoformat()
self._log_event("ACCESS_ACTIVATED", request.request_id, {
"requester": request.requester,
"resource": request.target_resource,
"granted_at": request.granted_at,
"expires_at": request.expires_at
})
def check_expirations(self) -> List[JITAccessRequest]:
"""Check and revoke expired access grants."""
now = datetime.datetime.now()
expired = []
for request in self.requests.values():
if request.status in (RequestStatus.ACTIVE, RequestStatus.EMERGENCY):
if request.expires_at:
expiry = datetime.datetime.fromisoformat(request.expires_at)
if now >= expiry:
request.status = RequestStatus.EXPIRED
request.revoked_at = now.isoformat()
expired.append(request)
self._log_event("ACCESS_EXPIRED", request.request_id, {
"requester": request.requester,
"resource": request.target_resource,
"expired_at": request.revoked_at
})
return expired
def revoke_access(self, request_id: str, reason: str = "") -> JITAccessRequest:
"""Manually revoke an active access grant."""
request = self.requests.get(request_id)
if not request:
raise ValueError(f"Request not found: {request_id}")
request.status = RequestStatus.REVOKED
request.revoked_at = datetime.datetime.now().isoformat()
self._log_event("ACCESS_REVOKED", request_id, {
"requester": request.requester,
"resource": request.target_resource,
"reason": reason
})
return request
def get_active_grants(self) -> List[JITAccessRequest]:
"""List all currently active access grants."""
return [r for r in self.requests.values()
if r.status in (RequestStatus.ACTIVE, RequestStatus.EMERGENCY)]
def get_metrics(self) -> Dict:
"""Calculate JIT access metrics."""
all_requests = list(self.requests.values())
total = len(all_requests)
if total == 0:
return {"total": 0}
by_status = {}
for r in all_requests:
by_status[r.status.value] = by_status.get(r.status.value, 0) + 1
emergency_count = sum(1 for r in all_requests if r.is_emergency)
# Calculate mean time to access
approved = [r for r in all_requests if r.granted_at and r.created_at]
if approved:
total_wait = sum(
(datetime.datetime.fromisoformat(r.granted_at) -
datetime.datetime.fromisoformat(r.created_at)).total_seconds()
for r in approved
)
mean_tta = total_wait / len(approved) / 60 # minutes
else:
mean_tta = 0
return {
"total_requests": total,
"by_status": by_status,
"emergency_grants": emergency_count,
"active_grants": len(self.get_active_grants()),
"mean_time_to_access_minutes": round(mean_tta, 1),
"audit_events": len(self.audit_log)
}
def generate_report(self) -> str:
"""Generate JIT access report."""
metrics = self.get_metrics()
active = self.get_active_grants()
lines = [
"=" * 70,
"JUST-IN-TIME ACCESS PROVISIONING REPORT",
"=" * 70,
f"Report Date: {datetime.datetime.now().isoformat()}",
f"Total Requests: {metrics['total_requests']}",
f"Active Grants: {metrics['active_grants']}",
f"Emergency Grants: {metrics['emergency_grants']}",
f"Mean Time to Access: {metrics['mean_time_to_access_minutes']} minutes",
f"Audit Events: {metrics['audit_events']}",
"-" * 70,
"",
"STATUS BREAKDOWN:",
]
for status, count in metrics.get("by_status", {}).items():
lines.append(f" {status}: {count}")
lines.append("")
if active:
lines.append("ACTIVE GRANTS:")
lines.append("-" * 40)
for r in active:
flag = " [EMERGENCY]" if r.is_emergency else ""
lines.append(f" {r.request_id}: {r.requester} -> {r.target_resource}{flag}")
lines.append(f" Expires: {r.expires_at}")
lines.append(f" Justification: {r.justification}")
lines.append("")
lines.append("=" * 70)
return "\n".join(lines)
def main():
"""Demo JIT access engine."""
engine = JITAccessEngine()
# Define resource policies
engine.add_policy(ResourcePolicy(
resource_pattern="*", resource_type="read_only",
max_duration_minutes=60, risk_level=RiskLevel.LOW,
auto_approve=True, required_approvals=0
))
engine.add_policy(ResourcePolicy(
resource_pattern="*", resource_type="production_server",
max_duration_minutes=240, risk_level=RiskLevel.HIGH,
auto_approve=False, required_approvals=2,
approver_roles=["manager", "security_team"],
session_recording=True
))
engine.add_policy(ResourcePolicy(
resource_pattern="*", resource_type="database_admin",
max_duration_minutes=120, risk_level=RiskLevel.CRITICAL,
auto_approve=False, required_approvals=2,
approver_roles=["dba_lead", "security_team"],
mfa_required=True, session_recording=True
))
# Submit requests
r1 = engine.submit_request("alice", "docs-server", "read_only", 30,
"Need to check documentation")
r2 = engine.submit_request("bob", "prod-web-01", "production_server", 120,
"Deploy hotfix for CVE-2026-1234", ticket_id="INC-5678")
r3 = engine.submit_request("charlie", "prod-db-01", "database_admin", 60,
"Critical production outage", is_emergency=True)
# Approve prod server access
engine.approve_request(r2.request_id, "manager_dave")
engine.approve_request(r2.request_id, "security_eve")
print(engine.generate_report())
if __name__ == "__main__":
main()