[Security Solution][Endpoint][Response Actions] Add automated tests for execute response action test cases (#155128)

This commit is contained in:
Ashokaditya 2023-04-20 17:56:31 +02:00 committed by GitHub
parent 92ce25d7c8
commit 241f71b346
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 227 additions and 48 deletions

View file

@ -7,6 +7,7 @@
import { v4 as uuidv4 } from 'uuid';
import { RESPONSE_ACTION_API_COMMANDS_NAMES } from '../service/response_actions/constants';
import {
EndpointActionListRequestSchema,
NoParametersRequestSchema,
@ -185,7 +186,7 @@ describe('actions schemas', () => {
}).not.toThrow();
});
it.each(['isolate', 'unisolate', 'kill-process', 'suspend-process', 'running-processes'])(
it.each(RESPONSE_ACTION_API_COMMANDS_NAMES)(
'should work with commands query params with %s action',
(command) => {
expect(() => {

View file

@ -0,0 +1,148 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { AppContextTestRender } from '../../../../../common/mock/endpoint';
import { createAppRootMockRenderer } from '../../../../../common/mock/endpoint';
import {
ConsoleManagerTestComponent,
getConsoleManagerMockRenderResultQueriesAndActions,
} from '../../../console/components/console_manager/mocks';
import React from 'react';
import { getEndpointConsoleCommands } from '../../lib/console_commands_definition';
import { enterConsoleCommand } from '../../../console/mocks';
import { getEndpointAuthzInitialState } from '../../../../../../common/endpoint/service/authz';
import type { EndpointCapabilities } from '../../../../../../common/endpoint/service/response_actions/constants';
import { ENDPOINT_CAPABILITIES } from '../../../../../../common/endpoint/service/response_actions/constants';
import { useGetEndpointPendingActionsSummary } from '../../../../hooks/response_actions/use_get_endpoint_pending_actions_summary';
import { useGetEndpointDetails } from '../../../../hooks';
import { EndpointActionGenerator } from '../../../../../../common/endpoint/data_generators/endpoint_action_generator';
import { EndpointMetadataGenerator } from '../../../../../../common/endpoint/data_generators/endpoint_metadata_generator';
jest.mock('../../../../hooks/response_actions/use_get_endpoint_pending_actions_summary');
jest.mock('../../../../hooks');
const useGetEndpointPendingActionsSummaryMock = useGetEndpointPendingActionsSummary as jest.Mock;
const useGetEndpointDetailsMock = useGetEndpointDetails as jest.Mock;
describe('When using processes action from response actions console', () => {
let render: (
capabilities?: EndpointCapabilities[]
) => Promise<ReturnType<AppContextTestRender['render']>>;
let renderResult: ReturnType<AppContextTestRender['render']>;
let consoleManagerMockAccess: ReturnType<
typeof getConsoleManagerMockRenderResultQueriesAndActions
>;
const agentId = 'a.b.c';
const pendingActionsMock = () => {
useGetEndpointPendingActionsSummaryMock.mockReturnValue({
data: {
data: [
new EndpointActionGenerator('seed').generateAgentPendingActionsSummary({
agent_id: agentId,
pending_actions: {
isolate: 0,
},
}),
],
},
});
};
const endpointDetailsMock = () => {
const endpointMetadata = new EndpointMetadataGenerator('seed').generateHostInfo({
metadata: {
'@timestamp': new Date('2023-04-20T09:37:40.309Z').getTime(),
agent: {
id: agentId,
version: '8.8.0',
},
elastic: {
agent: { id: agentId },
},
Endpoint: {
state: {
isolation: false,
},
},
},
});
useGetEndpointDetailsMock.mockReturnValue({
data: endpointMetadata,
isFetching: false,
isFetched: true,
});
};
beforeEach(() => {
const mockedContext = createAppRootMockRenderer();
render = async (capabilities: EndpointCapabilities[] = [...ENDPOINT_CAPABILITIES]) => {
renderResult = mockedContext.render(
<ConsoleManagerTestComponent
registerConsoleProps={() => {
return {
consoleProps: {
'data-test-subj': 'test',
commands: getEndpointConsoleCommands({
endpointAgentId: 'a.b.c',
endpointCapabilities: [...capabilities],
endpointPrivileges: {
...getEndpointAuthzInitialState(),
loading: false,
},
}),
},
};
}}
/>
);
consoleManagerMockAccess = getConsoleManagerMockRenderResultQueriesAndActions(renderResult);
await consoleManagerMockAccess.clickOnRegisterNewConsole();
await consoleManagerMockAccess.openRunningConsole();
return renderResult;
};
});
afterEach(() => {
jest.clearAllMocks();
});
it('should show expected status output', async () => {
pendingActionsMock();
endpointDetailsMock();
await render();
enterConsoleCommand(renderResult, 'status');
const statusResults = renderResult.getByTestId('agent-status-console-output');
expect(
Array.from(statusResults.querySelectorAll('dt')).map((term) => term.textContent)
).toEqual([
'Agent status',
'Platform',
'Version',
'Policy status',
'Policy version',
'Policy name',
'Last active',
]);
expect(
Array.from(statusResults.querySelectorAll('dd')).map((detail) => detail.textContent)
).toEqual([
'Healthy',
'Windows Server 2012R2',
'8.8.0',
'Success',
'v3',
'With Eventing',
'Apr 20, 2023 @ 09:37:40.309',
]);
});
});

View file

@ -796,6 +796,10 @@ describe('Response actions history', () => {
});
describe('Action status ', () => {
beforeEach(() => {
apiMocks = responseActionsHttpMocks(mockedContext.coreStart.http);
});
const expandRows = () => {
const { getAllByTestId } = renderResult;
@ -805,58 +809,84 @@ describe('Response actions history', () => {
return outputs;
};
it('shows completed status badge for successfully completed actions', async () => {
useGetEndpointActionListMock.mockReturnValue({
...getBaseMockedActionList(),
data: await getActionListMock({ actionCount: 2 }),
});
render();
it.each(RESPONSE_ACTION_API_COMMANDS_NAMES)(
'shows completed status badge for successfully completed %s actions',
async (command) => {
useGetEndpointActionListMock.mockReturnValue({
...getBaseMockedActionList(),
data: await getActionListMock({ actionCount: 2, commands: [command] }),
});
if (command === 'get-file' || command === 'execute') {
mockUseGetFileInfo = {
isFetching: false,
error: null,
data: apiMocks.responseProvider.fileInfo(),
};
}
const outputs = expandRows();
expect(outputs.map((n) => n.textContent)).toEqual([
'isolate completed successfully',
'isolate completed successfully',
]);
expect(
renderResult.getAllByTestId(`${testPrefix}-column-status`).map((n) => n.textContent)
).toEqual(['Successful', 'Successful']);
});
render();
it('shows Failed status badge for failed actions', async () => {
useGetEndpointActionListMock.mockReturnValue({
...getBaseMockedActionList(),
data: await getActionListMock({ actionCount: 2, wasSuccessful: false, status: 'failed' }),
});
render();
const outputs = expandRows();
expect(outputs.map((n) => n.textContent)).toEqual([
expect.stringContaining(`${command} completed successfully`),
expect.stringContaining(`${command} completed successfully`),
]);
expect(
renderResult.getAllByTestId(`${testPrefix}-column-status`).map((n) => n.textContent)
).toEqual(['Successful', 'Successful']);
}
);
const outputs = expandRows();
expect(outputs.map((n) => n.textContent)).toEqual(['isolate failed', 'isolate failed']);
expect(
renderResult.getAllByTestId(`${testPrefix}-column-status`).map((n) => n.textContent)
).toEqual(['Failed', 'Failed']);
});
it.each(RESPONSE_ACTION_API_COMMANDS_NAMES)(
'shows Failed status badge for failed %s actions',
async (command) => {
useGetEndpointActionListMock.mockReturnValue({
...getBaseMockedActionList(),
data: await getActionListMock({
actionCount: 2,
commands: [command],
wasSuccessful: false,
status: 'failed',
}),
});
render();
it('shows Failed status badge for expired actions', async () => {
useGetEndpointActionListMock.mockReturnValue({
...getBaseMockedActionList(),
data: await getActionListMock({
actionCount: 2,
isCompleted: false,
isExpired: true,
status: 'failed',
}),
});
render();
const outputs = expandRows();
expect(outputs.map((n) => n.textContent)).toEqual([
`${command} failed`,
`${command} failed`,
]);
expect(
renderResult.getAllByTestId(`${testPrefix}-column-status`).map((n) => n.textContent)
).toEqual(['Failed', 'Failed']);
}
);
const outputs = expandRows();
expect(outputs.map((n) => n.textContent)).toEqual([
'isolate failed: action expired',
'isolate failed: action expired',
]);
expect(
renderResult.getAllByTestId(`${testPrefix}-column-status`).map((n) => n.textContent)
).toEqual(['Failed', 'Failed']);
});
it.each(RESPONSE_ACTION_API_COMMANDS_NAMES)(
'shows Failed status badge for expired %s actions',
async (command) => {
useGetEndpointActionListMock.mockReturnValue({
...getBaseMockedActionList(),
data: await getActionListMock({
actionCount: 2,
commands: [command],
isCompleted: false,
isExpired: true,
status: 'failed',
}),
});
render();
const outputs = expandRows();
expect(outputs.map((n) => n.textContent)).toEqual([
`${command} failed: action expired`,
`${command} failed: action expired`,
]);
expect(
renderResult.getAllByTestId(`${testPrefix}-column-status`).map((n) => n.textContent)
).toEqual(['Failed', 'Failed']);
}
);
it('shows Pending status badge for pending actions', async () => {
useGetEndpointActionListMock.mockReturnValue({