Enhancement: better Crowdsec auth parsing, caching, and retries (#6419)

This commit is contained in:
shamoon
2026-03-13 21:58:24 -07:00
committed by GitHub
parent a6639b04b9
commit f7c12ad642
2 changed files with 104 additions and 8 deletions

View File

@@ -89,4 +89,76 @@ describe("widgets/crowdsec/proxy", () => {
expect(res.statusCode).toBe(500);
expect(res.body).toEqual({ error: "Failed to authenticate with Crowdsec" });
});
it("re-authenticates and retries once when API returns 401", async () => {
getServiceWidget.mockResolvedValue({
type: "crowdsec",
url: "http://cs",
username: "machine",
password: "pw",
});
httpProxy
.mockResolvedValueOnce([
200,
"application/json",
JSON.stringify({ token: "tok-old", expire: new Date(Date.now() + 60_000).toISOString() }),
])
.mockResolvedValueOnce([401, "application/json", Buffer.from("bad token")])
.mockResolvedValueOnce([
200,
"application/json",
JSON.stringify({ token: "tok-new", expire: new Date(Date.now() + 60_000).toISOString() }),
])
.mockResolvedValueOnce([200, "application/json", Buffer.from("data")]);
const req = { query: { group: "g", service: "svc", endpoint: "alerts", index: "0" } };
const res = createMockRes();
await crowdsecProxyHandler(req, res);
expect(httpProxy).toHaveBeenCalledTimes(4);
expect(httpProxy.mock.calls[3][1].headers.Authorization).toBe("Bearer tok-new");
expect(res.statusCode).toBe(200);
expect(res.body).toEqual(Buffer.from("data"));
});
it("returns 500 when 401 refresh fails to get a new token", async () => {
getServiceWidget.mockResolvedValue({
type: "crowdsec",
url: "http://cs",
username: "machine",
password: "pw",
});
httpProxy
.mockResolvedValueOnce([
200,
"application/json",
JSON.stringify({ token: "tok-old", expire: new Date(Date.now() + 60_000).toISOString() }),
])
.mockResolvedValueOnce([401, "application/json", Buffer.from("bad token")])
.mockResolvedValueOnce([500, "application/json", JSON.stringify({ error: "no token" })]);
const req = { query: { group: "g", service: "svc", endpoint: "alerts", index: "0" } };
const res = createMockRes();
await crowdsecProxyHandler(req, res);
expect(res.statusCode).toBe(500);
expect(res.body).toEqual({ error: "Failed to authenticate with Crowdsec" });
});
it("returns 500 when login response is not JSON", async () => {
getServiceWidget.mockResolvedValue({ type: "crowdsec", url: "http://cs", username: "machine", password: "pw" });
httpProxy.mockResolvedValueOnce([200, "text/plain", "not-json"]);
const req = { query: { group: "g", service: "svc", endpoint: "alerts", index: "0" } };
const res = createMockRes();
await crowdsecProxyHandler(req, res);
expect(res.statusCode).toBe(500);
expect(res.body).toEqual({ error: "Failed to authenticate with Crowdsec" });
});
});