Communitygithub.com

身份治理与生命周期流程构建

设计身份治理和生命周期(IGA)计划,覆盖 SailPoint、Saviynt 或 Entra ID Governance 等平台,包括入职-调岗-离职自动化、角色挖掘、访问请求、定期认证以及基于 HR 数据源的僵尸账户修复。适用于跨系统 JML 置备自动化、修复前员工访问权限,或为 SOX、HIPAA、GDPR 合规构建生命周期流程。

身份治理与生命周期流程构建 是什么?

该技能专注于为企业设计和自动化身份治理与生命周期(IGA)流程,确保从入职到离职的全生命周期管理。它通过代码示例展示了如何将 HR 系统(如 Workday)作为身份数据权威来源,连接 IGA 平台(如 SailPoint、Saviynt 或 Entra ID),并实现入职、调岗、离职自动化配置。该技能支持 SOX、HIPAA、GDPR 等合规需求,通过角色挖掘减少权限泛滥,自动识别和修复僵尸账户,并确保访问权限与组织安全策略一致。开发者可以直接使用提供的 Python 代码实现状态机转换、HR 数据同步、角色挖掘和认证报告生成,从而在 Cursor、Claude Code 或 Codex 等 AI 编码工具中快速构建 IGA 解决方案。该技能不适用于单应用的用户管理,而是解决跨系统的身份生命周期管理问题。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/mukul975/Anthropic-Cybersecurity-Skills/tree/main/skills/building-identity-governance-lifecycle-process

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

构建身份治理生命周期流程

何时使用

  • 组织缺少自动化的入职-调岗-离职(JML)身份管理流程
  • 访问权限配置是手动的,需要数天时间,造成生产力损失和安全缺口
  • 前员工离职后仍保留系统访问权限(僵尸账户)
  • 角色爆炸导致产生数千个角色,所有权不明确且权限重叠
  • 合规要求强制要求记录在案的身份生命周期流程(SOX、HIPAA、GDPR)
  • 全企业范围内缺乏对谁拥有哪些访问权限的集中可见性

不要用于单应用用户管理;身份治理解决的是跨系统生命周期管理,需要将权威 HR 数据源与下游应用置备进行关联。

前提条件

  • 权威 HR 系统(Workday、SAP SuccessFactors、BambooHR)作为身份数据源
  • IGA 平台(SailPoint、Saviynt、One Identity)或 Microsoft Entra ID Governance
  • Active Directory 和/或 Azure AD 作为主要目录服务
  • 用于需要自动化置备的目标系统的应用连接器
  • 已定义的组织角色结构和汇报层级
  • 来自 HR、IT、安全和业务部门经理的利益相关方支持

工作流程

第 1 步:定义身份生命周期状态和转换

映射从入职到离职的身份生命周期:

"""
身份生命周期状态机
定义所有身份状态及有效的转换,并包含自动化操作。
"""

