Files
cao.wangrenbo f70b344c85 chore: initial commit — 项目计划 v0.3
服务器用户管理节点(ws_usernode):
- docs/PLAN.md:需求交互确认后的完整项目计划(v0.3)
  - 单机节点 + RESTful API v1,后期可扩展多节点 agent
  - Go + Gin / Vue3 + Element Plus,GORM 双驱动(MySQL/SQLite)
  - 外部用户 OTP 双通道登录(邮件 + CLI)、sudoers 白名单系统操作
  - 账号生命周期、SSH 公钥管理、申请审批、审计归档
- .gitignore:Go / 前端 / 运行时产物忽略规则
2026-08-29 21:28:52 +08:00

19 KiB
Raw Permalink Blame History

项目计划:服务器用户管理节点(ws_usernode

版本:v0.3(需求已交互确认,含构建/配置细化) 日期:2026-08-29 状态:待评审


1. 项目概述

构建一个基于 Go 的服务器用户管理节点,提供 Web 前后端,用于对服务器上的外部用户(非本机管理员)进行集中化管理,覆盖:

  • 系统账号的创建、禁用、删除、过期与回收(统一 ext_ 前缀、external 组)
  • 外部用户自助上传与管理 SSH 公钥,实时同步 authorized_keys
  • 用户自助申请新账号 + 管理员审批流
  • SMTP 邮件通知(OTP 登录验证码、审批结果、到期提醒、密码重置)
  • 管理操作审计(保留 30 天 + 手动/每日定时归档)

部署形态:单机节点,一个 Go 二进制(前端产物 go:embed 嵌入),参考 Gitea 单二进制风格。所有能力通过 RESTful API v1 暴露,系统账号操作层接口化,为后期扩展"控制面 + 多节点 agent"预留空间。


2. 已确认决策汇总

2.1 架构与部署

决策点 结论
部署形态 单机节点;RESTful API v1;后期可扩展多节点 agent
后端 Go ≥ 1.22 + Gin
前端 Vue 3 + Vite + TypeScript + Element Plus + Pinia + Vue Router + Axios
前端部署 go:embed 嵌入 Go 二进制,单文件分发;开发期走 Vite dev server
数据库 GORM 抽象,MySQL 生产 / SQLite 开发,可平滑迁移
进程管理 systemd 服务
系统账号操作权限 节点以专有用户运行(如 usernode,加入 sudo 组),通过 sudoers 白名单执行 useradd/usermod/userdel/passwd 等,便于审计程序行为
日志 log/slog 结构化日志
构建环境 podman 容器构建(多阶段);前端可单独拉取前端 dev 镜像热开发
配置格式 TOMLconfig.example.toml,支持环境变量覆盖)

2.2 账号与认证

决策点 结论
外部用户系统账号 统一加入 external 组;用户名强制 ext_ 前缀(如 ext_zhangsan);系统账号口令锁定(passwd -l),仅密钥登录
外部用户登录 图形验证码 + 6 位 OTPOTP 支持邮件CLI 子命令双通道获取(同一验证码、同一 10 分钟有效期、同一 60s 冷却与失败限速,两通道对齐);会话 cookieHttpOnly/Secure/SameSite
管理员登录 用户名 + 密码(bcrypt);密码可通过 CLI 子命令邮件重置修改;不做 TOTP
用户邮箱 仅管理员可修改(OTP 接收方);用户不可自助改
默认有效期 批准激活起默认 90 天(全局可配置),管理员创建/延期时可覆盖

2.3 功能范围

