ZITADEL领域模型:身份实体设计与关系
引言:身份管理的核心挑战与解决方案
在现代分布式系统中,身份管理(Identity Management)面临着多维度的挑战:多租户架构下的资源隔离、复杂权限模型的灵活配置、跨系统身份联邦以及用户隐私保护等。ZITADEL作为开源身份基础设施,通过精心设计的领域模型(Domain Model)解决了这些问题。本文将深入剖析ZITADEL的核心实体设计与关系,帮助开发者理解其架构精髓,构建安全可控的身份系统。
读完本文后,你将能够:
- 掌握ZITADEL核心领域实体的设计原理
- 理解身份实体间的复杂关系网络
- 学会基于领域模型进行权限设计与访问控制
- 应用实体状态管理确保系统一致性
- 优化多租户环境下的身份资源组织
核心实体设计:从用户到权限的完整谱系
1. 用户实体(User):身份的核心载体
ZITADEL将用户分为两类核心类型,通过UserType
枚举明确区分:
type UserType int32
const (
UserTypeUnspecified UserType = iota // 未指定类型
UserTypeHuman // 人类用户
UserTypeMachine // 机器用户
userTypeCount
)
1.1 人类用户(Human)
人类用户包含丰富的身份属性和认证信息,定义于human.go
中:
type Human struct {
es_models.ObjectRoot // 事件溯源基础字段
Username string // 用户名
State UserState // 用户状态
*Password // 密码信息
HashedPassword string // 哈希后的密码
*Profile // 个人资料
*Email // 电子邮箱
*Phone // 电话号码
*Address // 地址信息
}
核心功能:
- 多因素认证支持(TOTP、U2F、Passwordless等)
- 个人资料管理(姓名、昵称、性别等)
- 联系方式验证(邮箱、电话)
- 密码策略执行(复杂度、过期时间)
1.2 机器用户(Machine)
机器用户用于服务间认证,定义于machine.go
:
type Machine struct {
models.ObjectRoot
Username string // 机器用户名
State UserState // 状态
Name string // 机器名称
Description string // 描述信息
}
应用场景:
- 服务间API调用认证
- 自动化任务执行授权
- 物联网设备身份标识
1.3 用户状态管理
用户生命周期通过UserState
枚举严格控制:
type UserState int32
const (
UserStateUnspecified UserState = iota // 未指定
UserStateActive // 活跃
UserStateInactive // 非活跃
UserStateDeleted // 已删除
UserStateLocked // 已锁定
UserStateSuspend // 已暂停
UserStateInitial // 初始状态
userStateCount
)
状态转换逻辑确保用户身份的安全性与可追溯性,例如:
IsEnabled()
方法检查用户是否允许登录Exists()
方法判断用户是否处于有效状态
2. 组织实体(Org):多租户的核心容器
组织是ZITADEL实现多租户架构的基础单元,定义于org.go
:
type Org struct {
models.ObjectRoot
State OrgState // 组织状态
Name string // 组织名称
PrimaryDomain string // 主域名
Domains []*OrgDomain // 域名列表
}
核心特性:
- 域名管理:支持多域名绑定与验证
- 状态控制:通过
OrgState
枚举管理生命周期 - 资源隔离:组织内实体逻辑隔离
组织状态管理与用户类似,通过OrgState
枚举实现:
type OrgState int32
const (
OrgStateUnspecified OrgState = iota // 未指定
OrgStateActive // 活跃
OrgStateInactive // 非活跃
OrgStateRemoved // 已删除
)
3. 项目与应用:资源访问的入口
3.1 项目实体(Project)
项目是应用的集合容器,定义于project.go
:
type Project struct {
models.ObjectRoot
State ProjectState // 状态
Name string // 名称
ProjectRoleAssertion bool // 角色断言开关
ProjectRoleCheck bool // 角色检查开关
HasProjectCheck bool // 项目检查开关
PrivateLabelingSetting PrivateLabelingSetting // 私有标签设置
}
项目状态管理确保资源可控:
type ProjectState int32
const (
ProjectStateUnspecified ProjectState = iota // 未指定
ProjectStateActive // 活跃
ProjectStateInactive // 非活跃
ProjectStateRemoved // 已删除
)
3.2 应用实体(Application)
应用是资源访问的具体入口,定义于application.go
:
type Application interface {
GetAppID() string
GetApplicationName() string
GetState() AppState
}
type AppState int32
const (
AppStateUnspecified AppState = iota // 未指定
AppStateActive // 活跃
AppStateInactive // 非活跃
AppStateRemoved // 已删除
)
具体应用类型:
- OAuth应用(
application_oauth.go
) - OIDC应用(
application_oidc.go
) - SAML应用(
application_saml.go
)
4. 身份提供商(IDP):联邦身份的桥梁
身份提供商实现外部身份联邦,定义于idp.go
:
type IDPType int32
const (
IDPTypeUnspecified IDPType = iota // 未指定
IDPTypeOIDC // OIDC提供商
IDPTypeJWT // JWT提供商
IDPTypeOAuth // OAuth提供商
IDPTypeLDAP // LDAP提供商
IDPTypeAzureAD // Azure AD
IDPTypeGitHub // GitHub
IDPTypeGitHubEnterprise // GitHub企业版
IDPTypeGitLab // GitLab
IDPTypeGitLabSelfHosted // 自托管GitLab
IDPTypeGoogle // Google
IDPTypeApple // Apple
IDPTypeSAML // SAML提供商
)
核心功能:
- 多类型身份提供商支持
- 身份联合与自动链接
- 登录流程集成
5. 权限控制:从角色到权限的映射
5.1 权限常量定义
系统权限在permission.go
中集中定义:
const (
PermissionUserWrite = "user.write"
PermissionUserRead = "user.read"
PermissionUserDelete = "user.delete"
PermissionUserCredentialWrite = "user.credential.write"
PermissionSessionWrite = "session.write"
PermissionSessionRead = "session.read"
// ... 更多权限常量
)
5.2 角色定义
角色在roles.go
中定义,包含系统预定义角色:
const (
IAMRolePrefix = "IAM"
OrgRolePrefix = "ORG"
ProjectRolePrefix = "PROJECT"
RoleOrgOwner = "ORG_OWNER"
RoleOrgProjectCreator = "ORG_PROJECT_CREATOR"
RoleIAMOwner = "IAM_OWNER"
// ... 更多角色常量
)
实体关系网络:构建身份生态系统
1. 核心实体关系图
2. 多对多关系:通过Grant实现灵活授权
2.1 项目授权(ProjectGrant)
项目授权允许组织间共享项目资源,定义于project_grant.go
:
type ProjectGrant struct {
es_models.ObjectRoot
GrantID string // 授权ID
GrantedOrgID string // 被授权组织ID
State ProjectGrantState // 状态
RoleKeys []string // 角色列表
}
2.2 用户授权(UserGrant)
用户授权直接将项目角色授予用户,定义于user_grant.go
:
type UserGrant struct {
es_models.ObjectRoot
State UserGrantState // 状态
UserID string // 用户ID
ProjectID string // 项目ID
ProjectGrantID string // 项目授权ID
RoleKeys []string // 角色列表
}
3. 成员关系(Member):基于角色的访问控制
成员关系将用户与资源(组织、项目等)关联,并赋予特定角色,定义于member.go
:
type Member struct {
es_models.ObjectRoot
UserID string // 用户ID
Roles []string // 角色列表
}
应用场景:
- 组织成员:用户在组织中担任的角色
- 项目成员:用户在项目中拥有的权限
- IAM成员:全局管理员角色分配
身份生命周期管理:状态机与业务规则
1. 用户状态流转
2. 组织与项目状态管理
组织和项目的生命周期管理类似,以组织为例:
func (s OrgState) Exists() bool {
return s != OrgStateRemoved && s != OrgStateUnspecified
}
func (s OrgState) Valid() bool {
return s > OrgStateUnspecified && s < orgStateMax
}
3. 业务规则验证
ZITADEL在领域模型中嵌入了丰富的业务规则验证,例如:
func (u *Human) Normalize() error {
if u.Username == "" {
return zerrors.ThrowInvalidArgument(nil, "COMMAND-00p2b", "Errors.User.Username.Empty")
}
if err := u.Profile.Validate(); err != nil {
return err
}
if err := u.Email.Validate(); err != nil {
return err
}
// ... 更多验证逻辑
return nil
}
实践指南:领域模型的应用场景
1. 多租户权限设计示例
// 创建组织管理员
func CreateOrgOwner(orgID, userID string) *Member {
return NewMember(orgID, userID, RoleOrgOwner)
}
// 为项目添加开发人员
func AddDeveloperToProject(projectID, userID string) *Member {
return NewMember(projectID, userID, "PROJECT_DEVELOPER")
}
// 跨组织共享项目
func GrantProjectToOrg(projectID, orgID string, roles []string) *ProjectGrant {
return &ProjectGrant{
ObjectRoot: es_models.ObjectRoot{AggregateID: projectID},
GrantedOrgID: orgID,
RoleKeys: roles,
State: ProjectGrantStateActive,
}
}
2. 身份认证流程中的领域模型应用
3. 权限检查实现
// 检查用户是否具有特定权限
func CheckPermission(ctx context.Context, userID, permission, resourceID string) bool {
// 1. 获取用户的所有角色
roles := GetUserRoles(ctx, userID, resourceID)
// 2. 检查角色是否包含所需权限
for _, role := range roles {
if roleHasPermission(role, permission) {
return true
}
}
return false
}
// 角色权限映射示例
var rolePermissions = map[string][]string{
RoleOrgOwner: {
PermissionUserWrite,
PermissionUserRead,
PermissionUserDelete,
PermissionProjectCreate,
// ... 其他权限
},
// ... 其他角色
}
高级主题:领域驱动设计的最佳实践
1. 事件溯源与领域事件
ZITADEL采用事件溯源模式,所有领域对象变更都通过事件记录:
// 领域对象基础类
type ObjectRoot struct {
AggregateID string
ResourceOwner string
Sequence uint64
CreationDate time.Time
ChangeDate time.Time
}
优势:
- 完整的审计跟踪
- 数据恢复能力
- 状态变更可追溯
2. 值对象的使用
ZITADEL大量使用值对象封装相关属性,例如:
// 电子邮件值对象
type Email struct {
EmailAddress string
IsVerified bool
VerifiedAt time.Time
ChangeDate time.Time
}
// 密码值对象
type Password struct {
SecretString string
ChangeRequired bool
Expiry time.Time
// ... 其他密码相关属性
}
优势:
- 数据完整性保证
- 业务规则封装
- 代码复用
3. 领域服务与领域规则
复杂业务逻辑通过领域服务实现:
// 密码哈希服务
func (u *Human) HashPasswordIfExisting(ctx context.Context, policy *PasswordComplexityPolicy, hasher *crypto.Hasher, onetime bool) error {
if u.Password != nil {
u.Password.ChangeRequired = onetime
return u.Password.HashPasswordIfExisting(ctx, policy, hasher)
}
return nil
}
总结与展望
ZITADEL的领域模型通过精心设计的实体与关系,构建了强大而灵活的身份管理基础。其核心优势在于:
-
实体设计的精确性:通过精细的类型划分(Human/Machine)和状态管理,确保身份数据的准确性和安全性。
-
关系模型的灵活性:通过Member和Grant机制,实现了复杂的权限分配和资源共享,满足多租户场景需求。
-
领域驱动的设计思想:将业务规则嵌入领域模型,确保核心逻辑的内聚性和可维护性。
-
可扩展性架构:模块化的实体设计和事件溯源模式,为未来功能扩展提供了坚实基础。
随着身份管理领域的不断发展,ZITADEL的领域模型也将持续演进,特别是在以下方向:
- 更细粒度的权限控制:支持属性基础访问控制(ABAC)
- 增强的身份联邦能力:扩展更多身份提供商类型
- 隐私增强技术:集成零知识证明等高级认证机制
- 自适应认证:基于风险评估动态调整认证流程
掌握ZITADEL的领域模型,不仅有助于深入理解身份管理系统的设计原理,也为构建安全、灵活的分布式系统提供了宝贵的架构参考。无论是企业级SaaS应用,还是复杂的物联网生态,ZITADEL的领域模型都能为身份基础设施提供坚实的理论基础和实践指导。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考