mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 04:51:51 +00:00
147 lines
4.3 KiB
TypeScript
147 lines
4.3 KiB
TypeScript
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
|
|
import { DOCS_URLS } from "@/lib/external-urls";
|
|
import { isCloud } from "@/lib/shared/env";
|
|
import {
|
|
ATTACK_PATH_QUERY_IDS,
|
|
type AttackPathQuery,
|
|
type AttackPathQueryParameter,
|
|
type AttackPathQueryResultSummary,
|
|
} from "@/types/attack-paths";
|
|
|
|
import {
|
|
adaptAttackPathQueriesResponse,
|
|
buildAttackPathQueries,
|
|
} from "./queries.adapter";
|
|
|
|
vi.mock("@/lib/shared/env", () => ({ isCloud: vi.fn() }));
|
|
|
|
// Empty-query filtering only applies in Prowler Cloud; default the flag on for
|
|
// the filtering suite and cover the self-hosted (flag off) case explicitly.
|
|
beforeEach(() => {
|
|
vi.mocked(isCloud).mockReturnValue(true);
|
|
});
|
|
|
|
const presetQuery: AttackPathQuery = {
|
|
type: "attack-paths-scans",
|
|
id: "preset-query",
|
|
attributes: {
|
|
name: "Preset Query",
|
|
short_description: "Returns privileged attack paths",
|
|
description: "Returns privileged attack paths.",
|
|
provider: "aws",
|
|
attribution: null,
|
|
parameters: [],
|
|
},
|
|
};
|
|
|
|
const makeQuery = (
|
|
id: string,
|
|
overrides: {
|
|
result_summary?: AttackPathQueryResultSummary | null;
|
|
parameters?: AttackPathQueryParameter[];
|
|
} = {},
|
|
): AttackPathQuery => ({
|
|
type: "attack-paths-scans",
|
|
id,
|
|
attributes: {
|
|
name: id,
|
|
short_description: "",
|
|
description: "",
|
|
provider: "aws",
|
|
attribution: null,
|
|
parameters: overrides.parameters ?? [],
|
|
result_summary: overrides.result_summary,
|
|
},
|
|
});
|
|
|
|
describe("adaptAttackPathQueriesResponse filtering", () => {
|
|
it("keeps only queries with data, plus everything without a definite empty verdict", () => {
|
|
const response = {
|
|
data: [
|
|
makeQuery("has-data", {
|
|
result_summary: { status: "ok", has_data: true },
|
|
}),
|
|
makeQuery("empty", {
|
|
result_summary: { status: "ok", has_data: false },
|
|
}),
|
|
makeQuery("errored", {
|
|
result_summary: { status: "error", has_data: null },
|
|
}),
|
|
makeQuery("parameterized", {
|
|
parameters: [
|
|
{
|
|
name: "ip",
|
|
label: "IP",
|
|
data_type: "string",
|
|
} as AttackPathQueryParameter,
|
|
],
|
|
result_summary: null,
|
|
}),
|
|
makeQuery("no-summary"), // scan predating the precompute step
|
|
],
|
|
};
|
|
|
|
const ids = adaptAttackPathQueriesResponse(response).data.map((q) => q.id);
|
|
|
|
// the only one hidden is the parameterless query known to be empty
|
|
expect(ids).toEqual(["has-data", "errored", "parameterized", "no-summary"]);
|
|
expect(ids).not.toContain("empty");
|
|
});
|
|
|
|
it("returns an empty list for a missing response", () => {
|
|
expect(adaptAttackPathQueriesResponse(undefined).data).toEqual([]);
|
|
});
|
|
|
|
it("updates the pagination count to the filtered length", () => {
|
|
const response = {
|
|
data: [
|
|
makeQuery("a", { result_summary: { status: "ok", has_data: true } }),
|
|
makeQuery("b", { result_summary: { status: "ok", has_data: false } }),
|
|
],
|
|
};
|
|
|
|
const { metadata } = adaptAttackPathQueriesResponse(response);
|
|
expect(metadata?.pagination.count).toBe(1);
|
|
});
|
|
|
|
it("shows every query when not running in Cloud (feature flag off)", () => {
|
|
vi.mocked(isCloud).mockReturnValue(false);
|
|
const response = {
|
|
data: [
|
|
makeQuery("has-data", {
|
|
result_summary: { status: "ok", has_data: true },
|
|
}),
|
|
makeQuery("empty", {
|
|
result_summary: { status: "ok", has_data: false },
|
|
}),
|
|
],
|
|
};
|
|
|
|
const ids = adaptAttackPathQueriesResponse(response).data.map((q) => q.id);
|
|
// self-hosted keeps current behaviour: no filtering, even the empty one
|
|
expect(ids).toEqual(["has-data", "empty"]);
|
|
});
|
|
});
|
|
|
|
describe("buildAttackPathQueries", () => {
|
|
it("prepends a custom query that links to the Prowler documentation", () => {
|
|
// When
|
|
const result = buildAttackPathQueries([presetQuery]);
|
|
|
|
// Then
|
|
expect(result[0]).toMatchObject({
|
|
id: ATTACK_PATH_QUERY_IDS.CUSTOM,
|
|
attributes: {
|
|
name: "Custom openCypher query",
|
|
short_description: "Write and run your own read-only query",
|
|
documentation_link: {
|
|
text: "Learn how to write custom openCypher queries",
|
|
link: DOCS_URLS.ATTACK_PATHS_CUSTOM_QUERIES,
|
|
},
|
|
},
|
|
});
|
|
expect(result[1]).toEqual(presetQuery);
|
|
});
|
|
});
|