# SDD-001:OpenVPN 浏览器 OIDC 登录 | 字段 | 内容 | |------|------| | 版本 / 变更级别 | 0.1 / S3(身份认证、部署) | | 设计状态 | Draft | | 实现状态 | 已实现本地集成;待 Linux + 飞书环境联调 | | 负责人 / 日期 | 待指定 / 2026-10-20 | | 关联需求 | 创建 OpenVPN 专线时配置飞书 OIDC 浏览器认证 | | 批准状态 | 未批准;用户已明确要求开始开发 | ## 1. 背景、目标与范围 - **当前行为与证据**:`backend/internal/service/openvpn/openvpn.go` 使用 `auth-user-pass-verify` 验证本地或 LDAP 密码,`frontend/src/views/TunnelWizard.vue` 的创建向导只有证书、密码、证书+密码模式。 - **本次目标**:增加独立 OIDC 浏览器认证模式、飞书应用配置引导、OpenVPN WebAuth 所需管理接口、辅助认证服务的可部署配置与失效保护。 - **非目标**:不把飞书网页登录等同 LDAP Bind;不声称现有 LDAP 用户名与飞书身份自动绑定;不让管理平台 `/api/login` 接受飞书令牌。 - **必须保留的行为**:原有三种认证方式与客户端配置保持兼容。 ## 2. 需求与约束 - FR-01:选择 OIDC 模式时,向导显示飞书应用创建、OIDC 设置、客户端及网络验收步骤;旧模式不受影响。 - FR-02:OIDC 模式生成 OpenVPN 管理接口 + WebAuth 配置,客户端不再要求本地/LDAP 密码;认证服务缺失时不能退回弱认证。 - FR-03:使用独立的 `openvpn-auth-oauth2` 服务;浏览器通过外网可达 HTTPS 地址接收 OIDC 回调,管理接口只在本机使用。 - FR-04:身份提供方必须显式限制可访问该应用的人员;VPN 拨号用户列表仍独立,不能凭同名邮箱自动认作 LDAP 用户。 - FR-05:新建 OIDC 专线时从 19090 起按已有配置的最大端口递增;手动加减或输入时跳过已配置及本机已监听的端口,编辑已有专线时保留原端口。 - NFR-01:OIDC 凭据及管理密码不可出现在隧道公开 JSON、客户端配置或普通日志,配置文件权限为 0600。 - NFR-02:不支持浏览器 WebAuth 的客户端应有明确兼容性提示;OpenVPN 服务端版本需满足上游最低 2.6.2 要求。 ## 3. 架构与方案 - 在原有 `auth_mode` 增加 `oidc`,单独生成 `management-client-auth`、`auth-user-pass-optional` 和本机 Unix 管理 socket,禁用密码校验脚本;OpenVPN 基础 PKI 和 `tls-crypt` 沿用。 - `openvpn-auth-oauth2` 使用独立 HTTPS 反代入口、飞书(或兼容身份代理)的 OIDC issuer、Client ID/Secret 与本机管理 socket。每个 OIDC 隧道使用独立回调主机或端口、管理 socket 与认证服务实例。 - 在向导和编辑页面提供步骤提示,告知回调地址属于认证服务,并标明管理员应在飞书开放平台创建应用、配置登录与人员授权,确认标准 OIDC 发现文档及客户端支持。 - 受登录保护的端口推荐接口扫描已有 OpenVPN 配置及本机回环监听情况;仅返回推荐端口,不预留端口。保存时检查专线配置冲突,启动时再检查真实监听冲突,避免推荐与启动之间的竞争。 - 安全边界:OIDC 的人员授权以飞书应用可用范围或身份代理群组为准;本期不以现有 LDAP 用户表做未经验证的身份匹配。 ## 4. 接口、数据与配置契约 - 接口变更:现有隧道 API `config.auth_mode` 新值 `oidc`;新增 `GET /api/tunnels/openvpn/oidc-port`(可选 `from`、`direction`)推荐空闲本机端口;不新增虚假的 `/oauth2/callback` 后端接口。 - 数据模型 / 迁移:沿用隧道配置 JSON 与 Secrets 密文,无强制数据库迁移。 - 配置变更:OIDC issuer、client ID、client secret、外网 HTTPS base URL、认证服务本地监听端口;生成认证服务配置和管理 socket 密码文件。 - 兼容性:其余认证模式行为不变;OIDC 仅供支持 WebAuth 的客户端使用。 ## 5. 风险与验收 ### 风险 | 风险或失败场景 | 防护 / 降级 / 恢复 | 可观察信号 | |----------------|--------------------|------------| | issuer 不是标准 OIDC 或飞书未授权应用 | 认证失败关闭;允许通过兼容身份代理接入 | 认证服务启动/登录错误 | | 认证服务停机 / 回调不可达 | 不能绕过认证;恢复服务与反代 | 客户端连接失败、服务日志 | | 使用不支持 WebAuth 的客户端 | 在向导提示已验证的客户端与版本 | 客户端不弹浏览器或登录超时 | | 未绑定本地 LDAP 用户 | 明确由身份源应用授权控制准入;后续按稳定 subject 制定绑定设计 | 管理端用户数与实际 OIDC 会话不一致 | | 查询端口后被其他进程占用 | 推荐结果不视为预留;启动时拒绝冲突,改选端口重试 | 启动报端口占用,原有隧道继续运行 | ### 验收标准 | AC | 对应需求 | 前置条件与操作 | 预期结果 | 验证方式 | 结果 | |----|----------|----------------|----------|----------|------| | AC-01 | FR-01 | 选择 OIDC / 切回密码模式 | 仅 OIDC 显示飞书和 WebAuth 提示 | 前端构建与页面检查 | 构建通过;浏览器手动检查待做 | | AC-02 | FR-02 | 生成 OIDC 服务端和客户端配置 | 管理模式开启、无密码脚本、客户端可发起 WebAuth | Go 测试 | 单元测试通过;WebAuth 联调待做 | | AC-03 | FR-03 | 启动认证服务,完成真实 OIDC 登录 | 浏览器回调并放行 OpenVPN | 真实 Linux 服务端 + 飞书应用 + 客户端联调 | Not Run | | AC-04 | FR-04 | 未获应用授权的用户登录 | 被身份提供方或代理拒绝 | 真实联调 | Not Run | | AC-05 | NFR-01 | 创建/编辑 OIDC 专线并检查文件及 API | 密钥不公开,文件 0600 | Go 测试与文件检查 | 单元测试通过;真实 API 交互待做 | | AC-06 | NFR-02 | OpenVPN 版本过低或客户端无 WebAuth | 明确错误与提示 | Go 测试及手动客户端检查 | 版本单元测试通过;客户端手动检查待做 | | AC-07 | FR-05 | 已配置 19090、监听 19091 后新建/加减端口 | 自动推荐 19092;编辑原有端口不变;启动前再检测冲突 | Go 端口选择测试、前端构建、真实页面手动检查 | 端口跳过单元测试与前端构建通过;真实页面待检查 | ## 6. 发布与恢复(S3 必填) - 前置条件:飞书开放平台应用获管理员发布与用户授权;OIDC discovery 可达;公网 HTTPS 域名/证书及反代;OpenVPN >=2.6.2、支持 WebAuth 的客户端、认证服务二进制。 - 发布顺序:先在测试隧道配置 OIDC 与回调,再验证失败拒绝、正确授权和断线重连;最后逐隧道切换,不批量改变现有密码隧道。 - 回滚:停用测试隧道,改回原有认证方式并重启;恢复旧客户端配置。原有隧道的密钥、PKI 与用户数据保持不变。 - 不可逆操作:本次不删除用户或凭据,不自动迁移 LDAP 认证。 ## 7. 待决问题 | 问题 | 是否阻塞 | 推荐方案 | |------|----------|----------| | 飞书租户是否公开标准 OIDC discovery / ID token | 阻塞真实联调,不阻塞本地实现 | 先从飞书应用或身份代理获取 issuer 并校验 discovery;不兼容时使用 Keycloak/Authentik 代理 | | 是否需要按 LDAP 用户逐一授权 OIDC | 不阻塞第一版 | 首版仅信任身份源应用的可用范围;逐一绑定必须引入稳定 subject 的独立授权方案 |