feat(security): 移除 admin123 硬编码默认密码 + 编译加 -trimpath

安全加固(降低二进制泄露/逆向的信息面):

1. 初始密码随机化
   - 首次启动生成 16 位随机密码(大小写+数字,排除 0/O/1/l/I 易混淆字符)
   - 写入数据卷 initial-admin-password.txt(0600)并打印到首次启动日志
   - admin 首次改密后自动删除该文件(seed.CleanupInitPassword)
   - 支持 ADMIN_INIT_PASSWORD 环境变量指定(自动化部署 / 固定密码场景)
   - 生成失败直接 Fatal 退出,不再降级到公开默认口令

2. 移除硬编码 admin123
   - main.go 不再打印 "Default login: admin / admin123"
   - 二进制内 admin123 命中:2 → 0

3. -trimpath
   - build.sh / run.sh 编译加 -trimpath
   - 二进制内 /app/backend/ 源码路径命中:66 → 0

4. 文档
   - README 新增「第 4 步:获取管理员初始密码」
     (docker compose exec / logs / docker cp / named volume 四种方式 + K8s 对应命令)
   - .env.example 补 ADMIN_INIT_PASSWORD
   - kubernetes/deployment.yaml 加 env 注释说明

验证(strings 对比加固前后二进制):
  admin123              2 → 0
  /app/backend/        66 → 0
  initial-admin-password.txt / ADMIN_INIT_PASSWORD / CleanupInitPassword 均存在
This commit is contained in:
opsx committed 2026-10-26 17:01:09 +00:00
1 parent 9a46a955d4
commit 3c27e58a73
8 files changed
+163 -5

No files matched your search

+63 -1
View File
@@ -65,7 +65,7 @@ docker compose ps
docker compose logs -f
# 打开 http://localhost:8080
# 默认账号:admin / admin123
# 管理员密码见「第 4 步」(首次启动随机生成,不再是固定 admin123)
```
### 第 3 步:验证健康状态
@@ -80,6 +80,68 @@ docker inspect --format='{{.State.Health.Status}}' opsxloki
curl http://localhost:8080/index.html
```
### 第 4 步:获取管理员初始密码
首次启动会生成**随机管理员密码**(不再固定 `admin123`),同时:
- 打印到启动日志(**仅首次**)
- 写入数据卷 `/app/data/initial-admin-password.txt`(权限 `0600`)
**任选一种方式获取**(推荐方式 1 —— 日志会轮转丢失):
```bash
# 方式 1(推荐):从容器内读文件 —— 日志轮转后依然可查
docker compose exec opsxloki cat /app/data/initial-admin-password.txt
# 方式 2:首次启动日志(只打印一次,重启后不会再有)
docker compose logs opsxloki | grep -A6 "已生成管理员账号"
# 方式 3:容器已停止时也能用(不要求 running)
docker cp opsxloki:/app/data/initial-admin-password.txt ./
# 方式 4:直接读 named volume(宿主机 root)
sudo cat /var/lib/docker/volumes/opsx-loki_opsxloki-data/_data/initial-admin-password.txt
```
> ⚠️ **为什么不能只靠日志**:`docker logs` 只在**首次启动**打印一次;日志轮转或容器重启后,
> 数据库里已有用户,**不会再打印**。所以**文件才是可靠来源**。
>
> 💡 容器名说明:本 compose 指定了 `container_name: opsxloki`,所以可直接用 `opsxloki`。
> 若你的部署没有指定,用服务名形式更通用:`docker compose exec opsxloki cat ...`
**Kubernetes 环境(同一个文件)**:
```bash
# 读文件(推荐)
kubectl -n log exec deploy/opsx-loki -- cat /app/data/initial-admin-password.txt
# 首次启动日志
kubectl -n log logs deploy/opsx-loki | grep -A6 "已生成管理员账号"
# 拷到本地
kubectl -n log cp <pod-name>:/app/data/initial-admin-password.txt ./
```
**想自己指定密码(跳过随机生成)**:
```bash
# Docker Compose:部署前设置环境变量
export ADMIN_INIT_PASSWORD='your-strong-password'
docker compose up -d
# Kubernetes:在 deployment 的 env 中加入 ADMIN_INIT_PASSWORD
```
**安全说明**:
| 项 | 说明 |
|----|------|
| 密码文件权限 | `0600`,属主 `opsxloki` |
| 自动清理 | **admin 首次修改密码后,该文件自动删除**(见 `seed.CleanupInitPassword`) |
| 日志内容 | 仅在首次启动打印,且容器日志由运行时轮转 |
| 忘了密码 | 数据卷里文件仍在;若文件已删,用 `ADMIN_INIT_PASSWORD` 重新初始化(需清空数据卷) |
| 环境变量优先 | 设置了 `ADMIN_INIT_PASSWORD` 时不生成随机密码、不写文件 |
---
## 生产部署