8000 Fixes Incompatability with newer Elasticsearch Systems by J12934 · Pull Request #3411 · secureCodeBox/secureCodeBox · GitHub
[go: up one dir, main page]

Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion hooks/persistence-elastic/hook/hook.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,10 @@ export async function handle({
},
]);

const { body: bulkResponse } = await client.bulk({ refresh: true, body });
const response = await client.bulk({ refresh: true, body });

// Support both ES 7.x (response.body) and ES 8.x (response directly)
const bulkResponse = response.body || response;

if (bulkResponse.errors) {
console.error("Bulk Request had errors:");
Expand Down
222 changes: 222 additions & 0 deletions hooks/persistence-elastic/hook/hook.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,3 +218,225 @@ test("should append week format like yyyy/'W'W -> 2020/W46", async () => {
index: `scb_2020/W46`,
});
});

test("should handle Elasticsearch 8.x response format (without body wrapper)", async () => {
const findings = [
{
id: "4560b3e6-1219-4f5f-9b44-6579f5a32407",
name: "Port 5601 is open",
category: "Open Port",
},
];

const getFindings = async () => findings;

// ES 8.x returns response directly without .body wrapper
const es8Client = {
indices: {
create: jest.fn(),
},
index: jest.fn(),
bulk: jest.fn(() => ({ errors: false, items: [] })), // ES 8.x format
};

await handle({
getFindings,
scan,
now: testDate,
tenant: "default",
appendNamespace: true,
client: es8Client,
});

expect(es8Client.bulk).toHaveBeenCalledTimes(1);
expect(es8Client.bulk).toHaveBeenCalledWith({
refresh: true,
body: [
{
index: {
_index: `scb_default_2020-11-11`,
},
},
{
"@timestamp": testDate,
category: "Open Port",
id: "4560b3e6-1219-4f5f-9b44-6579f5a32407",
name: "Port 5601 is open",
scan_id: "09988cdf-1fc7-4f85-95ee-1b1d65dbc7cc",
scan_labels: {
company: "iteratec",
},
scan_name: "demo-scan",
scan_type: "Nmap",
type: "finding",
},
],
});
});

test("should handle Elasticsearch 7.x response format (with body wrapper)", async () => {
const findings = [
{
id: "test-finding-id",
name: "Test Finding",
category: "Test Category",
},
];

const getFindings = async () => findings;

// ES 7.x returns response with .body wrapper
const es7Client = {
indices: {
create: jest.fn(),
},
index: jest.fn(),
bulk: jest.fn(() => ({ body: { errors: false, items: [] } })), // ES 7.x format
};

await handle({
getFindings,
scan,
now: testDate,
tenant: "default",
appendNamespace: true,
client: es7Client,
});

expect(es7Client.bulk).toHaveBeenCalledTimes(1);
expect(es7Client.bulk).toHaveBeenCalledWith({
refresh: true,
body: [
{
index: {
_index: `scb_default_2020-11-11`,
},
},
{
"@timestamp": testDate,
category: "Test Category",
id: "test-finding-id",
name: "Test Finding",
scan_id: "09988cdf-1fc7-4f85-95ee-1b1d65dbc7cc",
scan_labels: {
company: "iteratec",
},
scan_name: "demo-scan",
scan_type: "Nmap",
type: "finding",
},
],
});
});

test("should handle bulk errors in Elasticsearch 8.x format", async () => {
const findings = [
{
id: "error-finding",
name: "Error Finding",
category: "Error Category",
},
];

const getFindings = async () => findings;

const consoleErrorSpy = jest.spyOn(console, "error").mockImplementation();
const consoleLogSpy = jest.spyOn(console, "log").mockImplementation();

// ES 8.x with errors
const es8ClientWithErrors = {
indices: {
create: jest.fn(),
},
index: jest.fn(),
bulk: jest.fn(() => ({
errors: true,
items: [
{
index: {
error: {
type: "mapper_parsing_exception",
reason: "failed to parse field",
},
},
},
],
})),
};

await handle({
getFindings,
scan,
now: testDate,
tenant: "default",
client: es8ClientWithErrors,
});

expect(consoleErrorSpy).toHaveBeenCalledWith("Bulk Request had errors:");
expect(consoleLogSpy).toHaveBeenCalledWith(
expect.objectContaining({
errors: true,
items: expect.any(Array),
}),
);

consoleErrorSpy.mockRestore();
consoleLogSpy.mockRestore();
});

test("should handle bulk errors in Elasticsearch 7.x format", async () => {
const findings = [
{
id: "error-finding",
name: "Error Finding",
category: "Error Category",
},
];

const getFindings = async () => findings;

const consoleErrorSpy = jest.spyOn(console, "error").mockImplementation();
const consoleLogSpy = jest.spyOn(console, "log").mockImplementation();

// ES 7.x with errors
const es7ClientWithErrors = {
indices: {
create: jest.fn(),
},
index: jest.fn(),
bulk: jest.fn(() => ({
body: {
errors: true,
items: [
{
index: {
error: {
type: "mapper_parsing_exception",
reason: "failed to parse field",
},
},
},
],
},
})),
};

await handle({
getFindings,
scan,
now: testDate,
tenant: "default",
client: es7ClientWithErrors,
});

expect(consoleErrorSpy).toHaveBeenCalledWith("Bulk Request had errors:");
expect(consoleLogSpy).toHaveBeenCalledWith(
expect.objectContaining({
errors: true,
items: expect.any(Array),
}),
);

consoleErrorSpy.mockRestore();
consoleLogSpy.mockRestore();
});
Loading
0