决策点 结论
管理范围 账号生命周期 + SSH 密钥(仅用户上传,管理员不代签)
新账号申请 表单:用户名、邮箱、挂靠老师、用途;批准后自动 useradd 并邮件通知
审批范围 仅新账号申请走审批流;延期由管理员操作
密钥来源 仅用户自行上传公钥;无管理员代签、无密钥对下发路径
过期回收 到期自动禁用(锁系统账号)+ 邮件通知;可配置回收期(默认 30 天),期内可延期恢复,超期自动删除系统账号与密钥(保留审计
用户自助范围 管理自己的公钥(上传/重命名/吊销)、查看账号信息与状态、查看自己的审计痕迹
审计 管理操作审计,append-only;保留 30 天自动清理;手动 CSV 导出 + 每日定时归档(文件存磁盘)
批量导入 本期不做,接口预留(二期)

3. 需求范围

3.1 功能需求(FR

F1 认证与会话

  • 管理员:用户名+密码登录;bcrypt 存储;登录限速防暴力;忘记密码走 SMTP 邮件重置;CLI 子命令重置
  • 外部用户:图形验证码(防机器人)→ 6 位 OTP → 验证登录;OTP 经邮件CLI 子命令获取(同一验证码、同一有效期与限速,两通道对齐);发送冷却 60s、单账号失败限速
  • 会话:cookieHttpOnly/Secure/SameSite),默认 24h,可配置;登出即失效
  • 外部用户无 Web 口令(系统账号口令锁定,纯密钥登录)

F2 用户生命周期管理

  • 管理员创建外部用户:自动生成 ext_<name> 系统账号(external 组、锁定口令、默认 shell
  • 启用 / 禁用 / 删除 / 延期;状态与系统账号一致性校验
  • 到期自动禁用(锁账号)+ 邮件提醒;进入回收期(默认 30 天,可配置);回收期内可延期恢复;超期自动删除系统账号与密钥(保留审计)
  • 用户模型记录:邮箱、挂靠老师、用途、过期时间、创建者、最近登录

F3 SSH 密钥管理

  • 用户上传自己的公钥(格式校验:类型/长度/重复)
  • 密钥列表、重命名、吊销、删除
  • 有效密钥实时同步到 ~/.ssh/authorized_keys(原子写 + 并发锁),吊销立即失效

F4 申请与审批

  • 新账号申请单:用户名、邮箱、挂靠老师、用途
  • 管理员审批(通过 / 拒绝 + 理由),结果邮件通知;通过后自动创建账号
  • 拒绝后可重新提交

F5 邮件通知(SMTP

  • OTP 登录验证码、审批结果、账号创建通知、到期提醒、回收提醒、管理员密码重置
  • 发送队列 + 重试 + 失败记录(mail_logs);OTP 为双通道(邮件 + CLI),邮件失败不阻断登录

F6 审计

  • 记录管理操作:操作者、动作、对象、详情(JSON)、IP、结果、时间;append-only
  • 保留 30 天自动清理;手动 CSV 导出接口;每日定时归档到磁盘目录(归档后可安全清理)

F7 系统设置

  • SMTP、默认有效期、回收期、会话时长、审计保留天数等(config + settings 表)

3.2 非功能需求(NFR

  • 安全:私钥不经系统(无代签);系统命令 sudoers 白名单、最小权限;OTP/图形验证码/限速;cookie 安全属性;审计不可篡改
  • 兼容性SQLite ↔ MySQL 迁移无忧(GORM 通用类型 + 迁移脚本)
  • 部署:单二进制 + go:embed 前端 + systemd + sudoers 配置;提供 Docker 可选
  • 可观测:结构化日志、审计表、状态接口
  • 可扩展:system 层接口化,预留多节点 agent;API 无状态化(cookie 会话 + DB session 存储)

4. 技术选型

选型 理由
语言 Go ≥ 1.22 单二进制、并发好、部署简单
Web 框架 Gin 生态成熟、中间件丰富
ORM GORM v2sqlite + mysql 驱动) 一套模型双库支持
认证 服务端会话(DB 存储)+ cookiebcryptOTPcrypto/rand 生成) 符合"cookie 会话"确认
图形验证码 内置生成(图像,随机字符),不依赖第三方服务 防机器人,自包含
定时任务 robfig/cron/v3 过期扫描、回收、审计归档
邮件 gomailnet/smtp 封装) TLS 支持,队列+重试
SSH 公钥 crypto/ssh 解析校验 标准库,免依赖
前端 Vue 3 + Vite + TS + Element Plus + Pinia + Router + Axios 后台管理生态成熟
日志 log/slog 标准库结构化日志
配置 TOMLgithub.com/BurntSushi/toml 配置文件 + 环境变量覆盖
构建 podman 多阶段容器构建 Go 镜像 + 前端 dev 镜像

5. 总体架构

5.1 分层

┌───────────────────────────────────────────────┐
│ Web 前端 (Vue3 SPA, go:embed 进二进制)         │
└───────────────┬───────────────────────────────┘
                │ HTTPS / RESTful API v1
┌───────────────▼───────────────────────────────┐
│ HTTP 层 (Gin)  路由 / 中间件 / 参数校验 / 鉴权 │
├───────────────────────────────────────────────┤
│ 服务层 (service)                               │
│  auth │ user │ key │ approval │ mail │ audit   │
├───────────────────────────────────────────────┤
│ 系统账号抽象层 (system)  接口: CreateUser /     │
│   RemoveUser / SetLock / SyncAuthorizedKeys    │
│   └── 本地实现: sudoers 白名单 + sudo -n 执行   │
│       useradd/usermod/userdel/passwd、原子写    │
│       authorized_keys  ──(未来)──> 远程 agent   │
├───────────────────────────────────────────────┤
│ 数据层 (GORM)   users/ssh_keys/approvals/      │
│                 audit_logs/sessions/settings   │
│                 ├─ MySQL(生产)               │
│                 └─ SQLite(开发/单机)         │
└───────────────────────────────────────────────┘

5.2 目录结构(规划)

ws_usernode/
├── cmd/usernode/main.go          # 入口 + CLI 子命令
│   ├── serve                     # 启动服务
│   ├── migrate                   # 数据库迁移
│   ├── admin create              # 创建初始管理员
│   ├── admin reset-password      # 重置管理员密码(CLI)
│   └── user otp                  # 外部用户 OTP 获取(与邮件对齐)
├── internal/
│   ├── config/                   # 配置加载(yaml + 环境变量)
│   ├── server/                   # HTTP server、优雅启停
│   ├── router/                   # 路由注册
│   ├── api/                      # handler 层(v1
│   ├── model/                    # GORM 模型
│   ├── service/                  # 业务逻辑
│   ├── system/                   # 系统账号抽象层(sudoers 白名单实现)
│   ├── auth/                     # 会话、bcrypt、OTP、图形验证码、限速
│   ├── cron/                     # 过期扫描、回收、审计归档
│   └── pkg/                      # 工具(随机、时间、校验)
├── web/                          # Vue3 前端
│   ├── src/
│   └── Containerfile.dev         # 前端 dev 镜像(podman 热开发)
├── docs/                         # 本计划、API、数据库、部署
├── deploy/                       # systemd 单元、sudoers 配置、迁移脚本、Containerfile
├── config.example.toml
├── go.mod
└── Makefile                      # build / test / dev 工作流

6. 数据库设计(核心表)

GORM 定义;避免平台特有类型;时间统一 UTC;SQLite/MySQL 双兼容。

关键字段 说明
admin_users username, password_hash, email, role, status 管理端账号(唯一)
users username(ext_ 强制前缀), email, supervisor, purpose, status(active/disabled/expired), expire_at, shell, created_by, last_login_at, recycled_at 外部用户(1:1 系统账号)
ssh_keys user_id, name, key_type, public_key, fingerprint, status(active/revoked), source(默认 user_uploaded), created_by, revoked_at 仅用户上传公钥
approvals username_requested, email, supervisor, purpose, status(pending/approved/rejected), reviewer_id, reviewed_at, reason 仅新账号申请
audit_logs actor_id, actor_name, action, resource_type, resource_id, detail(JSON), ip, result, created_at append-only
sessions session_id, user_type(admin/user), ref_id, expire_at, ip, user_agent cookie 会话
settings key, value SMTP、策略等
mail_logs to, subject, status, error, retry_count 邮件队列/重试/失败记录

OTP 验证码与图形验证码:单实例可用内存缓存 + 限速计数(DB 或内存);文档注明多实例时需改为 DB/Redis。


7. API 设计(RESTful v1

统一前缀 /api/v1;会话基于 cookie(非 Bearer header)。

模块 方法 & 路径 说明 权限
认证 GET /auth/captcha 图形验证码 -
认证 POST /auth/otp/send 外部用户:用户名 + 图形验证码 → 发 OTP 邮件(60s 冷却) -
认证 POST /auth/otp/login 用户名 + 6 位 OTP → 建立 cookie 会话 -
认证 POST /auth/admin/login 管理员用户名+密码登录 -
认证 POST /auth/logout / GET /auth/me 登出 / 当前会话 user/admin
认证 POST /auth/admin/forgot / POST /auth/admin/reset 管理员邮件重置密码 -
用户 GET /users 列表(筛选/分页:状态、到期、挂靠老师) admin
用户 POST /users 管理员创建(自动 useradd admin
用户 GET /users/:id / PATCH /users/:id 详情 / 更新(含改邮箱) admin
用户 POST /users/:id/disable / enable 禁用 / 启用 admin
用户 POST /users/:id/extend 延长过期时间 admin
用户 DELETE /users/:id 删除并回收(系统账号+密钥,保留审计) admin
密钥 GET /me/keys 我的密钥列表 user
密钥 POST /me/keys 上传公钥 user
密钥 PATCH /me/keys/:id 重命名 user
密钥 DELETE /me/keys/:id 吊销 / 删除 user
密钥 GET /users/:id/keys 用户密钥列表(管理员) admin
审批 POST /approvals 提交新账号申请 -(公开)
审批 GET /approvals 申请单列表(按状态筛选) admin
审批 POST /approvals/:id/review 审批(通过→自动建号 / 拒绝+理由) admin
审计 GET /audit 查询(操作者/资源/时间范围/分页) admin
审计 GET /audit/export 手动 CSV 导出 admin
设置 GET /settings / PUT /settings 系统设置读写 admin
状态 GET /healthz 健康检查 -

8. 前端规划(Vue3

参考 Gitea 后台管理布局:

  1. 登录页:管理员(密码)与外部用户(图形验证码 + 邮件 OTP)双入口
  2. 仪表盘:用户数、待审批数、近期待过期账号、最近审计
  3. 用户管理(admin):列表筛选/分页、新建、详情、禁用/启用/延期/删除、改邮箱
  4. 密钥管理:我的密钥上传/重命名/吊销
  5. 申请审批(admin):待办列表、通过/拒绝 + 理由
  6. 审计日志admin):查询 + CSV 导出
  7. 系统设置(admin):SMTP、默认有效期、回收期、会话时长、审计保留
  8. 个人中心(user):账号信息(挂靠老师/用途/到期时间)、我的密钥、我的审计痕迹

技术栈:Vite + Vue Router + Pinia + Axios(统一拦截 401/错误码)+ Element Plus;构建产物 go:embed。


9. 安全设计

风险 对策
系统账号操作提权 节点以专有用户运行;sudoers 白名单仅允许固定命令(useradd/usermod/userdel/passwd/chsh)且禁任意 shell;命令参数程序内强校验;不在生产直接验证
OTP 爆破 / 滥用 图形验证码前置、发送冷却 60s、单账号失败限速、OTP 一次性 + 10 分钟过期;CLI 通道受同一限速约束
会话劫持 cookie HttpOnly/Secure/SameSite;会话过期;登出吊销;IP 变更可选提示
口令安全 管理员 bcrypt 存储、强度校验、登录限速
authorized_keys 并发写 文件锁 + 原子写(tmp + rename);全量重写基于 DB 状态
审计不可篡改 audit_logs 仅 INSERT30 天自动清理前先归档;定期备份
邮件安全 SMTP TLS、邮件内容不含验证码明文记录、密码不出现在日志
外部用户口令 系统账号 passwd -l 锁定,仅密钥登录

10. 里程碑与排期

估算总周期约 3~4 周(单人),每阶段含测试。

阶段 内容 交付物 估算
M0 骨架 Go 工程、CLI 子命令(含 OTP 获取)、TOML 配置、日志、GORM 双驱动、podman 多阶段构建、前端脚手架(Vite dev 镜像 + go:embed 打通) 可运行空壳 + 迁移 23 天
M1 认证 + 用户管理 管理员登录(密码/CLI/邮件重置)、外部用户 OTP 登录(图形验证码 + 邮件/CLI 双通道)、cookie 会话、用户 CRUD、system 层 sudoers 对接 可创建/禁用/删除真实系统用户 56 天
M2 SSH 密钥 公钥上传/管理、authorized_keys 原子同步、吊销即时失效 端到端密钥管理 34 天
M3 审批 + 邮件 新账号申请流(用户名/邮箱/挂靠老师/用途)、审批、SMTP 通知、拒绝重提 完整申请-审批闭环 34 天
M4 生命周期 + 审计 过期扫描 cron、回收期策略、审计(30 天 + 手动导出 + 每日归档) 自动化回收 + 可查可导出审计 34 天
M5 前端完善 + 部署 Vue3 全部页面、联调、podman 构建镜像、systemd + sudoers 部署、迁移脚本、文档 可交付部署版本 57 天

验收标准(M5 完成时)

  • 管理员创建用户 → 用户图形验证码 + OTP(邮件或 CLI)登录 → 上传公钥 → 立即 SSH 登录服务器
  • 吊销密钥立即失效;到期自动禁用并通知;回收期内可延期,超期自动回收(保留审计)
  • 所有管理操作可审计、可查询、可 CSV 导出,每日归档
  • SQLite 数据可迁移至 MySQL(提供脚本与验证)
  • 单二进制部署(systemd + sudoers 白名单)通过;podman 容器构建通过(Go 镜像 + 前端 dev 镜像)

11. 风险与对策

风险 影响 对策
系统账号操作失误(误删/误改) sudoers 白名单、命令参数强校验、回收二次确认、测试环境验证
OTP/邮件链路故障 邮件队列 + 重试 + 失败告警;OTP 双通道(邮件 + CLI),邮件不可用时经 CLI 获取
SQLite ↔ MySQL 迁移差异 GORM 通用类型、迁移前校验、迁移脚本 + 演练
定时任务并发触发 单实例部署说明;预留分布式锁接口
管理员密码丢失 CLI admin reset-password 兜底
多实例扩展(未来 agent 低(预留) system 层接口化;会话/OTP 存储预留 DB 方案

12. 待定项 / 二期展望

  • 多节点 agent 模式(system 层远程化)
  • CSV 批量导入用户
  • 用户自助延期申请(当前管理员操作)
  • TOTP 双因素(当前不做)
  • 审计归档格式扩展(当前 CSV;可加 JSON)
  • 通知渠道扩展(Webhook/企业微信/钉钉)

13. 下一步

  1. 评审本计划(v0.2),确认范围与里程碑
  2. 评审通过后启动 M0:工程骨架、CLI、CI、前端脚手架