Files
affiliate_dash/backend/internal/config/config_test.go
T
yml2213 d821fe13df fix(security): 分离 JWT 与数据加密密钥并新增启动安全体检
.env 中 JWT_SECRET 仍逐字节等于 .env.example 的示例值,且 DATA_ENCRYPTION_KEY
未设置、按 config.go 的回退逻辑实际等于 JWT_SECRET。任何见过仓库的人都能伪造
管理员 JWT,并解密库中全部 API Client / 回调密钥密文。

- JWT_SECRET 与 DATA_ENCRYPTION_KEY 改为各自独立的强随机值
- 新增 Config.SecurityWarnings():示例密钥 / 未分离 / release 下开调试日志均告警
- 新增 cmd/reencrypt_secrets:默认只预演,-apply 才写库;幂等,坏数据不中断整轮
- 新增 docs/密钥轮换说明.md;.gitignore 忽略 .env.bak*
- release 模式下关闭 OPEN_API_DEBUG
2026-10-06 19:42:42 +08:00

79 lines
2.2 KiB
Go

package config
import (
"strings"
"testing"
)
// containsWarning 判断告警列表里是否存在包含指定片段的告警。
func containsWarning(warnings []string, fragment string) bool {
for _, w := range warnings {
if strings.Contains(w, fragment) {
return true
}
}
return false
}
func TestSecurityWarnings(t *testing.T) {
cases := []struct {
name string
dataKeyEnv string
cfg Config
wantWarning string // 期望命中的告警片段;为空表示期望无任何告警
}{
{
name: "示例 JWT_SECRET 必须告警",
dataKeyEnv: "a-real-data-key",
cfg: Config{JWTSecret: exampleJWTSecret, DataEncryptionKey: "a-real-data-key", Mode: "debug"},
wantWarning: "JWT_SECRET",
},
{
name: "未显式设置 DATA_ENCRYPTION_KEY 时提示回退 JWT_SECRET",
dataKeyEnv: "",
cfg: Config{JWTSecret: "a-real-jwt-secret", DataEncryptionKey: "a-real-jwt-secret", Mode: "debug"},
wantWarning: "DATA_ENCRYPTION_KEY 未显式设置",
},
{
name: "示例 DATA_ENCRYPTION_KEY 必须告警",
dataKeyEnv: exampleDataKey,
cfg: Config{JWTSecret: "a-real-jwt-secret", DataEncryptionKey: exampleDataKey, Mode: "debug"},
wantWarning: "DATA_ENCRYPTION_KEY 仍是",
},
{
name: "release 模式开启 OPEN_API_DEBUG 必须告警",
dataKeyEnv: "a-real-data-key",
cfg: Config{JWTSecret: "a-real-jwt-secret", DataEncryptionKey: "a-real-data-key", Mode: "release", OpenAPIDebug: true},
wantWarning: "OPEN_API_DEBUG",
},
{
name: "健康配置不应产生任何告警",
dataKeyEnv: "a-real-data-key",
cfg: Config{
JWTSecret: "a-real-jwt-secret",
DataEncryptionKey: "a-real-data-key",
Mode: "release",
OpenAPIDebug: false,
},
wantWarning: "",
},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
t.Setenv("DATA_ENCRYPTION_KEY", tc.dataKeyEnv)
warnings := tc.cfg.SecurityWarnings()
if tc.wantWarning == "" {
if len(warnings) != 0 {
t.Fatalf("期望无告警,实际得到 %v", warnings)
}
return
}
if !containsWarning(warnings, tc.wantWarning) {
t.Fatalf("期望告警包含 %q,实际得到 %v", tc.wantWarning, warnings)
}
})
}
}