diff --git a/docs/task/86-mysql公网tls-ca校验.md b/docs/task/86-mysql公网tls-ca校验.md new file mode 100644 index 0000000..f06d0ce --- /dev/null +++ b/docs/task/86-mysql公网tls-ca校验.md @@ -0,0 +1,76 @@ +# 86 Admin:支持校验 CA 的 MySQL 公网 TLS 连接 + +- 类型:需求 +- 父级大工单:#76 +- 所属 MVP / 版本:#77 / 线上 MySQL 8 部署 +- 状态:已完成 +- 日期:2026-08-10 +- Gitea 工单: + +## 背景与目标 + +#85 开放固定公网 IP 后,MySQL 公网账号要求 SSL,但 Admin 的 Go 驱动没有启用 +TLS,因此正确密码也会收到 `1045 Access denied`。相同账号使用 MySQL 客户端 +`--ssl-mode=REQUIRED` 可以登录,确认直接原因是客户端缺少 TLS。 + +目标是让 `run_admin.bat` 使用公网 MySQL 时强制加密、验证服务器专属 CA,且验证 +失败不能回退明文。 + +## 最终方案 + +- 数据库配置增加 `tls_mode` 和 `tls_ca`,环境变量也可按字段覆盖。 +- `disabled` 保持同机及 SSH 隧道兼容;`verify_ca` 要求 TLS 1.2+、加载指定 PEM CA、 + 验证服务器证书链,并禁止明文回退。 +- MySQL 自动生成的服务端证书没有 SAN,不能做公网 IP 主机名匹配;客户端只信任该 + 服务器专属 CA,通过自定义 `VerifyConnection` 校验证书链,不使用单纯 + `skip-verify`。 +- Go 驱动改用 `mysql.NewConnector`,确保自定义 `tls.Config` 不会在 DSN 格式化时 + 丢失。 +- 提交服务器公开 CA 证书,不包含服务器私钥。 +- 本机被 Git 忽略的 `config.yaml` 已设置公网地址和 `verify_ca`。 + +## 改了哪些 + +- `admin/config/config.go`:增加 TLS 配置、环境变量覆盖和模式校验。 +- `admin/repository/mysql_db.go`:加载 CA、验证证书链、启用 TLS 1.2+,更新错误提示。 +- `admin/certs/mysql84-ca.pem`:服务器公开 CA,不含私钥。 +- `admin/config/config_test.go`:覆盖 TLS YAML、环境覆盖、非法模式和缺少 CA。 +- `admin/repository/mysql_db_tls_test.go`:覆盖驱动配置、损坏 CA 和公网只读 TLS 冒烟。 +- `admin/mysql_public_tls_smoke_test.go`:覆盖数据库连接、schema migration 和首页路由。 +- `admin/config.example.yaml`、`admin/AGENTS.md`、Admin 上手及安全文档:同步配置和门禁。 + +## 验收结果 + +| 验收标准 | 结果 | +|---|---| +| Go 驱动通过公网账号连接 MySQL | 通过 | +| TLS cipher 非空且不能回退明文 | 通过,`ECDHE-RSA-AES128-GCM-SHA256` | +| 使用服务器专属 CA 验证证书链 | 通过 | +| CA 缺失、损坏或非法模式返回明确错误 | 通过 | +| 默认 disabled 保持本机部署兼容 | 通过 | +| 公网数据库连接、schema migration 和首页路由 | 通过,首页返回 303 | +| Go 1.23.0 静态检查、构建和全部测试 | 通过 | + +## 测试 + +- 执行的命令: + + ```powershell + cd D:\chengma\cmautobuy\admin + $env:GOTOOLCHAIN="go1.23.0" + go vet ./... + go build ./... + go test ./... -count=1 + go test . ./repository -run '公网MySQLTLS|公网TLS只读冒烟' -v -count=1 + Remove-Item Env:GOTOOLCHAIN + ``` + +- 结果:全部通过;公网集成测试确认 MySQL 8.4.8 TLS cipher 为 + `ECDHE-RSA-AES128-GCM-SHA256`,页面冒烟完成 schema 初始化并返回 303。 +- **没验证到的部分**:本机执行策略禁止自动后台启动和终止临时 Admin 进程,因此 + 没有由自动化直接执行长期运行的 `run_admin.bat`;测试已覆盖其相同的配置加载、 + 数据库连接、migration 和路由组装路径,需用户重新启动脚本确认窗口保持运行。 + +## 相关提交 + +- `f0715ee` feat: 支持 MySQL 公网 TLS CA 校验 (#86)