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
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:
1 parent
301edd2c9a
commit
3e1a3f92c8
8 files changed
+448
-65
No files matched your search
@@ -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();
|
||||
|
||||
Reference in new issue
Block a user