IDENTITY_LIFECYCLE = {
    "states": {
        "PRE_HIRE": {
            "description": "员工在入职前,从 HR 数据源创建的身份记录",
            "automated_actions": [
                "在 IGA 平台创建身份记录",
                "生成唯一员工 ID",
                "预留邮箱",
                "根据岗位代码分配继承角色",
                "启动背景调查工作流"
            ],
            "valid_transitions": ["ACTIVE", "CANCELLED"]
        },
        "ACTIVE": {
            "description": "员工已入职,所有权限已配置完成",
            "automated_actions": [
                "创建 Active Directory 账户",
                "创建电子邮件邮箱",
                "配置继承的应用权限",
                "分配部门特定角色",
                "添加到通讯组",
                "发放 MFA 令牌/安全密钥",
                "如为远程员工,创建 VPN 账户"
            ],
            "valid_transitions": ["ROLE_CHANGE", "LEAVE_OF_ABSENCE", "TERMINATED"]
        },
        "ROLE_CHANGE": {
            "description": "员工发生调岗、晋升或部门变更",
            "automated_actions": [
                "根据新岗位代码重新计算角色分配",
                "移除前部门应用的访问权限",
                "配置新部门应用的访问权限",
                "更新组成员身份",
                "在目录中更新经理信息",
                "为保留的权限触发访问审查",
                "通知新经理有关继承的访问权限"
            ],
            "valid_transitions": ["ACTIVE", "LEAVE_OF_ABSENCE", "TERMINATED"]
        },
        "LEAVE_OF_ABSENCE": {
            "description": "员工长期休假(病假、产假、学术假)",
            "automated_actions": [
                "禁用交互式登录(保留账户)",
                "暂停 VPN 访问",
                "设置自动回复",
                "将邮箱委托给经理",
                "保留所有角色分配,待返回时恢复",
                "根据 HR 数据源设置恢复日期"
            ],
            "valid_transitions": ["ACTIVE", "TERMINATED"]
        },
        "TERMINATED": {
            "description": "员工已离职",
            "automated_actions": [
                "立即禁用 AD 账户",
                "撤销所有应用访问权限",
                "撤销 VPN 和远程访问权限",
                "将邮箱转换为共享(经理可访问90天)",
                "将 OneDrive 文件转移给经理",
                "从所有安全组和通讯组中移除",
                "撤销 OAuth 令牌和 API 密钥",
                "清除移动设备上的公司数据",
                "归档身份记录",
                "在保留期后安排账户删除"
            ],
            "valid_transitions": ["REHIRE", "DELETED"]
        },
        "REHIRE": {
            "description": "前员工重新入职",
            "automated_actions": [
                "重新激活现有身份记录",
                "重置凭据并要求重新注册 MFA",
                "根据新岗位代码配置权限(而非恢复先前权限)",
                "在前30天内标记为加强访问审查"
            ],
            "valid_transitions": ["ACTIVE"]
        },
        "DELETED": {
            "description": "保留期后永久删除账户",
            "automated_actions": [
                "删除 AD 账户",
                "删除电子邮件邮箱归档",
                "从 IGA 移除身份记录",
                "生成删除审计日志"
            ],
            "valid_transitions": []
        }
    },
    "retention_periods": {
        "terminated_to_deleted": "90 天(默认)",
        "mailbox_retention": "作为共享邮箱保留90天",
        "onedrive_retention": "经理访问权限30天,然后归档",
        "audit_log_retention": "保留7年以符合合规要求"
    }
}

第 2 步:实现权威数据源集成

将 HR 系统作为身份数据的单一权威来源进行连接:

"""
HR 数据源集成 - Workday 到 IGA 平台连接器
轮询 Workday 的员工生命周期事件,并触发置备操作。
"""
import requests
from datetime import datetime, timedelta
import logging

class WorkdayIdentityConnector:
    def __init__(self, config):
        self.base_url = config["workday_api_url"]
        self.tenant = config["tenant"]
        self.client_id = config["client_id"]
        self.client_secret = config["client_secret"]
        self.session = requests.Session()
        self.logger = logging.getLogger("workday_connector")

    def get_access_token(self):
        """向 Workday REST API 进行身份验证。"""
        token_url = f"{self.base_url}/ccx/oauth2/{self.tenant}/token"
        response = self.session.post(token_url, data={
            "grant_type": "client_credentials",
            "client_id": self.client_id,
            "client_secret": self.client_secret
        })
        response.raise_for_status()
        return response.json()["access_token"]

    def fetch_worker_changes(self, since_datetime):
        """获取自上次同步以来的所有员工生命周期事件。"""
        headers = {"Authorization": f"Bearer {self.get_access_token()}"}
        params = {
            "Updated_From": since_datetime.isoformat(),
            "Updated_Through": datetime.utcnow().isoformat(),
            "Count": 100
        }

        workers = []
        url = f"{self.base_url}/ccx/api/v1/{self.tenant}/workers"

        while url:
            response = self.session.get(url, headers=headers, params=params)
            response.raise_for_status()
            data = response.json()
            workers.extend(data.get("data", []))
            url = data.get("next", None)
            params = {}

        return workers

    def map_lifecycle_event(self, worker):
        """将 Workday 员工数据映射到身份生命周期事件。"""
        worker_data = worker.get("workerData", {})
        employment = worker_data.get("employmentData", {})
        personal = worker_data.get("personalData", {})

        event = {
            "employee_id": worker.get("id"),
            "first_name": personal.get("legalName", {}).get("firstName"),
            "last_name": personal.get("legalName", {}).get("lastName"),
            "email": worker_data.get("emailAddress"),
            "job_code": employment.get("jobProfile", {}).get("id"),
            "job_title": employment.get("jobProfile", {}).get("name"),
            "department": employment.get("organization", {}).get("name"),
            "department_code": employment.get("organization", {}).get("id"),
            "manager_id": employment.get("managerId"),
            "location": employment.get("location", {}).get("name"),
            "cost_center": employment.get("costCenter", {}).get("id"),
            "hire_date": employment.get("hireDate"),
            "termination_date": employment.get("terminationDate"),
            "status": employment.get("status"),
            "worker_type": employment.get("workerType"),
        }

        # 确定生命周期转换
        if event["status"] == "Active" and event["hire_date"]:
            hire_date = datetime.fromisoformat(event["hire_date"])
            if hire_date > datetime.utcnow():
                event["lifecycle_event"] = "PRE_HIRE"
            else:
                event["lifecycle_event"] = "JOINER"
        elif event["status"] == "Active":
            event["lifecycle_event"] = "MOVER"  # 部门或角色变更
        elif event["status"] == "Terminated":
            event["lifecycle_event"] = "LEAVER"
        elif event["status"] == "On Leave":
            event["lifecycle_event"] = "LEAVE_OF_ABSENCE"

        return event

    def process_lifecycle_events(self, since_datetime):
        """身份生命周期事件的主处理循环。"""
        workers = self.fetch_worker_changes(since_datetime)
        events = []

        for worker in workers:
            event = self.map_lifecycle_event(worker)
            events.append(event)
            self.logger.info(
                f"Lifecycle event: {event['lifecycle_event']} for "
                f"{event['first_name']} {event['last_name']} "
                f"(EmpID: {event['employee_id']})"
            )

        return events

