feat(security): recovery alerts, gate-block sharing, rolling-window burst and admin breakdown for CrowdSec
Gitea Actions Runner Test / test-job (push) Successful in 1s
CI / check (push) Successful in 30s
CI / tests-integration (push) Successful in 1m42s
CI / tests-unit (push) Successful in 1m50s
CI / tests-ui (push) Successful in 2m42s
CI / preflight (push) Skipped
CI / deploy (push) Successful in 2m3s

This commit is contained in:
openhands committed 2026-09-23 15:06:16 +02:00
1 parent 301edd2c9a
commit 3e1a3f92c8
8 files changed
+448 -65

No files matched your search

+37
View File
@@ -323,6 +323,43 @@ describe("crowdsec-report", () => {
expect(state.sendAlert).not.toHaveBeenCalled();
});
it("raises an info alert the first time the channel heals after failures", async () => {
fetchMock.mockImplementation((url: string) => {
const path = String(url).replace(CAPI, "");
if (path === "/watchers/login") {
return Promise.resolve(
jsonResponse({
token: "jwt-xyz",
expire: new Date(Date.now() + 3_600_000).toISOString(),
}),
);
}
if (path === "/signals") {
return Promise.resolve(jsonResponse({ message: "boom" }, 500));
}
return Promise.resolve(jsonResponse({}));
});
await reportCrowdsecSignal(signalInput("198.51.100.40"));
await tick();
expect(state.sendAlert).toHaveBeenCalledTimes(1);
expect((await getLastCrowdsecReport())?.ok).toBe(false);
// Channel heals: the first success after a failure is worth a notice.
routeCapi();
await reportCrowdsecSignal(signalInput("198.51.100.41"));
await tick();
const last: CrowdsecReportStatus | null = await getLastCrowdsecReport();
expect(last?.ok).toBe(true);
expect(state.sendAlert).toHaveBeenCalledTimes(2);
const alerts = state.sendAlert.mock.calls.map(([input]) => input);
expect(alerts[0].severity).toBe("warning");
expect(alerts[1].severity).toBe("info");
expect(alerts[1].message).toContain("recovered");
expect(alerts[1].context).toMatchObject({ ip: "198.51.100.41" });
});
it("verifies the watcher channel end to end", async () => {
routeCapi();
const status = await verifyCrowdsecReporting();