Skip to content

Commit

Permalink
[Security Solutions][Endpoint] Running-processes rename and refacto…
Browse files Browse the repository at this point in the history
…r to `processes` (#135569)

* Refactor changing runnin-processes by processes command. Also handle api errors when creating the command request

* Fixes ts types

* Fix multilang key

* Use import type for type imports

* Destructure object

* Update multilang keys

* Updates const name

* Fix const names

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
dasansol92 and kibanamachine authored Jul 5, 2022
1 parent 1b3c4e4 commit f94d5ff
Show file tree
Hide file tree
Showing 14 changed files with 151 additions and 104 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ const BASE_ENDPOINT_ACTION_ROUTE = `${BASE_ENDPOINT_ROUTE}/action`;
/** Action Response Routes */
export const ISOLATE_HOST_ROUTE_V2 = `${BASE_ENDPOINT_ACTION_ROUTE}/isolate`;
export const UNISOLATE_HOST_ROUTE_V2 = `${BASE_ENDPOINT_ACTION_ROUTE}/unisolate`;
export const GET_RUNNING_PROCESSES_ROUTE = `${BASE_ENDPOINT_ACTION_ROUTE}/running_procs`;
export const GET_PROCESSES_ROUTE = `${BASE_ENDPOINT_ACTION_ROUTE}/running_procs`;
export const KILL_PROCESS_ROUTE = `${BASE_ENDPOINT_ACTION_ROUTE}/kill_process`;
export const SUSPEND_PROCESS_ROUTE = `${BASE_ENDPOINT_ACTION_ROUTE}/suspend_process`;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,16 @@ import { merge } from 'lodash';
import * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { ENDPOINT_ACTION_RESPONSES_DS, ENDPOINT_ACTIONS_DS } from '../constants';
import { BaseDataGenerator } from './base_data_generator';
import {
import type {
ActionDetails,
ActivityLogItemTypes,
EndpointActivityLogAction,
EndpointActivityLogActionResponse,
EndpointPendingActions,
LogsEndpointAction,
LogsEndpointActionResponse,
RESPONSE_ACTION_COMMANDS,
RunningProcessesEntry,
ProcessesEntry,
} from '../types';
import { ActivityLogItemTypes, RESPONSE_ACTION_COMMANDS } from '../types';

export class EndpointActionGenerator extends BaseDataGenerator {
/** Generate a random endpoint Action request (isolate or unisolate) */
Expand Down Expand Up @@ -188,12 +187,12 @@ export class EndpointActionGenerator extends BaseDataGenerator {
return super.randomN(max);
}

randomResponseActionRunningProcesses(n?: number): RunningProcessesEntry[] {
randomResponseActionProcesses(n?: number): ProcessesEntry[] {
const numberOfEntries = n ?? this.randomChoice([20, 30, 40, 50]);
const entries = [];
for (let i = 0; i < numberOfEntries; i++) {
entries.push({
command: this.randomResponseActionRunningProcessesCommand(),
command: this.randomResponseActionProcessesCommand(),
pid: this.randomN(1000).toString(),
entity_id: this.randomString(50),
user: this.randomUser(),
Expand All @@ -203,7 +202,7 @@ export class EndpointActionGenerator extends BaseDataGenerator {
return entries;
}

protected randomResponseActionRunningProcessesCommand() {
protected randomResponseActionProcessesCommand() {
const commands = [
'/opt/cmd1',
'/opt/cmd2',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export interface ActionResponseOutput<TOutputContent extends object = object> {
};
}

export interface RunningProcessesEntry {
export interface ProcessesEntry {
command: string;
pid: string;
entity_id: string;
Expand Down Expand Up @@ -221,7 +221,7 @@ export interface HostIsolationResponse {
action: string;
}

export type RunningProcessesRequestBody = TypeOf<typeof NoParametersRequestSchema.body>;
export type ProcessesRequestBody = TypeOf<typeof NoParametersRequestSchema.body>;
export interface ResponseActionApiResponse<TOutput extends object = object> {
action?: string;
data: ActionDetails<TOutput>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { CommandDefinition } from '../console';
import { IsolateActionResult } from './isolate_action';
import { ReleaseActionResult } from './release_action';
import { EndpointStatusActionResult } from './status_action';
import { GetRunningProcessesActionResult } from './get_running_processes_action';
import { GetProcessesActionResult } from './get_processes_action';

export const getEndpointResponseActionsConsoleCommands = (
endpointAgentId: string
Expand Down Expand Up @@ -67,14 +67,11 @@ export const getEndpointResponseActionsConsoleCommands = (
},
},
{
name: 'running-processes',
about: i18n.translate(
'xpack.securitySolution.endpointConsoleCommands.runninProcesses.about',
{
defaultMessage: 'Display the running processes on the endpoint',
}
),
RenderComponent: GetRunningProcessesActionResult,
name: 'processes',
about: i18n.translate('xpack.securitySolution.endpointConsoleCommands.processes.about', {
defaultMessage: 'Display the processes on the endpoint',
}),
RenderComponent: GetProcessesActionResult,
meta: {
endpointId: endpointAgentId,
},
Expand All @@ -83,7 +80,7 @@ export const getEndpointResponseActionsConsoleCommands = (
required: false,
allowMultiples: false,
about: i18n.translate(
'xpack.securitySolution.endpointConsoleCommands.isolate.arg.comment',
'xpack.securitySolution.endpointConsoleCommands.processes.arg.comment',
{ defaultMessage: 'A comment to go along with the action' }
),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { responseActionsHttpMocks } from '../../mocks/response_actions_http_mock
import { enterConsoleCommand } from '../console/mocks';
import { waitFor } from '@testing-library/react';

describe('When using running-processes action from response actions console', () => {
describe('When using processes action from response actions console', () => {
let render: () => Promise<ReturnType<AppContextTestRender['render']>>;
let renderResult: ReturnType<AppContextTestRender['render']>;
let apiMocks: ReturnType<typeof responseActionsHttpMocks>;
Expand Down Expand Up @@ -54,19 +54,19 @@ describe('When using running-processes action from response actions console', ()

it('should call `running-procs` api when command is entered', async () => {
await render();
enterConsoleCommand(renderResult, 'running-processes');
enterConsoleCommand(renderResult, 'processes');

await waitFor(() => {
expect(apiMocks.responseProvider.runningProcesses).toHaveBeenCalledTimes(1);
expect(apiMocks.responseProvider.processes).toHaveBeenCalledTimes(1);
});
});

it('should accept an optional `--comment`', async () => {
await render();
enterConsoleCommand(renderResult, 'running-processes --comment "This is a comment"');
enterConsoleCommand(renderResult, 'processes --comment "This is a comment"');

await waitFor(() => {
expect(apiMocks.responseProvider.runningProcesses).toHaveBeenCalledWith(
expect(apiMocks.responseProvider.processes).toHaveBeenCalledWith(
expect.objectContaining({
body: expect.stringContaining('This is a comment'),
})
Expand All @@ -76,58 +76,74 @@ describe('When using running-processes action from response actions console', ()

it('should only accept one `--comment`', async () => {
await render();
enterConsoleCommand(renderResult, 'running-processes --comment "one" --comment "two"');
enterConsoleCommand(renderResult, 'processes --comment "one" --comment "two"');

expect(renderResult.getByTestId('test-badArgument-message').textContent).toEqual(
'Argument can only be used once: --comment'
);
});

it('should call the action status api after creating the `running-processes` request', async () => {
it('should call the action status api after creating the `processes` request', async () => {
await render();
enterConsoleCommand(renderResult, 'running-processes');
enterConsoleCommand(renderResult, 'processes');

await waitFor(() => {
expect(apiMocks.responseProvider.actionDetails).toHaveBeenCalled();
});
});

it('should show success when `running-processes` action completes with no errors', async () => {
it('should show success when `processes` action completes with no errors', async () => {
await render();
enterConsoleCommand(renderResult, 'running-processes');
enterConsoleCommand(renderResult, 'processes');

await waitFor(() => {
expect(renderResult.getByTestId('getRunningProcessesSuccessCallout')).toBeTruthy();
expect(renderResult.getByTestId('getProcessesSuccessCallout')).toBeTruthy();
});
});

it('should show error if get running-processes failed to complete successfully', async () => {
it('should show error if get processes failed to complete successfully', async () => {
const pendingDetailResponse = apiMocks.responseProvider.actionDetails({
path: '/api/endpoint/action/1.2.3',
});
pendingDetailResponse.data.wasSuccessful = false;
pendingDetailResponse.data.errors = ['error one', 'error two'];
apiMocks.responseProvider.actionDetails.mockReturnValue(pendingDetailResponse);
await render();
enterConsoleCommand(renderResult, 'running-processes');
enterConsoleCommand(renderResult, 'processes');

await waitFor(() => {
expect(renderResult.getByTestId('getRunningProcessesErrorCallout').textContent).toMatch(
expect(renderResult.getByTestId('getProcessesErrorCallout').textContent).toMatch(
/error one \| error two/
);
});
});

it('should show error if get processes request failed', async () => {
// FIXME: have to identify this type error
apiMocks.responseProvider.processes.mockRejectedValueOnce({
status: 500,
message: 'this is an error',
} as never);
await render();
enterConsoleCommand(renderResult, 'processes');

await waitFor(() => {
expect(renderResult.getByTestId('performGetProcessesErrorCallout').textContent).toMatch(
/this is an error/
);
});
});

describe('and when console is closed (not terminated) and then reopened', () => {
beforeEach(() => {
const _render = render;

render = async () => {
const response = await _render();
enterConsoleCommand(response, 'running-processes');
enterConsoleCommand(response, 'processes');

await waitFor(() => {
expect(apiMocks.responseProvider.runningProcesses).toHaveBeenCalledTimes(1);
expect(apiMocks.responseProvider.processes).toHaveBeenCalledTimes(1);
});

// Hide the console
Expand All @@ -137,11 +153,11 @@ describe('When using running-processes action from response actions console', ()
};
});

it('should NOT send the `running-processes` request again', async () => {
it('should NOT send the `processes` request again', async () => {
await render();
await consoleManagerMockAccess.openRunningConsole();

expect(apiMocks.responseProvider.runningProcesses).toHaveBeenCalledTimes(1);
expect(apiMocks.responseProvider.processes).toHaveBeenCalledTimes(1);
});

it('should continue to check action status when still pending', async () => {
Expand Down
Loading

0 comments on commit f94d5ff

Please sign in to comment.