第 3 步:实现角色挖掘和继承权限

根据岗位职能定义角色,以实现自动化配置:

"""
角色挖掘引擎
分析现有访问模式,推导出用于自动配置的角色定义。
"""
import pandas as pd
from collections import Counter
from itertools import combinations

class RoleMiningEngine:
    def __init__(self, access_data):
        """
        access_data: DataFrame,包含列
        [employee_id, job_code, department, application, entitlement]
        """
        self.access_data = access_data

    def mine_birthright_roles(self, min_assignment_pct=0.8):
        """
        识别应根据岗位代码自动分配的权限。
        如果具有相同岗位代码的用户中80%以上拥有某个权限,
        则该权限成为继承访问权限。
        """
        birthright_roles = {}

        for job_code, group in self.access_data.groupby("job_code"):
            total_users = group["employee_id"].nunique()
            entitlement_counts = group.groupby(
                ["application", "entitlement"]
            )["employee_id"].nunique()

            birthright_entitlements = []
            for (app, ent), count in entitlement_counts.items():
                pct = count / total_users
                if pct >= min_assignment_pct:
                    birthright_entitlements.append({
                        "application": app,
                        "entitlement": ent,
                        "assignment_percentage": round(pct * 100, 1),
                        "user_count": count
                    })

            if birthright_entitlements:
                birthright_roles[job_code] = {
                    "job_code": job_code,
                    "total_users": total_users,
                    "birthright_entitlements": birthright_entitlements
                }

        return birthright_roles

    def detect_role_explosion(self):
        """识别权限重叠过多的角色,表明需要合并。"""
        roles = self.access_data.groupby("job_code").apply(
            lambda x: set(zip(x["application"], x["entitlement"]))
        )

        overlap_report = []
        for (role1, ents1), (role2, ents2) in combinations(roles.items(), 2):
            if len(ents1) == 0 or len(ents2) == 0:
                continue
            overlap = len(ents1 & ents2)
            max_size = max(len(ents1), len(ents2))
            overlap_pct = overlap / max_size * 100

            if overlap_pct > 70:
                overlap_report.append({
                    "role_1": role1,
                    "role_2": role2,
                    "role_1_entitlements": len(ents1),
                    "role_2_entitlements": len(ents2),
                    "overlapping_entitlements": overlap,
                    "overlap_percentage": round(overlap_pct, 1),
                    "recommendation": "CONSOLIDATE" if overlap_pct > 90 else "REVIEW"
                })

        return sorted(overlap_report, key=lambda x: x["overlap_percentage"], reverse=True)

    def find_orphaned_access(self):
        """
        查找不再属于任何角色定义的权限。
        这些是随着时间的推移累积的异常权限。
        """
        # 获取继承权限定义
        birthright = self.mine_birthright_roles(min_assignment_pct=0.5)

        orphaned = []
        for _, row in self.access_data.iterrows():
            job_birthright = birthright.get(row["job_code"], {})
            expected_ents = set()
            for ent in job_birthright.get("birthright_entitlements", []):
                expected_ents.add((ent["application"], ent["entitlement"]))

            current_ent = (row["application"], row["entitlement"])

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

abusing-dpapi-for-credential-access

