Skip to content

Commit

Permalink
[Security Solution][Endpoint] Fix Response Console status command f…
Browse files Browse the repository at this point in the history
…or SentinelOne and error output for commands that hidden from `help` (elastic#180529)

## Summary

Fixes:

- Disable the `status` command for SentinelOne hosts (not supported)
- For console commands that are hidden from Help, if a user attempts to
still enter them in the console, the usage information should NOT be
displayed following the error message.
  • Loading branch information
paul-tavares authored Apr 11, 2024
1 parent 2b2d00d commit a78c522
Show file tree
Hide file tree
Showing 7 changed files with 166 additions and 36 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* 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 { CommandDefinition, ConsoleProps } from '..';
import type { AppContextTestRender } from '../../../../common/mock/endpoint';
import type { ConsoleTestSetup } from '../mocks';
import { getConsoleTestSetup } from '../mocks';

describe('BadArgument component', () => {
let render: (props?: Partial<ConsoleProps>) => ReturnType<AppContextTestRender['render']>;
let renderResult: ReturnType<typeof render>;
let command: CommandDefinition;
let enterCommand: ConsoleTestSetup['enterCommand'];

beforeEach(() => {
const testSetup = getConsoleTestSetup();
let commands: CommandDefinition[];

({ commands, enterCommand } = testSetup);
command = commands[0];
command.args = {
foo: {
about: 'foo',
required: true,
mustHaveValue: 'number-greater-than-zero',
allowMultiples: false,
},
};

render = (props = {}) => (renderResult = testSetup.renderConsole(props));
});

it('should display message and help output if command is not hidden from help', () => {
render();
enterCommand('cmd1 --foo');

expect(renderResult.getByTestId('test-badArgument-message').textContent).toEqual(
'Argument --foo must have a value'
);
expect(renderResult.getByTestId('test-badArgument-commandUsage'));
});

it('should only display message (no help) if command is hidden from help', () => {
command.helpHidden = true;
render();
enterCommand('cmd1 --foo');

expect(renderResult.getByTestId('test-badArgument-message').textContent).toEqual(
'Argument --foo must have a value'
);
expect(renderResult.queryByTestId('test-badArgument-commandUsage')).toBeNull();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -41,23 +41,28 @@ export const BadArgument = memo<CommandExecutionComponentProps<{}, { errorMessag
data-test-subj={getTestId('badArgument')}
>
<div data-test-subj={getTestId('badArgument-message')}>{store.errorMessage}</div>
<EuiSpacer size="s" />
<CommandInputUsage commandDef={command.commandDefinition} />
<ConsoleCodeBlock>
<EuiSpacer size="m" />
<FormattedMessage
id="xpack.securitySolution.console.badArgument.helpMessage"
defaultMessage="Enter {helpCmd} for further assistance."
values={{
helpCmd: (
<ConsoleCodeBlock
bold
inline
>{`${command.commandDefinition.name} --help`}</ConsoleCodeBlock>
),
}}
/>
</ConsoleCodeBlock>

{!command.commandDefinition.helpHidden && (
<div data-test-subj={getTestId('badArgument-commandUsage')}>
<EuiSpacer size="s" />
<CommandInputUsage commandDef={command.commandDefinition} />
<ConsoleCodeBlock>
<EuiSpacer size="m" />
<FormattedMessage
id="xpack.securitySolution.console.badArgument.helpMessage"
defaultMessage="Enter {helpCmd} for further assistance."
values={{
helpCmd: (
<ConsoleCodeBlock
bold
inline
>{`${command.commandDefinition.name} --help`}</ConsoleCodeBlock>
),
}}
/>
</ConsoleCodeBlock>
</div>
)}
</UnsupportedMessageCallout>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,9 @@ export const handleExecuteCommand: ConsoleStoreReducer<

case 'number':
case 'number-greater-than-zero':
{
if (typeof argValue === 'boolean') {
dataValidationError = executionTranslations.mustHaveValue(argName);
} else {
const valueNumber = Number(argValue);

if (!Number.isSafeInteger(valueNumber)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* 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 { CommandDefinition, ConsoleProps } from '..';
import type { AppContextTestRender } from '../../../../common/mock/endpoint';
import type { ConsoleTestSetup } from '../mocks';
import { getConsoleTestSetup } from '../mocks';

describe('ValidationError component', () => {
let render: (props?: Partial<ConsoleProps>) => ReturnType<AppContextTestRender['render']>;
let renderResult: ReturnType<typeof render>;
let command: CommandDefinition;
let enterCommand: ConsoleTestSetup['enterCommand'];

beforeEach(() => {
const testSetup = getConsoleTestSetup();
let commands: CommandDefinition[];

({ commands, enterCommand } = testSetup);
command = commands[0];
command.validate = () => 'this command is not active';

render = (props = {}) => (renderResult = testSetup.renderConsole(props));
});

it('should display message and help output if command is not hidden from help', () => {
render();
enterCommand('cmd1');

expect(renderResult.getByTestId('test-validationError-message').textContent).toEqual(
'this command is not active'
);
expect(renderResult.getByTestId('test-validationError-commandUsage'));
});

it('should only display message (no help) if command is hidden from help', () => {
command.helpHidden = true;
render();
enterCommand('cmd1');

expect(renderResult.getByTestId('test-validationError-message').textContent).toEqual(
'this command is not active'
);
expect(renderResult.queryByTestId('test-validationError-commandUsage')).toBeNull();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -42,23 +42,28 @@ export const ValidationError = memo<
data-test-subj={getTestId('validationError')}
>
<div data-test-subj={getTestId('validationError-message')}>{store.errorMessage}</div>
<EuiSpacer size="s" />
<CommandInputUsage commandDef={command.commandDefinition} />
<ConsoleCodeBlock>
<EuiSpacer size="m" />
<FormattedMessage
id="xpack.securitySolution.console.validationError.helpMessage"
defaultMessage="Enter {helpCmd} for further assistance."
values={{
helpCmd: (
<ConsoleCodeBlock
bold
inline
>{`${command.commandDefinition.name} --help`}</ConsoleCodeBlock>
),
}}
/>
</ConsoleCodeBlock>

{!command.commandDefinition.helpHidden && (
<div data-test-subj={getTestId('validationError-commandUsage')}>
<EuiSpacer size="s" />
<CommandInputUsage commandDef={command.commandDefinition} />
<ConsoleCodeBlock>
<EuiSpacer size="m" />
<FormattedMessage
id="xpack.securitySolution.console.validationError.helpMessage"
defaultMessage="Enter {helpCmd} for further assistance."
values={{
helpCmd: (
<ConsoleCodeBlock
bold
inline
>{`${command.commandDefinition.name} --help`}</ConsoleCodeBlock>
),
}}
/>
</ConsoleCodeBlock>
</div>
)}
</UnsupportedMessageCallout>
);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@

import React, { useCallback } from 'react';
import { EuiBetaBadge, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import { TECHNICAL_PREVIEW, TECHNICAL_PREVIEW_TOOLTIP } from '../../common/translations';
import {
TECHNICAL_PREVIEW,
TECHNICAL_PREVIEW_TOOLTIP,
UPGRADE_AGENT_FOR_RESPONDER,
} from '../../common/translations';
import { useLicense } from '../../common/hooks/use_license';
import type { ImmutableArray } from '../../../common/endpoint/types';
import {
Expand Down Expand Up @@ -99,6 +103,12 @@ export const useWithShowResponder = (): ShowResponseActionsConsole => {
return {
...command,
helpHidden: true,
validate: () => {
return UPGRADE_AGENT_FOR_RESPONDER(
agentType,
command.name as ConsoleResponseActionCommands
);
},
};
}
return command;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ const runCli: RunFn = async ({ log, flags }) => {
]);

// Trigger an alert on the SentinelOn host so that we get an alert back in Kibana
log.info(`Triggering SentinelOne alert`);
await s1HostVm.exec('nslookup elastic.co');

log.info(`Done!
Expand Down

0 comments on commit a78c522

Please sign in to comment.