fix(conf): 样例配置去掉行尾注释(会被并入值导致静默失效)
conf.Init 用 ini.LoadOptions{IgnoreInlineComment: true},该选项的语义是
**不剥离**行尾注释:`port = 1440 ; 注释` 解析出来的值是 "1440 ; 注释",
int 解析失败,而 MapTo 仍然返回 nil error —— 配置项静默回退零值。
实测照抄 app.sample.ini 的后果:
- text_censor_source 的值带注释,被 validateTextCensorSource 拒绝,直接起不来;
- ip_blacklist / security_alert_email 变成带注释的垃圾字符串;
- honeypot_max_rows / honeypot_auto_clean 静默失效(后者靠 sanitize 兜底才没出事)。
改动:
- 17 处 `key = value ; 注释` 改成「注释独占一行 + 裸值」,保留 CRLF;
- 蜜罐段补 honeypot_cred_dir,以及「提交凭据才封禁」的语义说明;
- 新增 TestSampleIniValuesHaveNoInlineComment:遍历所有段的键,断言值不含 ';'
(比逐字段断言彻底,新增配置项自动纳入)。
变异验证:给 ban_window_seconds 加回行尾注释,测试按预期失败;
- keynorm_test 补 HoneypotBanMinutes 的缺省值断言(缺省 1440 / 显式 0 交给 autoban 回退)。
This commit is contained in:
@@ -236,6 +236,7 @@ func TestSanitizeHoneypotDefaults(t *testing.T) {
|
||||
wantMaxRows int
|
||||
wantAutoClean bool
|
||||
wantThreshold int
|
||||
wantBan int
|
||||
}{
|
||||
{
|
||||
name: "全未配置时回退安全默认值",
|
||||
@@ -244,6 +245,7 @@ func TestSanitizeHoneypotDefaults(t *testing.T) {
|
||||
wantMaxRows: DefaultHoneypotMaxRows,
|
||||
wantAutoClean: true,
|
||||
wantThreshold: DefaultHoneypotThreshold,
|
||||
wantBan: DefaultHoneypotBanMinutes,
|
||||
},
|
||||
{
|
||||
name: "显式关闭自动清理被尊重",
|
||||
@@ -252,6 +254,7 @@ func TestSanitizeHoneypotDefaults(t *testing.T) {
|
||||
wantMaxRows: DefaultHoneypotMaxRows,
|
||||
wantAutoClean: false,
|
||||
wantThreshold: DefaultHoneypotThreshold,
|
||||
wantBan: DefaultHoneypotBanMinutes,
|
||||
},
|
||||
{
|
||||
name: "显式保留期被采用",
|
||||
@@ -260,6 +263,7 @@ func TestSanitizeHoneypotDefaults(t *testing.T) {
|
||||
wantMaxRows: DefaultHoneypotMaxRows,
|
||||
wantAutoClean: true,
|
||||
wantThreshold: DefaultHoneypotThreshold,
|
||||
wantBan: DefaultHoneypotBanMinutes,
|
||||
},
|
||||
{
|
||||
name: "保留期写成 0 回退默认而非永不清理",
|
||||
@@ -268,6 +272,7 @@ func TestSanitizeHoneypotDefaults(t *testing.T) {
|
||||
wantMaxRows: DefaultHoneypotMaxRows,
|
||||
wantAutoClean: true,
|
||||
wantThreshold: DefaultHoneypotThreshold,
|
||||
wantBan: DefaultHoneypotBanMinutes,
|
||||
},
|
||||
{
|
||||
name: "行数上限显式 0 表示不限",
|
||||
@@ -276,6 +281,27 @@ func TestSanitizeHoneypotDefaults(t *testing.T) {
|
||||
wantMaxRows: 0,
|
||||
wantAutoClean: true,
|
||||
wantThreshold: DefaultHoneypotThreshold,
|
||||
wantBan: DefaultHoneypotBanMinutes,
|
||||
},
|
||||
{
|
||||
name: "显式封禁时长被采用",
|
||||
src: "[security]\nhoneypot_ban_minutes = 90\n",
|
||||
wantRetain: DefaultHoneypotRetainDays,
|
||||
wantMaxRows: DefaultHoneypotMaxRows,
|
||||
wantAutoClean: true,
|
||||
wantThreshold: DefaultHoneypotThreshold,
|
||||
wantBan: 90,
|
||||
},
|
||||
{
|
||||
// 0 是逃生口:留着让 autoban 回退 ban_duration_minutes,
|
||||
// sanitize 不做覆盖(只告警),故期望值仍是 0。
|
||||
name: "封禁时长写 0 交给 autoban 回退 ban_duration_minutes",
|
||||
src: "[security]\nhoneypot_ban_minutes = 0\n",
|
||||
wantRetain: DefaultHoneypotRetainDays,
|
||||
wantMaxRows: DefaultHoneypotMaxRows,
|
||||
wantAutoClean: true,
|
||||
wantThreshold: DefaultHoneypotThreshold,
|
||||
wantBan: 0,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -290,6 +316,7 @@ func TestSanitizeHoneypotDefaults(t *testing.T) {
|
||||
Security.HoneypotMaxRows = 0
|
||||
Security.HoneypotAutoClean = false
|
||||
Security.HoneypotThreshold = 0
|
||||
Security.HoneypotBanMinutes = 0
|
||||
File = f
|
||||
if err := f.Section("security").MapTo(&Security); err != nil {
|
||||
t.Fatalf("map security: %v", err)
|
||||
@@ -308,6 +335,9 @@ func TestSanitizeHoneypotDefaults(t *testing.T) {
|
||||
if Security.HoneypotThreshold != c.wantThreshold {
|
||||
t.Errorf("HoneypotThreshold = %d, want %d", Security.HoneypotThreshold, c.wantThreshold)
|
||||
}
|
||||
if Security.HoneypotBanMinutes != c.wantBan {
|
||||
t.Errorf("HoneypotBanMinutes = %d, want %d", Security.HoneypotBanMinutes, c.wantBan)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -358,6 +388,34 @@ func TestSampleIniHasNoUnknownKeys(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestSampleIniValuesHaveNoInlineComment 守住「行尾注释会被并入值」的陷阱。
|
||||
//
|
||||
// conf.Init 用 ini.LoadOptions{IgnoreInlineComment: true},该选项的语义是
|
||||
// **不剥离**行尾注释(实测 `port = 1440 ; 注释` → 值 "1440 ; 注释",
|
||||
// int 解析失败,而 MapTo 仍然返回 nil error)。后果是该配置项静默回退零值,
|
||||
// 日志里只会说「配置值不对」,根本联想不到是注释造成的。
|
||||
//
|
||||
// 样例配置曾经全线是 `key = value ; 注释` 的写法:text_censor_source 因此
|
||||
// 让 conf.Init 直接拒绝启动,ip_blacklist / security_alert_email 变成带注释的
|
||||
// 垃圾字符串,honeypot_max_rows / honeypot_auto_clean 静默失效。
|
||||
//
|
||||
// 直接检查每个键的值里没有 ';',比逐个字段断言更彻底,也不会漏掉新加的配置项。
|
||||
func TestSampleIniValuesHaveNoInlineComment(t *testing.T) {
|
||||
path := filepath.Join("..", "..", "conf", "app.sample.ini")
|
||||
f, err := ini.LoadSources(ini.LoadOptions{IgnoreInlineComment: true}, path)
|
||||
if err != nil {
|
||||
t.Skipf("跳过:无法读取样例配置 %s(%v)", path, err)
|
||||
}
|
||||
for _, sec := range f.Sections() {
|
||||
for _, k := range sec.Keys() {
|
||||
if strings.Contains(k.Value(), ";") {
|
||||
t.Errorf("样例配置 [%s] %s 的值含 ';':%q —— 行尾注释会被并入值,该项将静默失效",
|
||||
sec.Name(), k.Name(), k.Value())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestNormalizeAllSectionKeysEndToEnd 走完整链路:
|
||||
// 加载带错拼键的配置 → 归一化 → MapTo → 拿到正确的保留期。
|
||||
//
|
||||
|
||||
Reference in New Issue
Block a user