| name | building-identity-governance-lifecycle-process |
| description | 构建全面的身份治理(Identity Governance)与生命周期管理流程,包括入职-调岗-离职(Joiner-Mover-Leaver)自动化、角色挖掘、访问申请工作流、定期重新认证以及孤立账户修复,使用 IGA 平台实现。 适用于身份生命周期管理、JML 流程、基于角色的访问配置或身份治理程序设计等相关请求。
|
| domain | cybersecurity |
| subdomain | identity-access-management |
| tags | ["identity-governance","lifecycle-management","JML","access-provisioning","RBAC","IGA"] |
| version | 1.0 |
| author | mahipal |
| license | Apache-2.0 |
构建身份治理生命周期流程
适用场景
- 组织缺乏自动化的入职-调岗-离职(Joiner-Mover-Leaver,JML)身份管理流程
- 访问配置是手动操作,需要数天时间,造成生产力损失和安全漏洞
- 前员工在离职后仍保留系统访问权限(孤立账户)
- 角色爆炸(Role Explosion)导致存在数千个职责不清、权限重叠的角色
- 合规要求(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": [, , ]
},
: {
: ,
: [
,
,
,
,
,
],
: [, ]
},
: {
: ,
: [
,
,
,
,
,
,
,
,
,
],
: [, ]
},
: {
: ,
: [
,
,
,
],
: []
},
: {
: ,
: [
,
,
,
],
: []
}
},
: {
: ,
: ,
: ,
:
}
}
步骤 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": }
params = {
: since_datetime.isoformat(),
: datetime.utcnow().isoformat(),
:
}
workers = []
url =
url:
response = .session.get(url, headers=headers, params=params)
response.raise_for_status()
data = response.json()
workers.extend(data.get(, []))
url = data.get(, )
params = {}
workers
():
worker_data = worker.get(, {})
employment = worker_data.get(, {})
personal = worker_data.get(, {})
event = {
: worker.get(),
: personal.get(, {}).get(),
: personal.get(, {}).get(),
: worker_data.get(),
: employment.get(, {}).get(),
: employment.get(, {}).get(),
: employment.get(, {}).get(),
: employment.get(, {}).get(),
: employment.get(),
: employment.get(, {}).get(),
: employment.get(, {}).get(),
: employment.get(),
: employment.get(),
: employment.get(),
: employment.get(),
}
event[] == event[]:
hire_date = datetime.fromisoformat(event[])
hire_date > datetime.utcnow():
event[] =
:
event[] =
event[] == :
event[] =
event[] == :
event[] =
event[] == :
event[] =
event
():
workers = .fetch_worker_changes(since_datetime)
events = []
worker workers:
event = .map_lifecycle_event(worker)
events.append(event)
.logger.info(
)
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,
: total_users,
: birthright_entitlements
}
birthright_roles
():
roles = .access_data.groupby().apply(
x: ((x[], x[]))
)
overlap_report = []
(role1, ents1), (role2, ents2) combinations(roles.items(), ):
(ents1) == (ents2) == :
overlap = (ents1 & ents2)
max_size = ((ents1), (ents2))
overlap_pct = overlap / max_size *
overlap_pct > :
overlap_report.append({
: role1,
: role2,
: (ents1),
: (ents2),
: overlap,
: (overlap_pct, ),
: overlap_pct >
})
(overlap_report, key= x: x[], reverse=)
():
birthright = .mine_birthright_roles(min_assignment_pct=)
orphaned = []
_, row .access_data.iterrows():
job_birthright = birthright.get(row[], {})
expected_ents = ()
ent job_birthright.get(, []):
expected_ents.add((ent[], ent[]))
current_ent = (row[], row[])
current_ent expected_ents:
orphaned.append({
: row[],
: row[],
: row[],
: row[],
:
})
pd.DataFrame(orphaned)
步骤 4:构建访问申请和审批工作流
实施基于风险的审批自助访问申请:
"""
访问申请工作流引擎
处理自助访问申请,根据所申请权限的风险分类
进行多级审批。
"""
ACCESS_REQUEST_WORKFLOW = {
"risk_levels": {
"LOW": {
"description": "标准业务应用程序",
"examples": ["电子邮件分发组", "SharePoint 团队站点", "标准 SaaS 应用"],
"approval_chain": ["manager"],
"sla_hours": 4,
"auto_approve_if_birthright": True
},
"MEDIUM": {
"description": "敏感数据访问或提升权限",
"examples": ["CRM 管理员", "财务报告", "HR 系统"],
"approval_chain": ["manager", "application_owner"],
"sla_hours": 24,
"auto_approve_if_birthright": False
},
"HIGH": {
"description": "特权访问或受监管数据",
"examples": ["数据库管理员", "云管理员", "PAM 保险库访问"],
"approval_chain": ["manager", "application_owner", "security_team"],
"sla_hours": 48,
"auto_approve_if_birthright": False,
"require_justification": True,
"require_time_limit":
},
: {
: ,
: [, , ],
: [, , , ],
: ,
: ,
: ,
: ,
: ,
:
}
}
}
:
():
.iga = iga_client
.risk_catalog = risk_catalog
():
risk_level = .risk_catalog.get_risk_level(entitlement_id)
workflow = ACCESS_REQUEST_WORKFLOW[][risk_level]
requester = .iga.get_identity(requester_id)
is_birthright = .iga.is_birthright_for_role(
entitlement_id, requester[]
)
is_birthright workflow.get():
._auto_approve(requester_id, entitlement_id, )
workflow.get():
sod_violations = .iga.check_sod(requester_id, entitlement_id)
sod_violations:
{
: ,
: sod_violations,
:
}
request = {
: requester_id,
: entitlement_id,
: risk_level,
: justification,
: duration_days workflow.get(),
: ._build_approval_chain(
requester, workflow[]
),
: workflow[],
:
}
.iga.create_request(request)
():
chain = []
approver_type approver_types:
approver_type == :
chain.append({
: ,
: requester[],
: requester.get()
})
approver_type == :
chain.append({
: ,
: ,
:
})
approver_type == :
chain.append({
: ,
: ,
:
})
approver_type == :
chain.append({
: ,
: ,
:
})
chain
步骤 5:实施孤立账户检测和修复
识别并修复没有活跃身份关联的账户:
"""
孤立账户检测
识别目标系统中在权威 HR 来源中没有对应活跃身份的账户。
"""
class OrphanedAccountDetector:
def __init__(self, hr_connector, app_connectors):
self.hr = hr_connector
self.apps = app_connectors
def detect_orphaned_accounts(self):
"""对照 HR 活跃员工比对应用程序账户。"""
active_employees = set(self.hr.get_active_employee_ids())
orphaned_accounts = []
for app_name, connector in self.apps.items():
app_accounts = connector.get_all_accounts()
for account in app_accounts:
correlated_id = account.get("employee_id") or account.get("correlation_id")
if correlated_id and correlated_id not in active_employees:
termination_info = self.hr.get_termination_info(correlated_id)
orphaned_accounts.append({
"application": app_name,
"account_name": account["username"],
"correlated_employee_id": correlated_id,
"account_status": account.get("status", "unknown"),
"last_login": account.get("last_login"),
"termination_date": termination_info.get("date") termination_info ,
: (
(datetime.utcnow() - termination_info[]).days
termination_info termination_info.get()
),
: ._assess_orphan_risk(account, termination_info)
})
correlated_id:
orphaned_accounts.append({
: app_name,
: account[],
: ,
: account.get(, ),
: account.get(),
: ,
:
})
orphaned_accounts
():
account.get():
termination_info termination_info.get():
account.get() == :
():
plan = []
account orphaned_accounts:
account[] == :
action =
sla =
account[] == :
action =
sla =
:
action =
sla =
plan.append({
**account,
: action,
: sla,
:
})
(plan, key= x: [, , , ].index(x[]))
核心概念
| 术语 | 定义 |
|---|
| 入职-调岗-离职(Joiner-Mover-Leaver,JML) | 核心身份生命周期转换,包括员工入职(Joiner)、角色/部门变更(Mover)和离职(Leaver) |
| 天赋访问权限(Birthright Access) | 根据职位代码、部门或地点自动配置的基线权限,无需提交访问申请 |
| 角色挖掘(Role Mining) | 通过识别相似职能中的常见权限分组,分析现有访问模式以推导角色定义 |
| 孤立账户(Orphaned Account) | 在权威 HR 来源中不再有对应活跃身份的应用账户,代表安全风险 |
| 权威来源(Authoritative Source) | 记录系统(通常是 HR),作为身份属性和就业状态的单一真相来源 |
| 访问申请工作流(Access Request Workflow) | 使用户能够申请额外权限的自助服务流程,带有基于风险的审批路由 |
工具与系统
- SailPoint IdentityIQ/IdentityNow:企业 IGA 平台,用于生命周期管理、访问认证和自动化配置
- Saviynt Enterprise Identity Cloud:云原生 IGA,包含身份仓库、访问治理和应用访问管理
- Microsoft Entra ID Governance:身份治理功能,包括生命周期工作流、访问审查和权限管理
- One Identity Manager:具备业务角色管理、证明和 IT 商店访问申请功能的 IGA 解决方案
常见场景
场景:为 10,000 名员工的组织构建 JML 流程
场景背景:快速成长的公司没有自动化身份生命周期。IT 手动创建账户,新员工需要 3-5 天才能就绪。离职员工保留访问权限长达数周。审计发现 45 个应用程序中存在 2,300 个孤立账户。
方法:
- 将 Workday 集成为权威来源,每日向 IGA 平台同步增量数据
- 挖掘现有访问模式,为前 20 个职位代码(涵盖 80% 的员工)定义天赋角色
- 在入职日期前 7 天触发预入职配置,涵盖 AD、电子邮件和天赋应用
- 构建离职工作流,在 HR 状态变更后 1 小时内禁用所有访问权限
- 构建调岗工作流,当职位代码或部门变更时重新计算角色
- 部署带有基于风险审批链的自助访问申请门户
- 运行孤立账户检测,识别并修复现有的 2,300 个孤立账户
- 安排季度访问认证以防止访问权限积累
常见陷阱:
- 未定义单一权威来源导致多个 HR 系统的身份数据冲突
- 未经业务验证就进行角色挖掘,导致创建与组织结构不匹配的技术角色
- 在未留知识转移宽限期的情况下自动化离职流程,令业务经理不满
- 未处理 HR 系统之外存在的承包商和供应商身份
输出格式
身份治理生命周期报告
=======================================
权威来源: Workday
IGA 平台: SailPoint IdentityIQ
身份总数: 10,247
在职员工: 9,834
承包商: 413
生命周期自动化
入职(预入职)SLA: 目标:0 天 | 实际:平均 0.2 天
调岗处理 SLA: 目标:1 天 | 实际:平均 0.8 天
离职禁用 SLA: 目标:1 小时 | 实际:平均 0.5 小时
配置指标(过去 30 天)
新入职员工: 187
自动配置: 174(93.0%)
人工干预: 13(7.0%)
角色变更处理: 89
离职处理: 43
1 小时 SLA 内: 41(95.3%)
角色治理
已定义角色: 127
天赋角色: 48
每角色平均权限数: 12.3
重叠度 > 70%: 8 对(建议整合)
孤立账户
检测到: 23
严重: 2(特权账户)
高: 8
中: 13
已修复(30 天): 19
未处理: 4
访问申请
提交: 342
自动审批(天赋): 87(25.4%)
已批准: 231(67.5%)
已拒绝: 24(7.0%)
平均审批时间: 6.2 小时
SOD 违规标记: 12