Files
opsx-vpn/docs/specs/SDD-011-feishu-directory-and-admission.md
T

5.7 KiB
Raw Blame History

SDD-011:飞书姓名补全与 OpenVPN 成员准入

字段 内容
级别 S3:认证准入、外部目录查询、数据库新增表
设计状态 已形成
实现状态 本地实现;待真实飞书环境验证与发布
日期 2026-10-23
授权 用户要求继续开发姓名反查及两类成员准入

1. 背景与范围

当前 identityprovider/handlers.go 使用飞书 authen/v1/user_info 的 name 保存到 IdentityProfile。测试环境已有会话稳定 subject,但保存姓名为飞书返回的“用户812604”。FeishuCallback 只检查 tenant_key,OIDC 专线尚无成员白名单。sessionmgr 仅用 subject 精确查姓名;不按 IP 或展示名猜测用户。

本轮在用户每次授权时尝试使用应用 tenant token 按同应用 open_id 查询基础姓名,再回退通讯录单用户接口;均失败时保留 user_info 结果,登录不中断。提供仅管理员可调用的姓名查询诊断,结果不含上游 token。增加专线级准入模式:现有与缺省专线保持同租户全员;指定成员模式只允许已明确授予的 subject,撤销后拒绝下一次登录。身份资料与授权名单分开,不自动让已登录用户获准。OpenVPN WebAuth 尚未完成认证时出现的 UNDEF 不创建匿名审计,待稳定 subject 出现后记录连接。

2. 需求

  • FR-01:反查同一应用 open_id 时,仅在返回有效姓名时覆盖展示名;权限、范围、超时等错误降级而不跳过租户检查;无管理员授权的用户不能调用诊断。
  • FR-02:管理员能查看/添加/撤销某条内置飞书 OpenVPN 专线的已验证用户授权;不能跨租户、跨 issuer 或凭可变姓名授权。
  • FR-03:all / allowlist 两模式:all 仍要求相同 tenant_key;allowlist 需精确匹配当前 tunnel ID + issuer + app ID + subject 的授权记录,缺数据和数据库错误均拒绝发放授权码。切换模式需在专线编辑页明示影响。
  • NFR-01:短期上游访问令牌不存数据库/日志;接口查询只由服务端执行;更换飞书应用后旧名单不能生效;历史会话不回填猜测姓名。

3. 架构

FeishuCallback 已有经过飞书签发并核实租户的 open_id。优先用本次授权的用户令牌调用飞书 POST /contact/v3/users/basic_batch?user_id_type=open_id;失败后用应用 tenant token 重试,最后尝试单用户通讯录接口。请求体为 user_ids;SDK 文档说明 basic_batch 不受通讯录可见范围限制,但接口仍可能返回权限错误。只接受 code=0、有姓名且响应用户 ID 与原 open_id 一致的结果;均失败即保留原姓名。认证判断在保存 profile 和生成内部授权码之前,根据回调 URL 定位唯一的内置专线并检查准入。管理员选择已验证 profile 加入准入表。UI 为专线编辑页模式选择与成员列表;身份设置页提供姓名权限检测和操作提示。

4. 接口和数据

在 Tunnel.Config 增加 feishu_access_mode,值为 all 或 allowlist;未配置按 all 处理以保持兼容。新增 FeishuTunnelGrant(tunnel_id、issuer、app_id、subject、created_at),唯一索引约束完整身份;撤销时删除此记录。管理员接口:查询已验证身份、列出授权、添加、撤销;诊断接口输入已验证 subject,服务端使用加密保存的 App Secret 请求飞书并返回有限的状态和展示名。其余认证模式拒绝使用此功能。

5. 风险和验收

风险 防护/恢复 观察
飞书权限不足或通讯录不可见 不阻断 all 登录;诊断说明需在飞书开放平台授权,平台不能代授 降级显示原姓名
白名单配置错误造成拒绝连接 切换前先加入用户;设置恢复 all 即回退 回调无新授权码
换 App 后旧授权误用 联合 issuer/app ID/subject 精确匹配 跨应用负向测试
在线已连用户撤销 下一次登录阻断;本轮不强制踢已有连接 会话状态与下一次授权
AC 需求 验证 状态
AC-01 FR-01/NFR-01 模拟飞书成功/403/不一致/请求取消,核验姓名与不泄露 token 单元测试通过;真实姓名待验证
AC-02 FR-02 管理员添加/撤销、普通账号禁止及未知身份拒绝 授权接口已实现,管理角色与未知身份尚未单独测试
AC-03 FR-03 默认 all;同租户白名单准入,跨应用、未授权、DB 失败均拒绝 单元测试通过,真实回调待验证
AC-04 全部 Go 测试、前端构建、现有登录路由回归 完整 Go 测试及前端构建通过;真实飞书登录待验证

6. 发布与恢复

先备份数据库和加密密钥,运行迁移与测试,部署后检查当前 all 专线仍能登录。先导入可验证身份并授予,再手动切换 allowlist;遇故障切回 all,新增表保留供重试。不删旧身份资料或证书。未实际完成测试前不标通过。

7. 未决

2026-10-23 测试环境以已保存的应用凭据查询已验证 open_id:tenant token 成功,basic_batch 返回飞书错误码 99991672,说明明确要求应用身份权限 contact:user.basic_profile:readonly;单用户接口成功且确认 open_id 匹配,但 name 仍为“用户812604”,其他姓名字段为空。浏览器用户令牌的 basic_batch 路径尚待下一次真人授权验证。基础姓名接口的应用权限和发布状态需在飞书开放平台核对;不能由平台代授权或仅靠用户数字反查。全量通讯录同步、部门实时同步和强制踢离在线用户留到后续迭代,本轮仅支持按已验证身份授权。