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
@@ -37,7 +37,9 @@ const (
|
||||
rangeScope = "Range"
|
||||
)
|
||||
|
||||
func TestCrowdSecDecisionBansItsNetblockUntilItEndsEvenWithTheEngineDown(t *testing.T) {
|
||||
func TestCrowdSecDecisionBansItsNetblockUntilItEndsEvenWithTheEngineDown(
|
||||
t *testing.T,
|
||||
) {
|
||||
t.Parallel()
|
||||
|
||||
synctest.Test(t, func(t *testing.T) {
|
||||
@@ -48,7 +50,13 @@ func TestCrowdSecDecisionBansItsNetblockUntilItEndsEvenWithTheEngineDown(t *test
|
||||
// A shorter decision on the same address, which is not the one
|
||||
// used.
|
||||
{"Ip", suspect, ban, sshBF, began.Add(4 * time.Hour)},
|
||||
{rangeScope, "198.51.100.0/24", ban, probing, began.Add(time.Hour)},
|
||||
{
|
||||
rangeScope,
|
||||
"198.51.100.0/24",
|
||||
ban,
|
||||
probing,
|
||||
began.Add(time.Hour),
|
||||
},
|
||||
{"Ip", "2001:db8::1", ban, sshBF, began.Add(2 * time.Hour)},
|
||||
// Left out: a decision to show a captcha, and one on a country.
|
||||
{"Ip", "192.0.2.50", "captcha", probing, began.Add(time.Hour)},
|
||||
@@ -74,14 +82,28 @@ func TestCrowdSecDecisionBansItsNetblockUntilItEndsEvenWithTheEngineDown(t *test
|
||||
e.set(func(e *engine) { e.failing = true })
|
||||
time.Sleep(time.Hour - time.Nanosecond)
|
||||
synctest.Wait()
|
||||
wantDecision(t, lists, "198.51.100.7",
|
||||
reputation.Decision{Expires: began.Add(time.Hour), Scenario: probing})
|
||||
wantDecision(
|
||||
t,
|
||||
lists,
|
||||
"198.51.100.7",
|
||||
reputation.Decision{
|
||||
Expires: began.Add(time.Hour),
|
||||
Scenario: probing,
|
||||
},
|
||||
)
|
||||
|
||||
time.Sleep(time.Nanosecond)
|
||||
synctest.Wait()
|
||||
wantDecision(t, lists, "198.51.100.7", reputation.Decision{})
|
||||
wantDecision(t, lists, suspect,
|
||||
reputation.Decision{Expires: began.Add(6 * time.Hour), Scenario: manual})
|
||||
wantDecision(
|
||||
t,
|
||||
lists,
|
||||
suspect,
|
||||
reputation.Decision{
|
||||
Expires: began.Add(6 * time.Hour),
|
||||
Scenario: manual,
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -96,7 +118,10 @@ func TestCrowdSecDecisionListFetchedAgainEveryMinute(t *testing.T) {
|
||||
lists := start(t, e, crowdSecParams())
|
||||
wantEngineFetches(t, e, 1)
|
||||
|
||||
added := reputation.Decision{Expires: began.Add(2 * time.Hour), Scenario: probing}
|
||||
added := reputation.Decision{
|
||||
Expires: began.Add(2 * time.Hour),
|
||||
Scenario: probing,
|
||||
}
|
||||
|
||||
e.set(func(e *engine) {
|
||||
e.decisions = append(e.decisions,
|
||||
@@ -125,23 +150,58 @@ func TestCrowdSecDecisionOnAClientIsTheOneThatEndsLast(t *testing.T) {
|
||||
// 198.51.100.130 is held by a decision on its address that ends
|
||||
// after the one on its netblock, and 192.0.2.20 by one that ends
|
||||
// before.
|
||||
{rangeScope, "198.51.100.128/25", ban, sshBF, began.Add(time.Hour)},
|
||||
{
|
||||
rangeScope,
|
||||
"198.51.100.128/25",
|
||||
ban,
|
||||
sshBF,
|
||||
began.Add(time.Hour),
|
||||
},
|
||||
{"Ip", "198.51.100.130", ban, probing, began.Add(3 * time.Hour)},
|
||||
{rangeScope, "192.0.2.0/24", ban, probing, began.Add(5 * time.Hour)},
|
||||
{
|
||||
rangeScope,
|
||||
"192.0.2.0/24",
|
||||
ban,
|
||||
probing,
|
||||
began.Add(5 * time.Hour),
|
||||
},
|
||||
{"Ip", "192.0.2.20", ban, sshBF, began.Add(2 * time.Hour)},
|
||||
}}
|
||||
lists := start(t, e, crowdSecParams())
|
||||
|
||||
wantDecision(t, lists, suspect,
|
||||
reputation.Decision{Expires: began.Add(4 * time.Hour), Scenario: probing})
|
||||
wantDecision(t, lists, "198.51.100.130",
|
||||
reputation.Decision{Expires: began.Add(3 * time.Hour), Scenario: probing})
|
||||
wantDecision(t, lists, "192.0.2.20",
|
||||
reputation.Decision{Expires: began.Add(5 * time.Hour), Scenario: probing})
|
||||
wantDecision(
|
||||
t,
|
||||
lists,
|
||||
suspect,
|
||||
reputation.Decision{
|
||||
Expires: began.Add(4 * time.Hour),
|
||||
Scenario: probing,
|
||||
},
|
||||
)
|
||||
wantDecision(
|
||||
t,
|
||||
lists,
|
||||
"198.51.100.130",
|
||||
reputation.Decision{
|
||||
Expires: began.Add(3 * time.Hour),
|
||||
Scenario: probing,
|
||||
},
|
||||
)
|
||||
wantDecision(
|
||||
t,
|
||||
lists,
|
||||
"192.0.2.20",
|
||||
reputation.Decision{
|
||||
Expires: began.Add(5 * time.Hour),
|
||||
Scenario: probing,
|
||||
},
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
func TestCrowdSecAnswerOfNoDecisionIsAGoodCopyThatListsNoClient(t *testing.T) {
|
||||
func TestCrowdSecAnswerOfNoDecisionIsAGoodCopyThatListsNoClient(
|
||||
t *testing.T,
|
||||
) {
|
||||
t.Parallel()
|
||||
|
||||
synctest.Test(t, func(t *testing.T) {
|
||||
@@ -203,27 +263,43 @@ func TestCrowdSecFailureKeepsTheLastGoodCopyAlertsOncePerCooldownAndHidesTheKey(
|
||||
}
|
||||
|
||||
wantEngineFetches(t, e, 3)
|
||||
wantDecision(t, lists, suspect,
|
||||
reputation.Decision{Expires: began.Add(4 * time.Hour), Scenario: sshBF})
|
||||
wantDecision(
|
||||
t,
|
||||
lists,
|
||||
suspect,
|
||||
reputation.Decision{
|
||||
Expires: began.Add(4 * time.Hour),
|
||||
Scenario: sshBF,
|
||||
},
|
||||
)
|
||||
|
||||
want := kept[0]
|
||||
want.Tried = time.Now()
|
||||
|
||||
if got := lists.Snapshot(); !reflect.DeepEqual(got, []reputation.List{want}) {
|
||||
t.Errorf("lists %+v, want the first copy, last tried now, %+v", got, want)
|
||||
got := lists.Snapshot()
|
||||
if !reflect.DeepEqual(got, []reputation.List{want}) {
|
||||
t.Errorf(
|
||||
"lists %+v, want the first copy, last tried now, %+v",
|
||||
got,
|
||||
want,
|
||||
)
|
||||
}
|
||||
|
||||
if lists.Failures(decisionsURL) != 2 {
|
||||
t.Errorf("%d failures, want 2", lists.Failures(decisionsURL))
|
||||
if n := lists.Failures(decisionsURL); n != 2 {
|
||||
t.Errorf("%d failures, want 2", n)
|
||||
}
|
||||
|
||||
// One alert for the first failure; the cooldown holds back the
|
||||
// second.
|
||||
wantAlert(t, queue,
|
||||
fetchFailure(time.Now().Add(-time.Minute), decisionsURL, tc.error))
|
||||
failed := time.Now().Add(-time.Minute)
|
||||
alert := fetchFailure(failed, decisionsURL, tc.error)
|
||||
wantAlert(t, queue, alert)
|
||||
|
||||
if !strings.Contains(log.String(), `"msg":"fetching a list failed",`+
|
||||
`"url":"`+decisionsURL+`","error":"`+tc.error) {
|
||||
if !strings.Contains(
|
||||
log.String(),
|
||||
`"msg":"fetching a list failed",`+
|
||||
`"url":"`+decisionsURL+`","error":"`+tc.error,
|
||||
) {
|
||||
t.Errorf("logged\n%s\nwant the failures", log.String())
|
||||
}
|
||||
|
||||
@@ -293,7 +369,11 @@ func crowdSecFailures() []crowdSecFailure {
|
||||
// log, the alerts waiting in queue, and the copies of lists, which
|
||||
// lists.json keeps.
|
||||
func wantKeyNotShown(
|
||||
t *testing.T, e *engine, log string, lists *reputation.Lists, queue *alerts.Queue,
|
||||
t *testing.T,
|
||||
e *engine,
|
||||
log string,
|
||||
lists *reputation.Lists,
|
||||
queue *alerts.Queue,
|
||||
) {
|
||||
t.Helper()
|
||||
|
||||
@@ -315,13 +395,21 @@ func wantKeyNotShown(
|
||||
}
|
||||
}
|
||||
|
||||
func TestCrowdSecDecisionListKeptAcrossARestartEndsWhenItsDecisionsDo(t *testing.T) {
|
||||
func TestCrowdSecDecisionListKeptAcrossARestartEndsWhenItsDecisionsDo(
|
||||
t *testing.T,
|
||||
) {
|
||||
t.Parallel()
|
||||
|
||||
synctest.Test(t, func(t *testing.T) {
|
||||
began := time.Now()
|
||||
e := &engine{key: engineKey, decisions: []decision{
|
||||
{rangeScope, "198.51.100.0/24", ban, probing, began.Add(time.Hour)},
|
||||
{
|
||||
rangeScope,
|
||||
"198.51.100.0/24",
|
||||
ban,
|
||||
probing,
|
||||
began.Add(time.Hour),
|
||||
},
|
||||
}}
|
||||
lists := start(t, e, crowdSecParams())
|
||||
kept := lists.Snapshot()
|
||||
@@ -342,7 +430,10 @@ func TestCrowdSecDecisionListKeptAcrossARestartEndsWhenItsDecisionsDo(t *testing
|
||||
|
||||
run(t, again)
|
||||
|
||||
want := reputation.Decision{Expires: began.Add(time.Hour), Scenario: probing}
|
||||
want := reputation.Decision{
|
||||
Expires: began.Add(time.Hour),
|
||||
Scenario: probing,
|
||||
}
|
||||
wantDecision(t, again, "198.51.100.7", want)
|
||||
|
||||
time.Sleep(30*time.Minute - time.Nanosecond)
|
||||
@@ -415,7 +506,8 @@ func (e *engine) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
|
||||
e.fetches++
|
||||
|
||||
if req.URL.String() != decisionsURL && req.Header.Get("X-Api-Key") != "" {
|
||||
if req.URL.String() != decisionsURL &&
|
||||
req.Header.Get("X-Api-Key") != "" {
|
||||
e.keySentTo = append(e.keySentTo, req.URL.String())
|
||||
}
|
||||
|
||||
@@ -425,7 +517,9 @@ func (e *engine) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
case req.URL.String() != decisionsURL || req.Header.Get("X-Api-Key") != e.key:
|
||||
status, body = http.StatusForbidden, `{"message":"access forbidden"}`
|
||||
case e.redirect != "":
|
||||
status, header = http.StatusFound, http.Header{"Location": {e.redirect}}
|
||||
status, header = http.StatusFound, http.Header{
|
||||
"Location": {e.redirect},
|
||||
}
|
||||
case e.failing:
|
||||
status, body = http.StatusServiceUnavailable, ""
|
||||
case body == "":
|
||||
@@ -449,7 +543,9 @@ func (e *engine) inForce(now time.Time) string {
|
||||
for _, d := range e.decisions {
|
||||
if now.Before(d.expires) {
|
||||
answer = append(answer, map[string]string{
|
||||
"duration": d.expires.Sub(now).String(), "origin": "crowdsec",
|
||||
"duration": d.expires.Sub(now).
|
||||
String(),
|
||||
"origin": "crowdsec",
|
||||
"scenario": d.scenario, "scope": d.scope, "type": d.kind, "value": d.value,
|
||||
})
|
||||
}
|
||||
@@ -501,13 +597,26 @@ func wantEngineFetches(t *testing.T, e *engine, want int) {
|
||||
// wantDecision checks the decision lists says is in force on addr now,
|
||||
// the zero Decision for none.
|
||||
func wantDecision(
|
||||
t *testing.T, lists *reputation.Lists, addr string, want reputation.Decision,
|
||||
t *testing.T,
|
||||
lists *reputation.Lists,
|
||||
addr string,
|
||||
want reputation.Decision,
|
||||
) {
|
||||
t.Helper()
|
||||
|
||||
got, listed := lists.CrowdSecDecision(netip.MustParseAddr(addr), time.Now())
|
||||
got, listed := lists.CrowdSecDecision(
|
||||
netip.MustParseAddr(addr),
|
||||
time.Now(),
|
||||
)
|
||||
if listed != !want.Expires.IsZero() ||
|
||||
listed && (!got.Expires.Equal(want.Expires) || got.Scenario != want.Scenario) {
|
||||
t.Errorf("%s has the decision %+v in force %t, want %+v", addr, got, listed, want)
|
||||
listed &&
|
||||
(!got.Expires.Equal(want.Expires) || got.Scenario != want.Scenario) {
|
||||
t.Errorf(
|
||||
"%s has the decision %+v in force %t, want %+v",
|
||||
addr,
|
||||
got,
|
||||
listed,
|
||||
want,
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user