script/fmt now runs golines -m 77 after gofmt, repeating golines until it changes nothing, since one pass can leave a line the next splits. script/fmt-check fails when either would change a file. script/bootstrap installs golines v0.13.0 with go install, pinned to its commit, and checks the installed version with go version -m. The tree is reformatted. The longer lines this makes are fixed by hand: nolint directives moved onto their own line above the statement, one string split, and 20 functions over funlen's 80 lines shortened or split, RunWAF and limitPercentages among them. Model: opus-5-5
This commit is contained in:
1 parent
63e58e326b
commit
7f8a59de04
118 files changed
+9447
-2670
No files matched your search
@@ -44,7 +44,12 @@ const sqlInjection = "/?id=1'%20OR%20'1'='1"
|
||||
// core_rule_set_score, and that it has duration_core_rule_set_ms, or with no
|
||||
// score, that it has none of the three: the Core Rule Set did not inspect the
|
||||
// request.
|
||||
func wantCoreRuleSet(t *testing.T, line logLine, score *int, ruleIDs ...int) {
|
||||
func wantCoreRuleSet(
|
||||
t *testing.T,
|
||||
line logLine,
|
||||
score *int,
|
||||
ruleIDs ...int,
|
||||
) {
|
||||
t.Helper()
|
||||
|
||||
if !slices.Equal(line.CoreRuleSetRuleIDs, ruleIDs) {
|
||||
@@ -55,9 +60,12 @@ func wantCoreRuleSet(t *testing.T, line logLine, score *int, ruleIDs ...int) {
|
||||
switch {
|
||||
case score == nil &&
|
||||
(line.CoreRuleSetScore != nil || line.DurationCoreRuleSetMS != nil):
|
||||
t.Errorf("log line has core_rule_set_score %v and "+
|
||||
"duration_core_rule_set_ms %v, want neither",
|
||||
line.fields["core_rule_set_score"], line.fields["duration_core_rule_set_ms"])
|
||||
t.Errorf(
|
||||
"log line has core_rule_set_score %v and "+
|
||||
"duration_core_rule_set_ms %v, want neither",
|
||||
line.fields["core_rule_set_score"],
|
||||
line.fields["duration_core_rule_set_ms"],
|
||||
)
|
||||
case score != nil &&
|
||||
(line.CoreRuleSetScore == nil || *line.CoreRuleSetScore != *score):
|
||||
t.Errorf("log line has core_rule_set_score %v, want %d",
|
||||
@@ -82,11 +90,21 @@ func TestCoreRuleSetMatchAddsTheExploitSignatureTag(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
s, _, _ := startWithClock(t, "", map[string]string{wafMode: tc.mode})
|
||||
s, _, _ := startWithClock(
|
||||
t,
|
||||
"",
|
||||
map[string]string{wafMode: tc.mode},
|
||||
)
|
||||
|
||||
wantTags(t, s.request(client, sqlInjection, tc.status, tc.action),
|
||||
"exploitsignature")
|
||||
wantTags(t, s.get(client, http.StatusOK, requestlog.ActionForward))
|
||||
wantTags(
|
||||
t,
|
||||
s.request(client, sqlInjection, tc.status, tc.action),
|
||||
"exploitsignature",
|
||||
)
|
||||
wantTags(
|
||||
t,
|
||||
s.get(client, http.StatusOK, requestlog.ActionForward),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -103,7 +121,9 @@ func TestDetectedAttackIsRefusedByTagDenyLast(t *testing.T) {
|
||||
wantHeuristic(t, line, "tag_deny", `{"tag": "exploitsignature"}`)
|
||||
}
|
||||
|
||||
func TestCoreRuleSetRefusesAttacksInBlockModeAndOnlyLogsThemInDetectMode(t *testing.T) {
|
||||
func TestCoreRuleSetRefusesAttacksInBlockModeAndOnlyLogsThemInDetectMode(
|
||||
t *testing.T,
|
||||
) {
|
||||
t.Parallel()
|
||||
|
||||
for _, attack := range []struct {
|
||||
@@ -142,10 +162,19 @@ func TestCoreRuleSetRefusesAttacksInBlockModeAndOnlyLogsThemInDetectMode(t *test
|
||||
{block, requestlog.ActionBlockedByCoreRuleSet, http.StatusForbidden},
|
||||
{detect, requestlog.ActionForward, http.StatusOK},
|
||||
} {
|
||||
s, _, _ := startWithClock(t, "", map[string]string{wafMode: tc.mode})
|
||||
s, _, _ := startWithClock(
|
||||
t,
|
||||
"",
|
||||
map[string]string{wafMode: tc.mode},
|
||||
)
|
||||
|
||||
line := s.requestWithHeader(client, attack.path, attack.header,
|
||||
tc.status, tc.action)
|
||||
line := s.requestWithHeader(
|
||||
client,
|
||||
attack.path,
|
||||
attack.header,
|
||||
tc.status,
|
||||
tc.action,
|
||||
)
|
||||
wantCoreRuleSet(t, line, &attack.score, attack.ruleIDs...)
|
||||
}
|
||||
})
|
||||
@@ -167,8 +196,12 @@ func TestOrdinaryRequestIsInspectedAndPassed(t *testing.T) {
|
||||
|
||||
s, _, _ := startWithClock(t, "", map[string]string{wafMode: block})
|
||||
|
||||
line := s.request(client, "/owner/repo/src/branch/main/README.md?display=source",
|
||||
http.StatusOK, requestlog.ActionForward)
|
||||
line := s.request(
|
||||
client,
|
||||
"/owner/repo/src/branch/main/README.md?display=source",
|
||||
http.StatusOK,
|
||||
requestlog.ActionForward,
|
||||
)
|
||||
wantCoreRuleSet(t, line, new(0))
|
||||
}
|
||||
|
||||
@@ -188,26 +221,48 @@ func TestCoreRuleSetIsNotRunWhenOffOrForAnExemptClientPathOrRuleFileRefusal(
|
||||
|
||||
// A client in SWW_ALLOW_NETS, and a path SWW_WAF_EXEMPT_PATHS
|
||||
// exempts, are not inspected.
|
||||
line := s.request(allowed, sqlInjection, http.StatusOK, requestlog.ActionForward)
|
||||
line := s.request(
|
||||
allowed,
|
||||
sqlInjection,
|
||||
http.StatusOK,
|
||||
requestlog.ActionForward,
|
||||
)
|
||||
wantCoreRuleSet(t, line, nil)
|
||||
line = s.request(client, "/api/v1/repos?id=1'%20OR%20'1'='1", http.StatusOK,
|
||||
requestlog.ActionForward)
|
||||
line = s.request(
|
||||
client,
|
||||
"/api/v1/repos?id=1'%20OR%20'1'='1",
|
||||
http.StatusOK,
|
||||
requestlog.ActionForward,
|
||||
)
|
||||
wantCoreRuleSet(t, line, nil)
|
||||
|
||||
// The prefix is matched as rate limit exempt paths are: a path that
|
||||
// goes up and out of it is inspected.
|
||||
line = s.request(client, "/api/../?id=1'%20OR%20'1'='1", http.StatusForbidden,
|
||||
requestlog.ActionBlockedByCoreRuleSet)
|
||||
line = s.request(
|
||||
client,
|
||||
"/api/../?id=1'%20OR%20'1'='1",
|
||||
http.StatusForbidden,
|
||||
requestlog.ActionBlockedByCoreRuleSet,
|
||||
)
|
||||
wantCoreRuleSet(t, line, new(25), 930100, 930110, 942100)
|
||||
|
||||
// A request a rule file refuses is not inspected.
|
||||
line = s.request(otherClient, "/blocked?id=1'%20OR%20'1'='1", http.StatusForbidden,
|
||||
requestlog.ActionBlockedByBlockRule)
|
||||
line = s.request(
|
||||
otherClient,
|
||||
"/blocked?id=1'%20OR%20'1'='1",
|
||||
http.StatusForbidden,
|
||||
requestlog.ActionBlockedByBlockRule,
|
||||
)
|
||||
wantCoreRuleSet(t, line, nil)
|
||||
|
||||
// With SWW_WAF_MODE off, no request is.
|
||||
s, _, _ = startWithClock(t, "", map[string]string{wafMode: off})
|
||||
line = s.request(client, sqlInjection, http.StatusOK, requestlog.ActionForward)
|
||||
line = s.request(
|
||||
client,
|
||||
sqlInjection,
|
||||
http.StatusOK,
|
||||
requestlog.ActionForward,
|
||||
)
|
||||
wantCoreRuleSet(t, line, nil)
|
||||
}
|
||||
|
||||
@@ -221,7 +276,12 @@ func TestAnomalyThreshold(t *testing.T) {
|
||||
wafMode: block, wafAnomalyThreshold: threshold,
|
||||
})
|
||||
|
||||
line := s.request(client, sqlInjection, http.StatusOK, requestlog.ActionForward)
|
||||
line := s.request(
|
||||
client,
|
||||
sqlInjection,
|
||||
http.StatusOK,
|
||||
requestlog.ActionForward,
|
||||
)
|
||||
wantCoreRuleSet(t, line, new(5), 942100)
|
||||
}
|
||||
|
||||
@@ -269,9 +329,20 @@ func TestDisabledRulesSwitchOffWhatGiteaWouldBeRefused(t *testing.T) {
|
||||
}
|
||||
|
||||
// By default, the rules are switched off.
|
||||
s, _, _ := startWithClock(t, "", map[string]string{wafMode: block})
|
||||
line, _ := s.requestWithBody(request.method, client, request.path,
|
||||
request.header, body, http.StatusOK, requestlog.ActionForward)
|
||||
s, _, _ := startWithClock(
|
||||
t,
|
||||
"",
|
||||
map[string]string{wafMode: block},
|
||||
)
|
||||
line, _ := s.requestWithBody(
|
||||
request.method,
|
||||
client,
|
||||
request.path,
|
||||
request.header,
|
||||
body,
|
||||
http.StatusOK,
|
||||
requestlog.ActionForward,
|
||||
)
|
||||
wantCoreRuleSet(t, line, new(0))
|
||||
|
||||
// A list given replaces the default.
|
||||
@@ -279,12 +350,24 @@ func TestDisabledRulesSwitchOffWhatGiteaWouldBeRefused(t *testing.T) {
|
||||
wafMode: block, wafDisabledRules: "942100",
|
||||
})
|
||||
score := 5 * len(request.ruleIDs)
|
||||
line, _ = s.requestWithBody(request.method, client, request.path,
|
||||
request.header, body, http.StatusForbidden, requestlog.ActionBlockedByCoreRuleSet)
|
||||
line, _ = s.requestWithBody(
|
||||
request.method,
|
||||
client,
|
||||
request.path,
|
||||
request.header,
|
||||
body,
|
||||
http.StatusForbidden,
|
||||
requestlog.ActionBlockedByCoreRuleSet,
|
||||
)
|
||||
wantCoreRuleSet(t, line, &score, request.ruleIDs...)
|
||||
|
||||
// And switches off the rules it lists.
|
||||
line = s.request(client, sqlInjection, http.StatusOK, requestlog.ActionForward)
|
||||
line = s.request(
|
||||
client,
|
||||
sqlInjection,
|
||||
http.StatusOK,
|
||||
requestlog.ActionForward,
|
||||
)
|
||||
wantCoreRuleSet(t, line, new(0))
|
||||
})
|
||||
}
|
||||
@@ -354,8 +437,13 @@ func TestBodiesReachTheAppAsSentWhileBodiesAreRead(t *testing.T) {
|
||||
|
||||
got := do(t, req)
|
||||
if got.status != http.StatusOK || string(got.body) != tc.body {
|
||||
t.Errorf("%s: the app got %d bytes, answered %d, want the %d sent, 200",
|
||||
tc.name, len(got.body), got.status, len(tc.body))
|
||||
t.Errorf(
|
||||
"%s: the app got %d bytes, answered %d, want the %d sent, 200",
|
||||
tc.name,
|
||||
len(got.body),
|
||||
got.status,
|
||||
len(tc.body),
|
||||
)
|
||||
}
|
||||
|
||||
line := out.endedLines(t, i+1)[i]
|
||||
@@ -384,13 +472,19 @@ func TestResponsesAreNotInspected(t *testing.T) {
|
||||
|
||||
got := get(t, addr, "/owner/repo/raw/branch/main/build.sh")
|
||||
if got.status != http.StatusOK || string(got.body) != page {
|
||||
t.Errorf("answered %d with %q, want 200 with the app's page", got.status, got.body)
|
||||
t.Errorf(
|
||||
"answered %d with %q, want 200 with the app's page",
|
||||
got.status,
|
||||
got.body,
|
||||
)
|
||||
}
|
||||
|
||||
wantLine(t, out.endedLine(t), http.StatusOK, requestlog.ActionForward)
|
||||
}
|
||||
|
||||
func TestCoreRuleSetRefusalIsAnOffenceAndCountsTowardTheErrorBurst(t *testing.T) {
|
||||
func TestCoreRuleSetRefusalIsAnOffenceAndCountsTowardTheErrorBurst(
|
||||
t *testing.T,
|
||||
) {
|
||||
t.Parallel()
|
||||
|
||||
s, _, server := startWithClock(t, "", map[string]string{
|
||||
@@ -408,8 +502,11 @@ func TestCoreRuleSetRefusalIsAnOffenceAndCountsTowardTheErrorBurst(t *testing.T)
|
||||
requestlog.ActionBlockedByCoreRuleSet)
|
||||
if line.LimitHit != requestlog.LimitHitMinuteRefusals ||
|
||||
line.Offence != requestlog.OffenceLimit {
|
||||
t.Errorf("log line has limit_hit %q and offence %q, want minute_refusals and limit",
|
||||
line.LimitHit, line.Offence)
|
||||
t.Errorf(
|
||||
"log line has limit_hit %q and offence %q, want minute_refusals and limit",
|
||||
line.LimitHit,
|
||||
line.Offence,
|
||||
)
|
||||
}
|
||||
|
||||
s.get(client, http.StatusForbidden, requestlog.ActionTemporarilyBanned)
|
||||
@@ -420,15 +517,30 @@ func TestCoreRuleSetRefusalIsAnOffenceAndCountsTowardTheErrorBurst(t *testing.T)
|
||||
}
|
||||
|
||||
metrics := s.scrape()
|
||||
wantMetric(t, metrics,
|
||||
`sww_core_rule_set_matches_total{instance="app",mode="block",rule_id="942100"}`, 3)
|
||||
wantMetric(t, metrics,
|
||||
`sww_offences_total{instance="app",kind="blocked_by_core_rule_set"}`, 3)
|
||||
wantMetric(t, metrics, `sww_requests_total{action="blocked_by_core_rule_set",`+
|
||||
`instance="app",status_class="4xx"}`, 3)
|
||||
wantMetric(
|
||||
t,
|
||||
metrics,
|
||||
`sww_core_rule_set_matches_total{instance="app",mode="block",rule_id="942100"}`,
|
||||
3,
|
||||
)
|
||||
wantMetric(
|
||||
t,
|
||||
metrics,
|
||||
`sww_offences_total{instance="app",kind="blocked_by_core_rule_set"}`,
|
||||
3,
|
||||
)
|
||||
wantMetric(
|
||||
t,
|
||||
metrics,
|
||||
`sww_requests_total{action="blocked_by_core_rule_set",`+
|
||||
`instance="app",status_class="4xx"}`,
|
||||
3,
|
||||
)
|
||||
}
|
||||
|
||||
func TestDetectModeMatchIsNoOffenceAndNotCountedTowardTheErrorBurst(t *testing.T) {
|
||||
func TestDetectModeMatchIsNoOffenceAndNotCountedTowardTheErrorBurst(
|
||||
t *testing.T,
|
||||
) {
|
||||
t.Parallel()
|
||||
|
||||
s, _, server := startWithClock(t, "", map[string]string{
|
||||
@@ -436,7 +548,12 @@ func TestDetectModeMatchIsNoOffenceAndNotCountedTowardTheErrorBurst(t *testing.T
|
||||
})
|
||||
|
||||
for range 3 {
|
||||
s.request(client, sqlInjection, http.StatusOK, requestlog.ActionForward)
|
||||
s.request(
|
||||
client,
|
||||
sqlInjection,
|
||||
http.StatusOK,
|
||||
requestlog.ActionForward,
|
||||
)
|
||||
}
|
||||
|
||||
s.get(client, http.StatusOK, requestlog.ActionForward)
|
||||
@@ -447,8 +564,12 @@ func TestDetectModeMatchIsNoOffenceAndNotCountedTowardTheErrorBurst(t *testing.T
|
||||
}
|
||||
|
||||
metrics := s.scrape()
|
||||
wantMetric(t, metrics,
|
||||
`sww_core_rule_set_matches_total{instance="app",mode="detect",rule_id="942100"}`, 3)
|
||||
wantMetric(
|
||||
t,
|
||||
metrics,
|
||||
`sww_core_rule_set_matches_total{instance="app",mode="detect",rule_id="942100"}`,
|
||||
3,
|
||||
)
|
||||
wantNoSeries(t, metrics,
|
||||
`sww_offences_total{instance="app",kind="blocked_by_core_rule_set"}`)
|
||||
}
|
||||
@@ -456,9 +577,18 @@ func TestDetectModeMatchIsNoOffenceAndNotCountedTowardTheErrorBurst(t *testing.T
|
||||
func TestObserveModeLogsWhatTheCoreRuleSetWouldDo(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
s, _, server := startWithClock(t, "", map[string]string{wafMode: block, mode: observe})
|
||||
s, _, server := startWithClock(
|
||||
t,
|
||||
"",
|
||||
map[string]string{wafMode: block, mode: observe},
|
||||
)
|
||||
|
||||
line := s.request(client, sqlInjection, http.StatusOK, requestlog.ActionForward)
|
||||
line := s.request(
|
||||
client,
|
||||
sqlInjection,
|
||||
http.StatusOK,
|
||||
requestlog.ActionForward,
|
||||
)
|
||||
wantWouldAction(t, line, requestlog.ActionBlockedByCoreRuleSet)
|
||||
wantCoreRuleSet(t, line, new(5), 942100)
|
||||
|
||||
@@ -508,7 +638,9 @@ func TestCoreRuleSetMatchRaisesTheCoreRuleSetMatchAlert(t *testing.T) {
|
||||
s.get(client, http.StatusOK, requestlog.ActionForward)
|
||||
|
||||
detail := map[string]any{
|
||||
"rule_ids": []int{942100}, "score": 5, "method": http.MethodGet,
|
||||
"rule_ids": []int{
|
||||
942100,
|
||||
}, "score": 5, "method": http.MethodGet,
|
||||
"path": sqlInjection,
|
||||
}
|
||||
if tc.alertMode != "" {
|
||||
@@ -527,7 +659,10 @@ func TestCoreRuleSetMatchRaisesTheCoreRuleSetMatchAlert(t *testing.T) {
|
||||
})
|
||||
|
||||
if queue.Suppressed() != 1 {
|
||||
t.Errorf("%d alerts held back, want the repeat", queue.Suppressed())
|
||||
t.Errorf(
|
||||
"%d alerts held back, want the repeat",
|
||||
queue.Suppressed(),
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user