mirror of
https://github.com/mukul975/Anthropic-Cybersecurity-Skills.git
synced 2026-07-26 14:10:59 +03:00
Initial commit - 611 cybersecurity skills across all subdomains
This commit is contained in:
@@ -0,0 +1,235 @@
|
||||
---
|
||||
name: building-role-mining-for-rbac-optimization
|
||||
description: Apply bottom-up and top-down role mining techniques to discover optimal RBAC roles from existing user-permission assignments, reducing role explosion and enforcing least privilege.
|
||||
domain: cybersecurity
|
||||
subdomain: identity-access-management
|
||||
tags: [rbac, role-mining, identity-governance, access-control, least-privilege, clustering]
|
||||
version: "1.0"
|
||||
author: mahipal
|
||||
license: MIT
|
||||
---
|
||||
|
||||
# Building Role Mining for RBAC Optimization
|
||||
|
||||
## Overview
|
||||
|
||||
Role mining is the process of analyzing existing user-permission assignments to discover optimal roles for a Role-Based Access Control (RBAC) system. Organizations accumulate excessive permissions over time through job changes, project assignments, and ad-hoc access grants, leading to "role explosion" where thousands of granular roles exist with significant overlap. Role mining uses data analysis -- including clustering algorithms, formal concept analysis, and graph-based methods -- to consolidate permissions into a minimal set of roles that accurately represent business functions while enforcing least privilege.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Export of current user-permission assignments (CSV/database)
|
||||
- Identity governance platform or directory service access
|
||||
- Python 3.9+ with pandas, scikit-learn, numpy
|
||||
- Understanding of organizational structure and job functions
|
||||
- Stakeholder access for role validation workshops
|
||||
|
||||
## Core Concepts
|
||||
|
||||
### Role Mining Approaches
|
||||
|
||||
| Approach | Description | Best For |
|
||||
|----------|-------------|----------|
|
||||
| Bottom-Up | Analyze existing permissions to discover common patterns | Large datasets with organic permission growth |
|
||||
| Top-Down | Design roles from business requirements and job descriptions | Greenfield RBAC or organizational restructuring |
|
||||
| Hybrid | Combine bottom-up analysis with top-down business validation | Most production environments |
|
||||
|
||||
### Role Mining Algorithms
|
||||
|
||||
**1. Permission Clustering**: Group users with similar permission sets using k-means or hierarchical clustering. Users in the same cluster share a common role.
|
||||
|
||||
**2. Formal Concept Analysis (FCA)**: Mathematical framework that identifies complete set of concepts (user groups sharing exact permission sets) from a binary user-permission matrix.
|
||||
|
||||
**3. Graph-Based Mining**: Model users and permissions as a bipartite graph, then find dense subgraphs representing candidate roles.
|
||||
|
||||
**4. Boolean Matrix Decomposition**: Decompose the user-permission matrix U into U ≈ R × P where R maps users to roles and P maps roles to permissions.
|
||||
|
||||
### Role Mining Metrics
|
||||
|
||||
| Metric | Formula | Target |
|
||||
|--------|---------|--------|
|
||||
| Role Count | Total distinct roles after mining | Minimize |
|
||||
| Coverage | Permissions explained by mined roles / Total permissions | > 95% |
|
||||
| Weighted Structural Complexity (WSC) | Sum of role-user + role-permission assignments | Minimize |
|
||||
| Deviation | Extra permissions not covered by assigned roles | < 5% |
|
||||
|
||||
## Implementation Steps
|
||||
|
||||
### Step 1: Extract User-Permission Data
|
||||
|
||||
Collect the current access state from all identity sources:
|
||||
|
||||
```python
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
|
||||
# Load user-permission assignments
|
||||
# Format: user_id, permission_id (one row per assignment)
|
||||
assignments = pd.read_csv("user_permissions.csv")
|
||||
|
||||
# Create binary user-permission matrix (UPA matrix)
|
||||
upa_matrix = assignments.pivot_table(
|
||||
index="user_id",
|
||||
columns="permission_id",
|
||||
aggfunc="size",
|
||||
fill_value=0
|
||||
)
|
||||
upa_matrix = (upa_matrix > 0).astype(int)
|
||||
|
||||
print(f"Users: {upa_matrix.shape[0]}")
|
||||
print(f"Permissions: {upa_matrix.shape[1]}")
|
||||
print(f"Assignments: {assignments.shape[0]}")
|
||||
print(f"Density: {upa_matrix.values.sum() / upa_matrix.size:.2%}")
|
||||
```
|
||||
|
||||
### Step 2: Bottom-Up Role Discovery Using Clustering
|
||||
|
||||
```python
|
||||
from sklearn.cluster import AgglomerativeClustering
|
||||
from sklearn.metrics import silhouette_score
|
||||
|
||||
def find_optimal_clusters(matrix, max_k=50):
|
||||
"""Find optimal number of roles using silhouette analysis."""
|
||||
scores = []
|
||||
for k in range(2, min(max_k, matrix.shape[0])):
|
||||
clustering = AgglomerativeClustering(
|
||||
n_clusters=k, metric="jaccard", linkage="average"
|
||||
)
|
||||
labels = clustering.fit_predict(matrix)
|
||||
score = silhouette_score(matrix, labels, metric="jaccard")
|
||||
scores.append((k, score))
|
||||
|
||||
optimal_k = max(scores, key=lambda x: x[1])[0]
|
||||
return optimal_k, scores
|
||||
|
||||
def mine_roles_clustering(upa_matrix, n_clusters):
|
||||
"""Mine roles using hierarchical clustering on Jaccard distance."""
|
||||
clustering = AgglomerativeClustering(
|
||||
n_clusters=n_clusters, metric="jaccard", linkage="average"
|
||||
)
|
||||
user_matrix = upa_matrix.values
|
||||
labels = clustering.fit_predict(user_matrix)
|
||||
|
||||
roles = {}
|
||||
for cluster_id in range(n_clusters):
|
||||
cluster_users = upa_matrix.index[labels == cluster_id]
|
||||
cluster_permissions = upa_matrix.loc[cluster_users]
|
||||
|
||||
# Core role = permissions held by >80% of cluster members
|
||||
permission_frequency = cluster_permissions.mean()
|
||||
core_permissions = permission_frequency[permission_frequency >= 0.8].index.tolist()
|
||||
|
||||
roles[f"Role_{cluster_id}"] = {
|
||||
"permissions": core_permissions,
|
||||
"user_count": len(cluster_users),
|
||||
"users": cluster_users.tolist(),
|
||||
"coverage": permission_frequency[permission_frequency >= 0.8].mean()
|
||||
}
|
||||
|
||||
return roles, labels
|
||||
```
|
||||
|
||||
### Step 3: Formal Concept Analysis
|
||||
|
||||
```python
|
||||
def mine_roles_fca(upa_matrix, min_support=3):
|
||||
"""Mine roles using Formal Concept Analysis (frequent closed itemsets)."""
|
||||
from itertools import combinations
|
||||
|
||||
users = upa_matrix.index.tolist()
|
||||
permissions = upa_matrix.columns.tolist()
|
||||
|
||||
concepts = []
|
||||
|
||||
# Find all maximal permission sets shared by at least min_support users
|
||||
for size in range(len(permissions), 0, -1):
|
||||
for perm_combo in combinations(permissions, size):
|
||||
perm_set = set(perm_combo)
|
||||
# Find users who have ALL permissions in this set
|
||||
matching_users = []
|
||||
for user in users:
|
||||
user_perms = set(upa_matrix.columns[upa_matrix.loc[user] == 1])
|
||||
if perm_set.issubset(user_perms):
|
||||
matching_users.append(user)
|
||||
|
||||
if len(matching_users) >= min_support:
|
||||
# Check if this is a closed concept (no superset with same extent)
|
||||
is_closed = True
|
||||
for concept in concepts:
|
||||
if set(matching_users) == set(concept["users"]) and \
|
||||
perm_set.issubset(set(concept["permissions"])):
|
||||
is_closed = False
|
||||
break
|
||||
|
||||
if is_closed:
|
||||
concepts.append({
|
||||
"permissions": list(perm_set),
|
||||
"users": matching_users,
|
||||
"support": len(matching_users)
|
||||
})
|
||||
|
||||
if len(concepts) > 100: # Limit for performance
|
||||
break
|
||||
|
||||
return concepts
|
||||
```
|
||||
|
||||
### Step 4: Evaluate and Select Roles
|
||||
|
||||
```python
|
||||
def evaluate_role_set(roles, upa_matrix):
|
||||
"""Evaluate the quality of a mined role set."""
|
||||
total_assignments = upa_matrix.values.sum()
|
||||
covered_assignments = 0
|
||||
extra_assignments = 0
|
||||
|
||||
for role_name, role_data in roles.items():
|
||||
role_perms = set(role_data["permissions"])
|
||||
for user in role_data["users"]:
|
||||
user_perms = set(upa_matrix.columns[upa_matrix.loc[user] == 1])
|
||||
covered = role_perms.intersection(user_perms)
|
||||
extra = role_perms - user_perms
|
||||
covered_assignments += len(covered)
|
||||
extra_assignments += len(extra)
|
||||
|
||||
metrics = {
|
||||
"total_roles": len(roles),
|
||||
"total_assignments": total_assignments,
|
||||
"covered_assignments": covered_assignments,
|
||||
"coverage_rate": covered_assignments / total_assignments if total_assignments else 0,
|
||||
"extra_permissions": extra_assignments,
|
||||
"deviation_rate": extra_assignments / (covered_assignments + extra_assignments) if (covered_assignments + extra_assignments) else 0,
|
||||
"avg_role_size": np.mean([len(r["permissions"]) for r in roles.values()]),
|
||||
"avg_users_per_role": np.mean([r["user_count"] for r in roles.values()]),
|
||||
}
|
||||
return metrics
|
||||
```
|
||||
|
||||
### Step 5: Business Validation
|
||||
|
||||
After mining candidate roles:
|
||||
|
||||
1. Map mined roles to business functions (department, job title)
|
||||
2. Conduct workshops with business unit managers to validate role definitions
|
||||
3. Identify outlier permissions that indicate misconfiguration
|
||||
4. Refine roles based on feedback and re-evaluate metrics
|
||||
5. Document role definitions with business justification
|
||||
|
||||
## Validation Checklist
|
||||
|
||||
- [ ] User-permission matrix extracted from all identity sources
|
||||
- [ ] Multiple mining algorithms compared (clustering, FCA)
|
||||
- [ ] Optimal role count determined via silhouette analysis or WSC
|
||||
- [ ] Coverage rate exceeds 95% of existing assignments
|
||||
- [ ] Deviation rate below 5% (minimal extra permissions)
|
||||
- [ ] Mined roles validated with business stakeholders
|
||||
- [ ] Role hierarchy defined (parent-child inheritance)
|
||||
- [ ] Exception/outlier permissions documented
|
||||
- [ ] Migration plan created for transitioning to new role model
|
||||
- [ ] Ongoing role governance process defined
|
||||
|
||||
## References
|
||||
|
||||
- [Role Mining: Optimizing RBAC - NIST](https://csrc.nist.gov/projects/role-based-access-control)
|
||||
- [RBAC Standard - ANSI/INCITS 359-2012](https://www.incits.org/)
|
||||
- [Formal Concept Analysis for Role Engineering](https://link.springer.com/chapter/10.1007/978-3-540-73070-6_7)
|
||||
- [scikit-learn Clustering Documentation](https://scikit-learn.org/stable/modules/clustering.html)
|
||||
@@ -0,0 +1,52 @@
|
||||
# Role Mining Project Template
|
||||
|
||||
## Project Overview
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| Organization | |
|
||||
| Project Lead | |
|
||||
| Start Date | |
|
||||
| Target Completion | |
|
||||
| Identity Sources | AD / Azure / AWS / Applications |
|
||||
|
||||
## Data Collection Summary
|
||||
|
||||
| Source | Users | Permissions | Assignments |
|
||||
|--------|-------|-------------|-------------|
|
||||
| Active Directory | | | |
|
||||
| AWS IAM | | | |
|
||||
| Azure AD | | | |
|
||||
| Applications | | | |
|
||||
| **Total (Deduplicated)** | | | |
|
||||
|
||||
## Mining Results
|
||||
|
||||
| Algorithm | Roles Found | Coverage | Deviation | WSC |
|
||||
|-----------|-------------|----------|-----------|-----|
|
||||
| Clustering (k=___) | | | | |
|
||||
| Intersection Mining | | | | |
|
||||
| Selected Approach | | | | |
|
||||
|
||||
## Proposed Role Definitions
|
||||
|
||||
| Role Name | Department | Permissions | Users | Status |
|
||||
|-----------|------------|-------------|-------|--------|
|
||||
| | | | | Draft/Validated/Approved |
|
||||
| | | | | |
|
||||
|
||||
## Stakeholder Validation
|
||||
|
||||
| Business Unit | Reviewer | Roles Reviewed | Approved | Date |
|
||||
|--------------|----------|---------------|----------|------|
|
||||
| | | | Yes/No | |
|
||||
|
||||
## Migration Plan
|
||||
|
||||
- [ ] Roles created in identity governance platform
|
||||
- [ ] User-role assignments configured
|
||||
- [ ] Individual permission grants removed
|
||||
- [ ] Test users validated access
|
||||
- [ ] Full migration completed
|
||||
- [ ] Post-migration access verification
|
||||
- [ ] Old permissions cleanup confirmed
|
||||
@@ -0,0 +1,46 @@
|
||||
# Role Mining for RBAC Optimization - Standards Reference
|
||||
|
||||
## RBAC Standards
|
||||
|
||||
### ANSI/INCITS 359-2012 - Core RBAC
|
||||
- Defines User, Role, Permission, Session abstractions
|
||||
- Role assignment: users are assigned to roles
|
||||
- Permission assignment: permissions are assigned to roles
|
||||
- Role hierarchy: senior roles inherit junior role permissions
|
||||
- Separation of Duty constraints (static and dynamic)
|
||||
|
||||
### NIST RBAC Model (SP 800-162)
|
||||
- Core RBAC: Basic user-role and role-permission mappings
|
||||
- Hierarchical RBAC: Role inheritance relationships
|
||||
- Constrained RBAC: Static and dynamic separation of duties
|
||||
- Symmetric RBAC: Combined user-centric and permission-centric views
|
||||
|
||||
## Identity Governance Standards
|
||||
|
||||
### ISO 27001:2022 - A.5.15 Access Control
|
||||
- Access control policy based on business and security requirements
|
||||
- Roles determined by job function
|
||||
- Regular review of access rights
|
||||
- Formal authorization for privilege changes
|
||||
|
||||
### NIST SP 800-53 Rev 5
|
||||
- AC-2: Account Management
|
||||
- AC-3: Access Enforcement
|
||||
- AC-5: Separation of Duties
|
||||
- AC-6: Least Privilege
|
||||
- AC-16: Security and Privacy Attributes
|
||||
- AC-24: Access Control Decisions
|
||||
|
||||
## Role Mining Research
|
||||
|
||||
### Key Algorithms
|
||||
- **RoleMiner (Vaidya et al., 2007)**: Iterative role mining minimizing WSC
|
||||
- **CompleteMiner / FastMiner (Vaidya et al., 2006)**: Complete vs. approximate algorithms
|
||||
- **ORCA (Schlegelmilch & Steffens, 2005)**: Clustering-based approach
|
||||
- **Graph Optimization (Lu et al., 2008)**: Graph-based role mining
|
||||
|
||||
### Quality Metrics
|
||||
- Weighted Structural Complexity: min(|UA| + |PA| + |Roles|)
|
||||
- Boolean Matrix Decomposition error
|
||||
- Jaccard similarity between mined and original access
|
||||
- Role coverage percentage
|
||||
@@ -0,0 +1,82 @@
|
||||
# Role Mining for RBAC Optimization - Workflows
|
||||
|
||||
## End-to-End Role Mining Workflow
|
||||
|
||||
```
|
||||
Phase 1: DATA COLLECTION (Week 1-2)
|
||||
├── Export user-permission data from all identity sources
|
||||
│ ├── Active Directory group memberships
|
||||
│ ├── Cloud IAM role assignments
|
||||
│ ├── Application-level permissions
|
||||
│ └── Database access grants
|
||||
├── Collect HR data (job titles, departments, cost centers)
|
||||
├── Normalize data into User-Permission Assignment (UPA) matrix
|
||||
└── Clean data: remove disabled accounts, system accounts
|
||||
|
||||
Phase 2: ANALYSIS (Week 3-4)
|
||||
├── Run clustering algorithms (hierarchical, k-means)
|
||||
├── Run Formal Concept Analysis for exact role candidates
|
||||
├── Compare results using WSC and coverage metrics
|
||||
├── Identify optimal number of roles via silhouette analysis
|
||||
└── Map candidate roles to organizational structure
|
||||
|
||||
Phase 3: VALIDATION (Week 5-6)
|
||||
├── Present candidate roles to business unit managers
|
||||
├── Validate each role against job descriptions
|
||||
├── Identify and resolve outlier permissions
|
||||
├── Define role hierarchy (inheritance relationships)
|
||||
└── Agree on role names and descriptions
|
||||
|
||||
Phase 4: IMPLEMENTATION (Week 7-8)
|
||||
├── Create roles in identity governance platform
|
||||
├── Assign users to validated roles
|
||||
├── Remove individual permission assignments
|
||||
├── Test access for sample users in each role
|
||||
└── Document role definitions and approval chain
|
||||
|
||||
Phase 5: GOVERNANCE (Ongoing)
|
||||
├── Monitor for permission drift
|
||||
├── Quarterly role effectiveness review
|
||||
├── Re-run mining annually to detect new patterns
|
||||
└── Track role count and WSC metrics over time
|
||||
```
|
||||
|
||||
## Data Normalization Workflow
|
||||
|
||||
```
|
||||
Raw Data Sources
|
||||
│
|
||||
├── AD: user → group → permissions
|
||||
│ Normalize to: user_id, permission_id
|
||||
│
|
||||
├── AWS: user/role → policy → actions
|
||||
│ Normalize to: user_id, permission_id
|
||||
│
|
||||
├── Azure: user → role → permissions
|
||||
│ Normalize to: user_id, permission_id
|
||||
│
|
||||
└── Applications: user → app_role → features
|
||||
Normalize to: user_id, permission_id
|
||||
|
||||
Merge all sources → Deduplicate → Create UPA matrix
|
||||
```
|
||||
|
||||
## Role Consolidation Workflow
|
||||
|
||||
```
|
||||
Mining produces N candidate roles
|
||||
│
|
||||
├── Remove roles with < 3 users (outliers)
|
||||
│
|
||||
├── Merge roles with > 90% Jaccard similarity
|
||||
│
|
||||
├── Identify hierarchical relationships:
|
||||
│ └── If Role A permissions ⊂ Role B permissions
|
||||
│ → Role A is junior to Role B
|
||||
│
|
||||
├── Check for SoD violations:
|
||||
│ └── Does any role combine conflicting permissions?
|
||||
│ → Split into separate roles if needed
|
||||
│
|
||||
└── Final role set with hierarchy and constraints
|
||||
```
|
||||
@@ -0,0 +1,251 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Role Mining Engine for RBAC Optimization
|
||||
|
||||
Implements multiple role mining algorithms (clustering, FCA) on user-permission
|
||||
assignment data to discover optimal RBAC roles. Generates role definitions,
|
||||
coverage reports, and migration plans.
|
||||
|
||||
Requirements:
|
||||
pip install pandas numpy scikit-learn
|
||||
"""
|
||||
|
||||
import csv
|
||||
import json
|
||||
from collections import defaultdict
|
||||
from itertools import combinations
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
from sklearn.cluster import AgglomerativeClustering
|
||||
from sklearn.metrics import silhouette_score
|
||||
|
||||
|
||||
class RoleMiningEngine:
|
||||
"""Core role mining engine supporting multiple algorithms."""
|
||||
|
||||
def __init__(self, assignments_file=None):
|
||||
self.upa_matrix = None
|
||||
self.user_metadata = {}
|
||||
self.mined_roles = {}
|
||||
|
||||
if assignments_file:
|
||||
self.load_assignments(assignments_file)
|
||||
|
||||
def load_assignments(self, filepath):
|
||||
"""Load user-permission assignments from CSV (user_id, permission_id)."""
|
||||
df = pd.read_csv(filepath)
|
||||
required = {"user_id", "permission_id"}
|
||||
if not required.issubset(df.columns):
|
||||
raise ValueError(f"CSV must contain columns: {required}")
|
||||
|
||||
self.upa_matrix = df.pivot_table(
|
||||
index="user_id", columns="permission_id",
|
||||
aggfunc="size", fill_value=0
|
||||
)
|
||||
self.upa_matrix = (self.upa_matrix > 0).astype(int)
|
||||
|
||||
print(f"[OK] Loaded UPA matrix: {self.upa_matrix.shape[0]} users x "
|
||||
f"{self.upa_matrix.shape[1]} permissions")
|
||||
print(f" Total assignments: {self.upa_matrix.values.sum()}")
|
||||
density = self.upa_matrix.values.sum() / self.upa_matrix.size
|
||||
print(f" Matrix density: {density:.2%}")
|
||||
|
||||
def load_user_metadata(self, filepath):
|
||||
"""Load user HR data (user_id, department, title, location)."""
|
||||
df = pd.read_csv(filepath)
|
||||
for _, row in df.iterrows():
|
||||
self.user_metadata[row["user_id"]] = row.to_dict()
|
||||
|
||||
def find_optimal_k(self, max_k=50):
|
||||
"""Determine optimal number of roles using silhouette analysis."""
|
||||
if self.upa_matrix is None:
|
||||
raise ValueError("No data loaded")
|
||||
|
||||
matrix = self.upa_matrix.values
|
||||
max_k = min(max_k, matrix.shape[0] - 1)
|
||||
scores = []
|
||||
|
||||
for k in range(2, max_k + 1):
|
||||
clustering = AgglomerativeClustering(
|
||||
n_clusters=k, metric="jaccard", linkage="average"
|
||||
)
|
||||
labels = clustering.fit_predict(matrix)
|
||||
score = silhouette_score(matrix, labels, metric="jaccard")
|
||||
scores.append({"k": k, "silhouette": round(score, 4)})
|
||||
|
||||
best = max(scores, key=lambda x: x["silhouette"])
|
||||
print(f"[OK] Optimal k={best['k']} (silhouette={best['silhouette']})")
|
||||
return best["k"], scores
|
||||
|
||||
def mine_roles_clustering(self, n_clusters=None, threshold=0.8):
|
||||
"""Mine roles using hierarchical clustering with Jaccard distance."""
|
||||
if self.upa_matrix is None:
|
||||
raise ValueError("No data loaded")
|
||||
|
||||
if n_clusters is None:
|
||||
n_clusters, _ = self.find_optimal_k()
|
||||
|
||||
matrix = self.upa_matrix.values
|
||||
clustering = AgglomerativeClustering(
|
||||
n_clusters=n_clusters, metric="jaccard", linkage="average"
|
||||
)
|
||||
labels = clustering.fit_predict(matrix)
|
||||
|
||||
roles = {}
|
||||
for cluster_id in range(n_clusters):
|
||||
mask = labels == cluster_id
|
||||
cluster_users = self.upa_matrix.index[mask].tolist()
|
||||
cluster_data = self.upa_matrix.loc[cluster_users]
|
||||
|
||||
perm_freq = cluster_data.mean()
|
||||
core_perms = perm_freq[perm_freq >= threshold].index.tolist()
|
||||
|
||||
# Determine role name from user metadata
|
||||
role_label = f"Role_{cluster_id:03d}"
|
||||
if self.user_metadata:
|
||||
depts = [self.user_metadata.get(u, {}).get("department", "Unknown")
|
||||
for u in cluster_users]
|
||||
dept_counts = defaultdict(int)
|
||||
for d in depts:
|
||||
dept_counts[d] += 1
|
||||
if dept_counts:
|
||||
dominant_dept = max(dept_counts, key=dept_counts.get)
|
||||
role_label = f"{dominant_dept}_Role_{cluster_id:03d}"
|
||||
|
||||
roles[role_label] = {
|
||||
"permissions": core_perms,
|
||||
"user_count": len(cluster_users),
|
||||
"users": cluster_users,
|
||||
"permission_count": len(core_perms),
|
||||
}
|
||||
|
||||
self.mined_roles = roles
|
||||
print(f"[OK] Mined {len(roles)} roles via clustering")
|
||||
return roles
|
||||
|
||||
def mine_roles_intersection(self, min_users=3):
|
||||
"""Mine roles by finding common permission intersections."""
|
||||
if self.upa_matrix is None:
|
||||
raise ValueError("No data loaded")
|
||||
|
||||
user_perm_sets = {}
|
||||
for user in self.upa_matrix.index:
|
||||
perms = set(self.upa_matrix.columns[self.upa_matrix.loc[user] == 1])
|
||||
user_perm_sets[user] = perms
|
||||
|
||||
# Find unique permission sets shared by multiple users
|
||||
perm_set_users = defaultdict(list)
|
||||
for user, perms in user_perm_sets.items():
|
||||
key = frozenset(perms)
|
||||
perm_set_users[key].append(user)
|
||||
|
||||
roles = {}
|
||||
role_idx = 0
|
||||
for perm_set, users in perm_set_users.items():
|
||||
if len(users) >= min_users:
|
||||
roles[f"ExactRole_{role_idx:03d}"] = {
|
||||
"permissions": sorted(perm_set),
|
||||
"user_count": len(users),
|
||||
"users": users,
|
||||
"permission_count": len(perm_set),
|
||||
}
|
||||
role_idx += 1
|
||||
|
||||
self.mined_roles = roles
|
||||
print(f"[OK] Mined {len(roles)} exact-match roles "
|
||||
f"(min {min_users} users per role)")
|
||||
return roles
|
||||
|
||||
def evaluate_roles(self, roles=None):
|
||||
"""Calculate quality metrics for a set of mined roles."""
|
||||
if roles is None:
|
||||
roles = self.mined_roles
|
||||
if not roles:
|
||||
return {"error": "No roles to evaluate"}
|
||||
|
||||
total_assignments = int(self.upa_matrix.values.sum())
|
||||
covered = 0
|
||||
extra = 0
|
||||
|
||||
for role_data in roles.values():
|
||||
role_perms = set(role_data["permissions"])
|
||||
for user in role_data["users"]:
|
||||
user_perms = set(
|
||||
self.upa_matrix.columns[self.upa_matrix.loc[user] == 1]
|
||||
)
|
||||
covered += len(role_perms & user_perms)
|
||||
extra += len(role_perms - user_perms)
|
||||
|
||||
total_role_assignments = sum(
|
||||
r["user_count"] + r["permission_count"] for r in roles.values()
|
||||
)
|
||||
|
||||
metrics = {
|
||||
"total_roles": len(roles),
|
||||
"total_original_assignments": total_assignments,
|
||||
"covered_assignments": covered,
|
||||
"extra_permissions_granted": extra,
|
||||
"coverage_rate": round(covered / total_assignments, 4) if total_assignments else 0,
|
||||
"deviation_rate": round(extra / (covered + extra), 4) if (covered + extra) else 0,
|
||||
"wsc": total_role_assignments + len(roles),
|
||||
"avg_permissions_per_role": round(
|
||||
np.mean([r["permission_count"] for r in roles.values()]), 1
|
||||
),
|
||||
"avg_users_per_role": round(
|
||||
np.mean([r["user_count"] for r in roles.values()]), 1
|
||||
),
|
||||
}
|
||||
return metrics
|
||||
|
||||
def export_roles(self, output_path):
|
||||
"""Export mined roles to JSON for import into IGA platform."""
|
||||
export = {
|
||||
"generated_at": pd.Timestamp.now().isoformat(),
|
||||
"metrics": self.evaluate_roles(),
|
||||
"roles": {}
|
||||
}
|
||||
|
||||
for name, data in self.mined_roles.items():
|
||||
export["roles"][name] = {
|
||||
"name": name,
|
||||
"permissions": data["permissions"],
|
||||
"user_count": data["user_count"],
|
||||
"permission_count": data["permission_count"],
|
||||
}
|
||||
|
||||
with open(output_path, "w") as f:
|
||||
json.dump(export, f, indent=2)
|
||||
print(f"[OK] Exported {len(self.mined_roles)} roles to {output_path}")
|
||||
|
||||
def generate_migration_plan(self, output_path):
|
||||
"""Generate a CSV migration plan mapping users to new roles."""
|
||||
rows = []
|
||||
for role_name, role_data in self.mined_roles.items():
|
||||
for user in role_data["users"]:
|
||||
rows.append({
|
||||
"user_id": user,
|
||||
"new_role": role_name,
|
||||
"permissions_in_role": len(role_data["permissions"]),
|
||||
"current_permissions": int(self.upa_matrix.loc[user].sum()),
|
||||
})
|
||||
|
||||
df = pd.DataFrame(rows)
|
||||
df.to_csv(output_path, index=False)
|
||||
print(f"[OK] Migration plan exported to {output_path}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("=" * 60)
|
||||
print("Role Mining Engine for RBAC Optimization")
|
||||
print("=" * 60)
|
||||
print()
|
||||
print("Usage:")
|
||||
print(" engine = RoleMiningEngine('user_permissions.csv')")
|
||||
print(" engine.load_user_metadata('hr_data.csv')")
|
||||
print(" optimal_k, scores = engine.find_optimal_k()")
|
||||
print(" roles = engine.mine_roles_clustering(n_clusters=optimal_k)")
|
||||
print(" metrics = engine.evaluate_roles()")
|
||||
print(" engine.export_roles('mined_roles.json')")
|
||||
print(" engine.generate_migration_plan('migration_plan.csv')")
|
||||
Reference in New Issue
Block a user