Extract and decrypt Windows DPAPI-protected secrets (Credential Manager, browser logins/cookies, Wi-Fi credentials, KeePass keys) online or offline using SharpDPAPI, SharpChrome, Mimikatz, or Impacket

abusing-shadow-credentials-for-privesc

Take over Active Directory accounts by writing attacker-controlled public keys to msDS-KeyCredentialLink (Shadow Credentials) with pyWhisker, Whisker, or Certipy, then authenticate via PKINIT to recover the target

achieving-cmmc-level-2-compliance

>-

acquiring-disk-image-with-dd-and-dcfldd

Create forensically sound bit-for-bit disk images with dd or dcfldd on a Linux forensic workstation, preserving evidence integrity through hash verification (MD5/SHA) during acquisition. Use when imaging a suspect drive, USB device, or memory card for investigation, preserving volatile disk evidence during incident response, or producing a verified copy for legal or law-enforcement proceedings before any destructive analysis.

analyzing-active-directory-acl-abuse

Detect dangerous ACL misconfigurations in Active Directory using ldap3

analyzing-android-malware-with-apktool

Perform static analysis of Android APK malware using apktool for resource decompilation, jadx for Java source recovery, and androguard for manifest inspection, dangerous permission-combination detection, and identification of obfuscated code, dynamic code loading, and reflection-based API calls. Use to statically triage a suspicious APK without executing it or to build mobile malware detection rules.

analyzing-api-gateway-access-logs

Parses API Gateway access logs (AWS API Gateway, Kong, Nginx) to detect

analyzing-apt-group-with-mitre-navigator

Query ATT&CK data with attackcti, mitreattack-python, and stix2, then build MITRE ATT&CK Navigator layers and multi-layer heatmap overlays mapping one or more APT groups

analyzing-azure-activity-logs-for-threats

Queries Azure Monitor activity logs and sign-in logs via azure-monitor-query

analyzing-bootkit-and-rootkit-samples

Analyzes bootkit and advanced rootkit malware infecting the Master

analyzing-browser-forensics-with-hindsight

Parse Chromium-based browser databases with Hindsight to extract and correlate browsing history, downloads, cookies, cached content, autofill data, saved passwords, and extensions from Chrome, Edge, Brave, Opera, and Vivaldi into a unified timeline (XLSX, JSON, or SQLite output). Use during incident response, insider-threat investigations, or criminal cases when you need to reconstruct a user

analyzing-campaign-attribution-evidence

Systematically evaluate cyber-campaign evidence to attribute an operation to a threat actor, using the Diamond Model and Analysis of Competing Hypotheses (ACH) to weigh infrastructure overlaps, TTP consistency, malware code similarity, and timing/language artifacts into confidence-weighted attribution assessments. Use when an incident investigation needs a defensible attribution confidence level.

analyzing-certificate-transparency-for-phishing

Monitor Certificate Transparency logs using crt.sh and Certstream to

analyzing-cloud-storage-access-patterns

Detect abnormal access in AWS S3, GCS, and Azure Blob Storage by analyzing CloudTrail Data Events, GCS audit logs, and Azure Storage Analytics for after-hours bulk downloads, new-IP access, and API-call spikes (e.g. GetObject) via statistical baselines and time-series anomaly detection. Use when investigating suspected cloud data exfiltration or building related detection rules.

analyzing-cobalt-strike-beacon-configuration

Extract and analyze Cobalt Strike beacon configuration from PE files

analyzing-cobaltstrike-malleable-c2-profiles

Parse and analyze Cobalt Strike Malleable C2 profiles with dissect.cobaltstrike (profiles and beacon-payload configs) and pyMalleableC2 (AST parsing) to extract HTTP/DNS transforms, URIs, headers, sleep/jitter, and injection behavior, then generate network detection signatures. Use when reverse-engineering a captured malleable profile or building detections against Cobalt Strike Beacon traffic.

analyzing-command-and-control-communication

Analyzes malware C2 communication over HTTP, HTTPS, DNS, and custom

analyzing-cyber-kill-chain

Analyzes intrusion activity against the Lockheed Martin Cyber Kill Chain

analyzing-disk-image-with-autopsy

Perform comprehensive forensic analysis of raw (dd), E01, or AFF disk images with Autopsy and The Sleuth Kit, recovering deleted files, examining metadata and embedded artifacts, keyword searching, and building investigation timelines with visual reports. Use for structured analysis of a forensic disk image or when stakeholders need visual reports from evidence.

analyzing-dns-logs-for-exfiltration

Analyzes DNS query logs to detect data exfiltration via DNS tunneling,

相关技能