Name request log actions so they say what they mean (closes #229)
check / check (push) Failing after 14m41s
check / check (push) Failing after 14m41s
Rename too_large, rate_limited, rule_blocked and denied, and split banned into temporarily_banned and permanently_banned by whether the ban runs out. A client under both a temporary and a permanent ban gets the permanent one. A request that makes a ban permanent gets permanently_banned. A ban rule, a trap path or a CrowdSec decision gets the value for the ban it makes, and in observe mode would_action names the ban enforce mode would have made. The offence kind rule_blocked follows, as a metric label and a key in clients.json. Model: opus-5-5
This commit is contained in:
1 parent
6850cb0e9f
commit
d8fefb1288
48 files changed
+522
-300
No files matched your search
@@ -341,3 +341,48 @@ func TestLiftLiftsEveryActiveBanCoveringTheClient(t *testing.T) {
|
||||
|
||||
wantChanged(t, ledger, false)
|
||||
}
|
||||
|
||||
func TestPermanentBanOnAWiderNetblockIsReturnedOverATemporaryBan(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
client := netip.MustParseAddr("203.0.113.9")
|
||||
ledger := bans.New(defaultRules())
|
||||
|
||||
// The temporary ban is made first, so that its netblock is looked at first.
|
||||
ledger.BanForLimit(netip.MustParsePrefix("203.0.113.9/32"), midnight(), bans.Notes{})
|
||||
ledger.BanForAdmin(netip.MustParsePrefix("203.0.113.0/24"), midnight(), time.Time{},
|
||||
"for good")
|
||||
|
||||
wantPermanentBan(t, ledger, client, midnight().Add(time.Minute))
|
||||
}
|
||||
|
||||
func TestOlderPermanentBanIsReturnedOverANewerTemporaryBan(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
netblock := netip.MustParsePrefix("203.0.113.0/24")
|
||||
ledger := bans.New(defaultRules())
|
||||
|
||||
ledger.BanForAdmin(netblock, midnight(), time.Time{}, "for good")
|
||||
ledger.BanForAdmin(netblock, midnight().Add(time.Minute), midnight().Add(time.Hour),
|
||||
"for an hour")
|
||||
|
||||
wantPermanentBan(t, ledger, netblock.Addr(), midnight().Add(2*time.Minute))
|
||||
}
|
||||
|
||||
// wantPermanentBan checks that Find and Check return a permanent ban for
|
||||
// client at now.
|
||||
func wantPermanentBan(
|
||||
t *testing.T, ledger *bans.Ledger, client netip.Addr, now time.Time,
|
||||
) {
|
||||
t.Helper()
|
||||
|
||||
for name, look := range map[string]func(netip.Addr, time.Time) (bans.Ban, bool, bool){
|
||||
"Find": ledger.Find,
|
||||
"Check": ledger.Check,
|
||||
} {
|
||||
ban, banned, _ := look(client, now)
|
||||
if !banned || !ban.Permanent() {
|
||||
t.Errorf("%s returned %+v and banned %v, want a permanent ban", name, ban, banned)
|
||||
}
|
||||
}
|
||||
}
|
||||
+29
-7
@@ -274,16 +274,27 @@ func (l *Ledger) Find(client netip.Addr, now time.Time) (Ban, bool, bool) {
|
||||
|
||||
// activeBan returns the ban in bans, a netblock's bans oldest first, that
|
||||
// is active at now, or nil when none is. If several are, it returns the
|
||||
// one that started last. Every ban is looked at, since a ban an admin adds
|
||||
// to bans.json can start before the netblock's others and outlast them.
|
||||
// newest permanent one, or the newest when none is permanent. Every ban is
|
||||
// looked at, since a ban an admin adds to bans.json can start before the
|
||||
// netblock's others and outlast them.
|
||||
func activeBan(bans []Ban, now time.Time) *Ban {
|
||||
var newest *Ban
|
||||
|
||||
for i := len(bans) - 1; i >= 0; i-- {
|
||||
if bans[i].ActiveAt(now) {
|
||||
if !bans[i].ActiveAt(now) {
|
||||
continue
|
||||
}
|
||||
|
||||
if bans[i].Permanent() {
|
||||
return &bans[i]
|
||||
}
|
||||
|
||||
if newest == nil {
|
||||
newest = &bans[i]
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return newest
|
||||
}
|
||||
|
||||
// BanForLimit bans netblock at now for a broken limit, with notes, and
|
||||
@@ -743,13 +754,16 @@ func (l *Ledger) markChanged() {
|
||||
}
|
||||
|
||||
// active returns the ban active at now on a netblock client is in, or
|
||||
// nil.
|
||||
// nil. If several netblocks have one, it returns a permanent ban when
|
||||
// there is one.
|
||||
func (l *Ledger) active(client netip.Addr, now time.Time) *Ban {
|
||||
lengths := l.v6Lengths
|
||||
if client.Is4() {
|
||||
lengths = l.v4Lengths
|
||||
}
|
||||
|
||||
var first *Ban
|
||||
|
||||
for _, length := range lengths {
|
||||
bans, found := l.netblocks.Get(netip.PrefixFrom(client, length).Masked())
|
||||
if !found {
|
||||
@@ -757,12 +771,20 @@ func (l *Ledger) active(client netip.Addr, now time.Time) *Ban {
|
||||
}
|
||||
|
||||
ban := activeBan(*bans, now)
|
||||
if ban != nil {
|
||||
if ban == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if ban.Permanent() {
|
||||
return ban
|
||||
}
|
||||
|
||||
if first == nil {
|
||||
first = ban
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return first
|
||||
}
|
||||
|
||||
// covering returns the bans of each netblock held that client is in,
|
||||
|
||||
Reference in new issue
Block a user