XINFRA 安全·认证·数据报告¶
生成日期:2026-08-27 | 基于源码深度分析
一、认证架构总览¶
XINFRA 实现了多协议统一认证网关,支持本地登录、SAML 2.0 SSO、OAuth 2.0/OIDC 三种认证方式,并通过 JWT 实现会话管理。
graph TD
subgraph "认证网关层"
A["本地登录\nPOST /login"]
B["SAML 2.0 SSO\nGET /login/internal-sso"]
C["OAuth 2.0 / OIDC\n/auth/oauth/*"]
end
A --> JWT["JWT 签发/校验\nHS256/RS256"]
B --> JWT
C --> JWT
JWT --> MW["AuthMiddleware\nBearer Token"]
style JWT fill:#fff3e0
style MW fill:#e8f5e9
💡 统一认证网关
三种认证方式最终都汇聚到 JWT 签发/校验,后端通过统一的 AuthMiddleware 处理所有请求的认证。SSO 启用时本地登录自动禁用,保证认证入口收敛。
二、本地登录¶
端点: POST /auth/api/v1/login
流程:
- 接收
username+password - 查询数据库用户记录
- 验证密码哈希
- 签发 HS256 JWT(Claims: UserID, Username, Email, DisplayName, IsAdmin)
- 返回 token
限制: SSO 启用时(SSO_ENABLED=true)禁用本地登录
三、SAML 2.0 SSO¶
3.1 组件¶
| 组件 | 路径 | 职责 |
|---|---|---|
sso/login.go |
internal/sso/ |
SAML SP 核心实现 |
sso/metadata.go |
internal/sso/ |
SP 元数据 XML 生成 |
handler/saml.go |
internal/handler/ |
HTTP Handler |
3.2 登录流程¶
sequenceDiagram
participant U as 用户
participant FE as 前端
participant BE as 后端
participant IDP as SAML IDP
U->>FE: 点击 SSO 登录
FE->>BE: GET /login/internal-sso
BE->>BE: BuildLoginRedirect()
BE->>BE: 构建 AuthnRequest (deflate+base64)
BE-->>FE: 302 重定向到 IDP
FE->>IDP: 用户在 IDP 认证
IDP-->>BE: POST SAMLResponse 到 /saml/acs
BE->>BE: DecodeSAMLResponse()
BE->>BE: 解密断言 (RSA-OAEP + AES)
BE->>BE: 创建/更新用户 + 签发 JWT
BE-->>FE: 重定向回前端 (携带 sso_token)
💡 SAML 2.0 实现
完整实现 SAML 2.0 SP:AuthnRequest 构建(deflate + base64 编码)→ HTTP-Redirect 绑定 → IDP 认证 → SAMLResponse 解析。支持加密断言解密(RSA-OAEP 密钥传输 + AES-128/192/256-CBC/GCM 数据加密)。
3.3 加密算法支持¶
- 密钥传输: RSA-OAEP
- 数据加密:
- AES-128-CBC / AES-192-CBC / AES-256-CBC
- AES-128-GCM / AES-192-GCM / AES-256-GCM
3.4 SP 元数据¶
端点: GET /auth/api/v1/saml/metadata
生成标准 SAML SP 元数据 XML,包含: - EntityDescriptor - SPSSODescriptor - 签名/加密 KeyDescriptor - AssertionConsumerService (ACS) URL
3.5 登出¶
端点: GET/POST /auth/api/v1/logout
- 清除本地 JWT(Redis token 吊销)
- 可选重定向到 SAML IDP 登出 URL
四、OAuth 2.0 / OIDC Provider¶
4.1 端点¶
| 端点 | 路径 | 说明 |
|---|---|---|
| Discovery | /auth/.well-known/openid-configuration |
OIDC 发现文档 |
| Authorize | /auth/oauth/authorize |
授权端点 |
| Token | /auth/oauth/token |
Token 端点 |
| JWKS | /auth/oauth/jwks |
公钥端点 |
| UserInfo | /auth/oauth/userinfo |
用户信息端点 |
4.2 支持的 Client¶
| Client ID | 用途 | Token 类型 |
|---|---|---|
wayne |
Wayne K8s 管理平台 | HS256 access_token |
clouddm |
CloudDM 数据库管理 | HS256 access_token |
archery |
Archery SQL 审核 | RS256 PlatformToken |
4.3 授权码流程¶
sequenceDiagram
participant FE as 前端
participant BE as 后端
participant Redis as Redis
FE->>BE: GET /oauth/authorize?client_id=...
BE->>BE: 用户认证 + 生成 OAuth Code
BE->>Redis: SetNX + TTL 存储 Code
BE-->>FE: 302 redirect_uri?code=...
FE->>BE: POST /oauth/token (code)
BE->>Redis: 校验 + 消费 Code(一次性)
BE-->>FE: access_token + id_token
💡 OAuth2 授权码流程
OAuth Code 使用 Redis SetNX + TTL 存储,保证一次性消费。Token 端点按 client 差异化签发:Wayen/CloudDM 使用 HS256 access_token,Archery 使用 RS256 PlatformToken。
4.4 Token 签发¶
- access_token: HS256,包含 UserID, Username, Email, IsAdmin
- id_token: RS256,符合 OIDC 规范,包含 UserID, Username, Email, EmailVerified, Name, IsAdmin, Nonce
- Archery 特殊处理: 签发 RS256 PlatformToken 替代 HS256 access_token
4.5 Token 吊销¶
- 通过 Redis key 检查实现
- 登出时将 token 加入吊销列表
- AuthMiddleware 校验时可选检查 Redis 吊销状态
五、JWT 机制¶
5.1 Claims 结构¶
| 类型 | 算法 | 用途 | 包含字段 |
|---|---|---|---|
Claims |
HS256 | 访问令牌 | UserID, Username, Email, DisplayName, IsAdmin |
OAuthCodeClaims |
HS256 | OAuth 授权码 | UserID, ClientID, RedirectURI, Scope, Nonce |
IDTokenClaims |
RS256 | OIDC ID Token | UserID, Username, Email, EmailVerified, Name, IsAdmin, Nonce |
PlatformTokenClaims |
RS256 | 子系统平台令牌 | UserID, Username, Email, DisplayName, IsAdmin |
5.2 密钥管理¶
- HS256: 通过
JWT_SECRET环境变量配置 - RS256: RSA 私钥从文件加载(支持 PKCS1/PKCS8 格式)
- JWK 构建:从 RSA 公钥导出
- KeyID 生成:SHA256 前 8 字节 Base64
- 通过 JWKS 端点暴露公钥
5.3 配置¶
| 配置项 | 说明 |
|---|---|
JWT_SECRET |
HS256 密钥 |
JWT_ISSUER |
签发者(默认 authserver) |
JWT_TTL_MINUTES |
Token 有效期(默认 120 分钟) |
六、权限模型¶
6.1 RBAC 架构¶
graph TD
subgraph "平台级权限"
P1["PlatformRoleBinding\nUserID → Role (platform_admin)"]
end
subgraph "业务线级权限"
B1["BusinessLineUser\nUserID → Role (owner/member)"]
B2["BusinessLinePermission\nUserID → Permission"]
end
subgraph "子系统级权限"
S1["Wayne\nNamespace Role Binding"]
S2["Archery\nResource Group / Permission Group"]
end
P1 --> B1
B1 --> S1
B1 --> S2
style P1 fill:#e1f5fe
style B1 fill:#fff3e0
style B2 fill:#fff3e0
💡 三级 RBAC
权限模型分为三级:平台级(platform_admin 管理员)→ 业务线级(owner/member + 细粒度权限)→ 子系统级(Wayne 命名空间角色 + Archery 资源组/权限组)。前端通过四级路由守卫实现权限控制。
6.2 平台级角色¶
platform_admin— 平台管理员,存储在PlatformRoleBinding表- 系统用户
xinfra-platform在初始化时自动创建并授予此角色
6.3 业务线级角色¶
owner— 业务线管理员,拥有所有业务线权限member— 业务线成员,按BusinessLinePermission授予权限
6.4 权限清单¶
平台级权限(platformPermission):
business_line.manage— 业务线管理
业务线级权限(capability):
| 权限 | 说明 |
|---|---|
subsystem.wayne.manage |
Wayne 子系统管理(含 role.grant + role.revoke) |
subsystem.wayne.read |
Wayne 子系统只读 |
subsystem.archery.manage |
Archery 子系统管理 |
subsystem.archery.read |
Archery 子系统只读 |
machine.view / machine.manage |
机器资源查看/管理 |
delivery.view / delivery.deploy / delivery.credentials |
交付系统查看/部署/凭证 |
execution_profile.manage |
执行配置管理 |
audit.login.view / audit.operation.view |
审计日志查看 |
6.5 前端权限检查¶
四级检查(路由守卫):
platformPermission—authStore.hasPlatformPermission()businessLineMember—businessLineStore.current?.id存在性businessLineOwner—businessLineStore.isCurrentAdmincapability/capabilities—authStore.hasAnyBusinessLinePermission()
权限别名映射(前端硬编码):
subsystem.wayne.manage→subsystem.wayne.role.grant,subsystem.wayne.role.revokemachine.view→machine.read,machine.credential.readmachine.manage→machine.create/update/delete/credential.manage/syncdelivery.view→delivery.target.read,delivery.readdelivery.deploy→delivery.createdelivery.credentials→delivery.credential.revealexecution_profile.manage→execution_profile.publish
七、审计日志¶
7.1 数据模型¶
AuditLog 表:
| 字段 | 类型 | 说明 |
|---|---|---|
ActorUserID |
uint | 操作者 ID |
ActorUsername |
string | 操作者用户名 |
ClientIP |
string | 客户端 IP |
Action |
string | 操作类型 |
ResourceType |
string | 资源类型 |
ResourceID |
string | 资源 ID |
ScopeType |
string | 作用域类型 |
ScopeID |
string | 作用域 ID |
BusinessLineID |
uint | 业务线 ID |
Decision |
string | 决策结果 |
Reason |
string | 原因 |
Metadata |
JSON | 元数据 |
7.2 审计分类¶
| 分类 | 端点 | 内容 |
|---|---|---|
| 登录审计 | GET /auth/api/v1/audit/login |
登录/登出事件 |
| 业务线权限审计 | GET /auth/api/v1/audit/operations?category=business_line_permission |
权限授予/撤销 |
| 子系统授权审计 | GET /auth/api/v1/audit/operations?category=subsystem_authorization |
子系统角色绑定 |
| 服务交付审计 | GET /auth/api/v1/audit/operations?category=service_delivery |
交付任务操作 |
7.3 写入机制¶
AuditService异步写入(不阻塞业务请求)- 支持分页查询
八、数据库设计¶
8.1 连接与迁移¶
- 数据库: MySQL 8.0
- ORM: GORM(
gorm.io/driver/mysql) - 迁移:
AUTO_MIGRATE=true时自动迁移 40+ 张表 - 初始化:
SeedDefaults创建系统平台用户xinfra-platform
8.2 核心数据模型分组¶
用户与权限(7 张表)¶
User— 用户主表(软删除)WayenCredential— Wayne 平台凭据(软删除)BusinessLine— 业务线BusinessLineUser— 业务线成员关系PlatformRoleBinding— 平台角色绑定BusinessLinePermission— 业务线权限BusinessLineWayneNamespace/BusinessLineSinaOrganization— 业务线映射
交付系统(12+ 张表)¶
DeliveryTask— 交付任务(16 种状态)ResourceQuota/ResourceReservation— 配额与预留MySQLPrecheckLease— 预检租约(唯一约束)DeploymentResult/DeploymentCredential— 部署结果与凭证VaultDatabaseAccount— Vault 数据库账号ServiceConfig— 服务配置台账MySQLDynamicVariable— MySQL 动态变量(12 个种子数据)ExecutionJob/RollbackJob— 执行与回滚TaskEvent— 任务事件AWXRuntimeInventory— AWX 运行时 Inventory
MySQL HA(5 张表)¶
MySQLCluster— 集群(HAMode: none/mha)MySQLInstance— 实例(Role: primary/replica)MySQLReplicationChannel— 复制通道MySQLInternalCredential— 内部凭据(Vault 注册后清除)ServerIDAllocation— Server ID 分配
PostgreSQL HA(8 张表)¶
PostgreSQLCluster— 集群PostgreSQLInstance— 实例PostgreSQLResourceUsage— 资源使用PostgreSQLCloudDMReservation— CloudDM 预留PostgreSQLHAOperation— HA 操作(14 种状态)PostgreSQLHAHostPlan— 主机计划PostgreSQLHAAudit— HA 审计PostgreSQLHAControlOperation/PostgreSQLHAJobLog
机器与 Receptor(6 张表)¶
MachineResource— 机器资源MachineCredential— 机器凭据MachineSyncState— 同步状态ReceptorNode— Receptor 节点ReceptorProvisioningTask/ReceptorProvisioningEvent— 供应任务SSHCredential— SSH 凭据(PGP 加密)
执行配置(3 张表)¶
ExecutionProfileRelease— 配置发布ExecutionBindingRelease— 绑定发布TaskExecutionSnapshot— 执行快照
Archery 集成(5 张表)¶
BusinessLineArcheryResourceGroup/BusinessLineArcheryPermissionGroupArcheryAccessSyncTask— 同步任务ArcheryInstanceBinding/ArcheryUserBinding
审计(1 张表)¶
AuditLog— 统一审计日志
8.3 迁移逻辑¶
AutoMigrate 包含复杂的索引迁移逻辑:
- RBAC 迁移:从 users.is_admin 导入 platform_role_bindings
- 业务线角色迁移:permission=0 映射为 owner
- PostgreSQL HA UUID 准备:将空字符串转为 NULL 以支持唯一索引
- MySQL/PostgreSQL 台账索引重建:活跃集群/实例的唯一约束
- SSH 凭据 schema 迁移
- MySQL 动态变量种子数据
九、缓存策略¶
9.1 Redis 使用¶
| 用途 | Key 模式 | TTL |
|---|---|---|
| OAuth Code 存储 | oauth:code:{code} |
可配置(OAuthCodeTTL) |
| Token 吊销 | token:revoked:{token} |
JWT 剩余有效期 |
| Wayne 容器数据缓存 | 业务相关 | 可配置(CacheTTL) |
9.2 配置¶
| 配置项 | 说明 |
|---|---|
REDIS_ENABLED |
是否启用 Redis |
REDIS_ADDR |
Redis 地址 |
REDIS_PASSWORD |
Redis 密码 |
REDIS_DB |
数据库编号 |
REDIS_CONNECT_TIMEOUT / REDIS_READ_TIMEOUT / REDIS_WRITE_TIMEOUT |
超时配置 |
十、Vault 密钥管理¶
10.1 架构¶
graph TD
subgraph VaultServer["Vault Server"]
KV["KV v2\n通用密钥"]
DB["Database Secrets Engine\n数据库凭据自动化"]
end
AppRole["AppRole Auth"] --> KV
StaticRole["Static Role"] --> DB
AppRole -->|"role_id + secret_id"| VaultServer
DB -->|"MySQL/PostgreSQL 连接"| DB
style VaultServer fill:#e1f5fe
style AppRole fill:#e8f5e9
💡 Vault 集成
Vault 通过 AppRole 认证获取 token,支持自动续期(TTL 前 1 分钟刷新)和 401/403 请求重试。Database Secrets Engine 实现数据库凭据全生命周期自动化:连接注册 → Static Role 登记 → 凭据读取 → 清理。
10.2 认证方式¶
- AppRole 认证: 通过
role_id+secret_id获取 token - 自动续期: TTL 前 1 分钟自动刷新
- 请求重试: 401/403 自动重新认证后重试一次
10.3 KV v2 操作¶
| 方法 | 说明 |
|---|---|
ReadKVV2(path, key) |
读取密钥 |
WriteKVV2(path, data) |
写入密钥 |
DeleteKVV2(path, key) |
删除密钥 |
10.4 Database Secrets Engine¶
MySQL 连接注册¶
- plugin_name:mysql-database-plugin
- 校验 skip_static_role_import_rotation 是否生效
Static Role 注册¶
- 读取database/static-creds/<role> 验证凭据可用性
- 支持 skip_import_rotation 避免立即轮换密码
凭据读取¶
- 读取 Static Role 当前凭据(只用于运行时,不持久化)清理¶
10.5 配置¶
| 配置项 | 说明 |
|---|---|
VAULT_ENABLED |
是否启用 Vault |
VAULT_ADDR |
Vault 地址 |
VAULT_NAMESPACE |
Vault Namespace |
VAULT_TOKEN |
Vault Token(备用) |
VAULT_KVV2_MOUNT_PATH |
KV v2 挂载路径 |
VAULT_APPROLE_ROLE_ID / VAULT_APPROLE_SECRET_ID |
AppRole 凭据 |
VAULT_DATABASE_MYSQL_CONNECTION_NAME |
MySQL 连接名 |
VAULT_DATABASE_STATIC_ROLE_PREFIX |
Static Role 前缀 |
VAULT_DATABASE_ROTATION_PERIOD |
密码轮换周期(默认 87600h = 10 年) |
十一、凭据安全¶
11.1 SSH 凭据加密¶
SSHCredential 模型:
PrivateKeyCiphertext— PGP 加密的私钥EncryptedDataKey— 加密的 DataKeyKnownHosts— 已知主机HostKeyPolicy— 主机密钥策略
加密方案:
- 生成随机 DataKey
- 使用 DataKey 的 AES 密钥加密私钥
- 使用 PGP 公钥加密 DataKey
- 存储加密后的私钥和加密后的 DataKey
11.2 交付凭据¶
DeploymentCredential 模型:
Ciphertext— 加密的凭据Nonce— 加密 nonceStatus— 状态(pending/revealed/expired)ViewedBy— 查看者
凭证揭示:
POST /delivery/tasks/:id/credentials/reveal- 支持 JSON 和 XLSX 下载两种格式
- 一次性揭示,标记为
revealed
11.3 临时文件安全¶
Ansible playbook 中的凭据处理:
# 创建临时文件
- tempfile:
state: file
suffix: .cred
register: cred_file
# 写入凭据
- copy:
content: "{{ password }}"
dest: "{{ cred_file.path }}"
mode: '0600'
# 使用后清理
- file:
path: "{{ cred_file.path }}"
state: absent
使用 mktemp + chmod 600 + trap 模式,避免命令行泄露。
十二、Wayne 服务间签名¶
12.1 签名方案¶
算法: HMAC-SHA256
签名 Payload:
Headers:
X-Wayne-Service— 服务名X-Wayne-Timestamp— 时间戳X-Wayne-Nonce— 随机 nonceX-Wayne-Signature— HMAC-SHA256 签名
12.2 验签¶
- 常量时间比较(
hmac.Equal),防止时序攻击 - 校验时间戳有效期
十三、安全配置汇总¶
13.1 传输安全¶
- K8s 内部通信使用 HTTP(Service DNS)
- 外部访问通过 NodePort 暴露
- SAML SP 证书路径可配置
13.2 认证安全¶
- JWT Token 有效期可配置(默认 120 分钟)
- Token 吊销通过 Redis 实现
- SAML 加密断言支持 RSA-OAEP + AES-CBC/GCM
- OAuth Code 一次性使用(Redis SetNX + 消费)
13.3 数据安全¶
- SSH 凭据 PGP + AES 加密
- 交付凭据 AES 加密 + 一次性揭示
- Vault 集成实现密钥自动化管理
- 数据库密码定期轮换(默认 10 年)
13.4 访问控制¶
- 三级 RBAC:平台级 → 业务线级 → 子系统级
- 路由级权限控制(路由守卫四级检查)
- API 级权限控制(AuthMiddleware + 业务逻辑校验)
- 全链路审计日志
💡 安全设计原则
- 纵深防御: 传输层(NodePort)→ 认证层(JWT/SAML/OAuth)→ 授权层(三级 RBAC)→ 审计层(全链路日志)
- 最小权限: SSH 凭据 PGP 加密、交付凭据一次性揭示、Vault 自动轮换
- 零信任: OAuth Code 一次性消费、Token 吊销、常量时间签名验证防时序攻击