# 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)