PLATFORM SYSTEMS
Security
主要威胁:
View source1. 安全原则
- 最小权限。
- 控制平面不 SSH Node host。
- token 哈希存储。
- 配置校验。
- 租户隔离。
- 敏感日志最小化。
- 所有关键操作可审计。
2. 威胁模型
主要威胁:
- enrollment token 泄露。
- subscription token 泄露。
- Edge Runtime device key 泄露。
- Edge Runtime identity 文件被复制。
- 租户越权访问。
- 恶意配置下发。
- 未授权 Traffic Entry 使用 Traffic Exit。
- 日志泄露用户凭证。
3. Token 安全
Enrollment Token
要求:
- 临时 enrollment / re-enrollment 授权。
- 短有效期。
- 绑定租户。
- 可绑定 initial capability intent。
- 哈希存储。
- 使用策略可以是 single-use 或 multi-use same-device。
- 不作为 Edge Runtime 长期身份。
Subscription Token
要求:
- 哈希存储。
- 可轮换。
- 可吊销。
- 可限流。
- 不记录完整 token。
Console OIDC Tokens
要求:
- 登录响应使用标准 OIDC / OAuth token 字段:
access_token、token_type、expires_in、refresh_token、id_token、scope。 access_token用于 API Bearer 鉴权。id_token用于客户端识别登录主体,不用于 API 权限判断。refresh_token用于换取新的access_token和id_token。- token claim 必须包含
iss、sub、aud、iat、exp。 - token claim 使用
typ区分access_token、id_token、refresh_token。 - token claim 使用
sid绑定服务端 auth session。 iss和aud必须通过配置固定,禁止在请求中动态信任。refresh_token是签名 token,但必须与服务端auth_sessions.refresh_token_hash匹配。- refresh 会轮换新的
refresh_token,并更新 session hash、last_seen_at和expires_at。 - API Bearer 鉴权必须校验 access token 中的
sid对应 active auth session。 - session 被 revoke 后,对应 access token 和 refresh token 都不能继续访问控制平面。
- Console 必须记录端侧
client_type、device_key、device_name、user_agent、ip_address,并提供当前 session 列表与非当前 session revoke。 - 个人账号必须提供 session 管理入口,允许用户主动退出指定设备会话,用于释放租户策略分配的设备名额。
当前内部登录不是完整 OIDC Provider:
- 不提供
/.well-known/openid-configuration。 - 不提供
/oauth2/authorizeauthorization-code flow。 - 不提供
/oauth2/jwks。 - 企业 SSO、外部 OIDC、Feishu、WeCom、GitHub Team 以后通过 identity provider / group mapping 接入,不改变当前 token response 基础形态。
Team Membership And RBAC
Team 是用户可见的协作容器,当前实现映射到 tenant。Tenant 仍然是资源隔离边界。
成员管理 API:
GET /api/v1/tenant-role-catalogGET /api/v1/tenants/{tenant_id}/membersPOST /api/v1/tenants/{tenant_id}/membersPATCH /api/v1/tenants/{tenant_id}/members/{id}DELETE /api/v1/tenants/{tenant_id}/members/{id}GET /api/v1/tenants/{tenant_id}/invitationsPOST /api/v1/tenants/{tenant_id}/invitationsPOST /api/v1/tenants/{tenant_id}/invitations/{id}/revokePOST /api/v1/team-invitations/accept
当前支持:
- owner/admin 查看成员。
- owner/admin 添加已存在用户为成员。
- owner/admin 创建成员邀请。
- owner/admin 撤销 pending 邀请。
- owner/admin 调整成员角色。
- owner/admin 禁用成员。
- owner 才能分配 owner 角色。
- 最后一个 active owner 不能被降级或禁用。
- delete 语义为软禁用,即 membership
status=disabled。 - 邀请 token 只在创建响应中返回一次,服务端只保存 token hash。
- 接受邀请时,当前登录用户 email 必须匹配邀请 email。
- 接受邀请后会创建或重新启用对应 tenant membership。
- 邀请状态包括
pending、accepted、revoked、expired。 - 邀请默认有效期 7 天,最长 30 天。
- 当前不发送邀请邮件,Console 直接展示一次性 invitation token。
内置角色:
owner: 租户所有者,拥有成员、资源和账务治理能力。admin: 租户管理员,管理资源、策略和成员,但不能分配 owner。member: 使用租户能力,管理自己的 client access 资源。viewer: 租户只读。billing: 账务角色,当前保留。operator: 历史兼容角色,等价于 admin,但新流程不再主动分配。
Identity Providers
Identity Provider 是租户级身份接入配置,用于后续把外部身份源映射为 OrbitMesh user、membership、role 和 group policy。
管理 API:
GET /api/v1/tenants/{tenant_id}/identity-providersPOST /api/v1/tenants/{tenant_id}/identity-providersPATCH /api/v1/tenants/{tenant_id}/identity-providers/{id}DELETE /api/v1/tenants/{tenant_id}/identity-providers/{id}
当前支持的 provider kind:
oidcgithub_teamfeishuwecom
配置约束:
config_json必须是 JSON object。mappings_json必须是 JSON array。- provider 状态包括
enabled、disabled。 - delete 语义为软禁用,即 status 更新为
disabled。 - Console 只管理 provider 配置,不直接执行外部登录流或 group sync。
- 业务权限仍以 Control Plane 计算出的 membership / role / session policy 为准,业务页面不能直接信任外部 IdP 响应。
Tenant Session Policy
个人会话属于 user account,策略治理属于 tenant。
租户级会话策略由 session_policies 管理,按以下维度生效:
tenant: 租户默认策略。role: owner、admin、member、viewer 等角色策略。group: 来自内部用户组或外部 IdP group mapping。当前组模型尚未启用,策略保留该 scope。user: 指定用户覆盖策略。client_type: console_web、cli、desktop、mobile、edge_runtime 等端类型。
策略字段:
max_active_sessions: 同一账号在该租户内允许的 active session 总数。max_active_devices: 同一账号在该租户内允许的设备总数,按稳定 device identity 或 device fingerprint 统计。session_ttl: session 最大有效期。idle_timeout: 空闲超时。exceed_action: 超限动作,取值为deny_new_session、revoke_oldest_session、require_user_revoke。priority: 多条策略命中时的优先级。
生效逻辑:
- 登录创建 session 前先解析 effective session policy。
- refresh 时继续校验 session 是否仍满足 policy。
client_type为空或*的策略作为全局策略,限制该用户所有端的 active session / active device。client_type有具体值时作为端类型策略,只限制同一端类型。- 多条策略命中时,数值限制取最严格的正数值,TTL 和 idle timeout 取最短正时长。
deny_new_session返回明确错误。require_user_revoke返回明确错误,前端引导用户到 Account Sessions 退出旧设备。revoke_oldest_session已进入模型,但当前不自动踢设备,仍返回错误。- 用户永远可以在 Account Sessions 中 revoke 自己的非当前 session。
- 租户管理员在 tenant settings 中管理租户范围内的 session policy,而不是管理用户个人会话本身。
当前设备统计基于 auth_sessions.device_key。第一版 device_key 由 client_type、device_name、user_agent 归一化后生成,用于端侧会话限制。后续如果引入更稳定的设备身份,可以替换生成来源,但仍保持 device_key 作为策略统计键。
管理入口:
- API:
/api/v1/session-policies支持 list、create、update、delete。 - Console:
Settings / Security管理租户级 session policy。 - Console role scope 从 tenant role catalog 选择。
- Console user scope 从当前 tenant members 选择。
- group scope 在内部 group / 外部 IdP group mapping 模型落地前保留为不可选。
- Delete 是软删除,策略状态更新为
deleted。 - Update 使用 patch 语义:未出现的字段不修改;出现且值为
0的限制字段会清空该限制;出现且为空字符串的scope_id/client_type会清空对应字段。
Edge Runtime Device Identity
要求:
- Edge Runtime 本地生成 Ed25519 keypair。
- 控制平面只保存 public key。
- private key 只保存于设备本地 root 权限文件。
- 同一设备可以用新 enrollment token 重新注册并复用原身份。
- 不同设备不能复用旧身份。
edge_secret不作为目标设计的一部分。
4. Edge Runtime 签名
Edge Runtime 请求头:
X-OrbitMesh-Node-Id
X-OrbitMesh-Edge-Runtime-Id
X-OrbitMesh-Installation-Id
X-OrbitMesh-Timestamp
X-OrbitMesh-Nonce
X-OrbitMesh-Body-SHA256
X-OrbitMesh-Signature
签名内容:
method + path_and_query + body_hash + timestamp + nonce + node_id + edge_runtime_id + installation_id
使用 Ed25519 请求签名。
5. 租户隔离
所有租户资源查询必须包含 tenant_id。
禁止:
- 通过 node_id 跨租户访问。
- 通过 subscription token 获取其他租户配置。
- shared node 未授权进入私有租户。
6. Secret 管理
Secret 类型:
- runtime password。
- Edge Runtime private key。
- TLS private key。
- subscription token。
- API token。
MVP 可存数据库加密字段。
后续接入:
- Vault。
- KMS。
- Cloud Secret Manager。
7. 日志规范
禁止记录:
- 明文 token。
- 明文 runtime password。
- Edge Runtime private key。
- TLS 私钥。
- 完整 subscription URL。
允许记录:
- token 前 6 位 hash。
- node_id。
- runtime_binding_id。
- request_id。
- tenant_id。
- error code。
8. 安全验收
- enrollment token 重复使用策略符合配置。
- subscription token 吊销后不可访问。
- Edge Runtime 未签名请求失败。
- 不同设备复用旧 Edge Runtime 身份失败。
- 用户不能访问其他租户 Node。
- 日志中不能搜索到明文 token。