Files
opsx-vpn/docs/specs/SDD-001-openvpn-oidc.md
T

85 lines
9.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# SDD-001:OpenVPN 浏览器 OIDC 登录
| 字段 | 内容 |
|------|------|
| 版本 / 变更级别 | 0.1 / S3(身份认证、部署) |
| 设计状态 | Draft |
| 实现状态 | OpenVPN WebAuth 配置与认证组件进程管理已实现;2026-10-22 已安装上游 openvpn-auth-oauth2 v2.3.0,真实飞书登录仍待 OIDC 提供方与独立认证入口联调 |
| 负责人 / 日期 | 待指定 / 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`)推荐空闲本机端口,以及只读 `GET /api/tunnels/openvpn/oidc-readiness` 展示组件版本与管理 HTTPS 前提(不代表认证入口或发行者已配置);不新增虚假的 `/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 的独立授权方案 |
### 2026-10-21 接入核查与发布边界
- 飞书应用的 App ID/Secret 是**飞书上游**应用凭据。若使用 Keycloak / Authentik,先在代理中配置飞书上游和其专用回调,再在代理中创建供 `openvpn-auth-oauth2` 使用的 OIDC 客户端;向导中的 issuer、Client ID/Secret 全部从代理获取。仅当飞书本身确实发布可用的 OIDC discovery、JWKS 与 ID Token 时,才能直接使用飞书提供的 issuer 和对应的客户端凭据。OpsX VPN 当前不提供签名密钥、OIDC discovery 或 ID Token,`http://<管理主机>:18080` 不能充当 issuer。
- 对外回调为 `https://<认证入口>/oauth2/callback`,由 `openvpn-auth-oauth2` 处理;代理方案还要把**代理提供给飞书的上游回调**登记在飞书应用,两条回调不能互换。认证入口可与管理后台同机不同域名部署,需要 HTTPS 与完整认证组件路由转发,`127.0.0.1:19090` 不对公网开放。
- 2026-10-21 服务器检查:OpenVPN 2.6.19 已安装;`openvpn-auth-oauth2`、Nginx/Certbot 和 80/443 监听均未检测到。未安装组件、准备可访问的 issuer、TLS 证书、飞书应用发布与授权之前,不切换现有运行中的 OpenVPN 专线到 OIDC。先用独立测试专线验证允许与拒绝、断线重连,再变更生产线路。发现失败时停止测试专线并保留原密码专线,不将缺失组件视为已完成登录联调。
- 飞书应用密钥曾出现在交互截图中,管理员应轮换后仅输入后台密钥框;仓库、文档、日志和测试均不得包含实际密钥。
### 2026-10-22 进展
- 上游 v2.3.0 Linux amd64 发布包校验 SHA-256 后安装在服务器 `data/bin/openvpn-auth-oauth2`;以管理进程相同的 root 权限执行 `--version` 显示 2.3.0,未启动任何 OIDC 专线。现有生成配置的 `http.baseurl`、`oauth2.issuer/client` 与 `openvpn.addr/password` 字段和固定版本官方配置样例一致。
- 管理域名 `test-link.appx365.com` 的 HTTPS 证书已签发、续签演练通过;它目前只转发管理页面/API,不作为认证组件的公网入口。管理页面区分“组件已安装”与“认证入口/发行者未就绪”,不得把前者当成已完成飞书登录。