[SecuritySolution][Endpoint][Response Actions] Remove scan feature flag and branch logic. (#190601)

This commit is contained in:
Ash 2024-08-28 11:54:36 +02:00 committed by GitHub
parent dda6cd9d9e
commit 74ba0b4f54
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 102 additions and 207 deletions

View file

@ -673,11 +673,13 @@ export const getSecuritySubFeaturesMap = ({
[SecuritySubFeatureId.processOperations, processOperationsSubFeature],
[SecuritySubFeatureId.fileOperations, fileOperationsSubFeature],
[SecuritySubFeatureId.executeAction, executeActionSubFeature],
[SecuritySubFeatureId.scanAction, scanActionSubFeature],
];
if (experimentalFeatures.responseActionScanEnabled) {
securitySubFeaturesList.push([SecuritySubFeatureId.scanAction, scanActionSubFeature]);
}
// Use the following code to add feature based on feature flag
// if (experimentalFeatures.featureFlagName) {
// securitySubFeaturesList.push([SecuritySubFeatureId.featureId, featureSubFeature]);
// }
const securitySubFeaturesMap = new Map<SecuritySubFeatureId, SubFeatureConfig>(
securitySubFeaturesList

View file

@ -83,11 +83,6 @@ export const allowedExperimentalValues = Object.freeze({
*/
responseActionsCrowdstrikeManualHostIsolationEnabled: true,
/**
* Enables scan response action on Endpoint
*/
responseActionScanEnabled: true,
/**
* Enables new notes
*/

View file

@ -58,7 +58,6 @@ describe('When using scan action from response actions console', () => {
beforeEach(() => {
mockedContext = createAppRootMockRenderer();
mockedContext.setExperimentalFlag({ responseActionScanEnabled: true });
apiMocks = responseActionsHttpMocks(mockedContext.coreStart.http);
endpointPrivileges = {
...getEndpointAuthzInitialStateMock(),

View file

@ -164,7 +164,6 @@ export const getEndpointConsoleCommands = ({
const featureFlags = ExperimentalFeaturesService.get();
const isUploadEnabled = featureFlags.responseActionUploadEnabled;
const isScanEnabled = featureFlags.responseActionScanEnabled;
const doesEndpointSupportCommand = (commandName: ConsoleResponseActionCommands) => {
// Agent capabilities is only validated for Endpoint agent types
@ -486,43 +485,41 @@ export const getEndpointConsoleCommands = ({
});
}
if (isScanEnabled) {
consoleCommands.push({
name: 'scan',
about: getCommandAboutInfo({
aboutInfo: CONSOLE_COMMANDS.scan.about,
isSupported: doesEndpointSupportCommand('scan'),
}),
RenderComponent: ScanActionResult,
meta: {
agentType,
endpointId: endpointAgentId,
capabilities: endpointCapabilities,
privileges: endpointPrivileges,
consoleCommands.push({
name: 'scan',
about: getCommandAboutInfo({
aboutInfo: CONSOLE_COMMANDS.scan.about,
isSupported: doesEndpointSupportCommand('scan'),
}),
RenderComponent: ScanActionResult,
meta: {
agentType,
endpointId: endpointAgentId,
capabilities: endpointCapabilities,
privileges: endpointPrivileges,
},
exampleUsage: 'scan --path "/full/path/to/folder" --comment "Scan folder for malware"',
exampleInstruction: ENTER_OR_ADD_COMMENT_ARG_INSTRUCTION,
validate: capabilitiesAndPrivilegesValidator(agentType),
mustHaveArgs: true,
args: {
path: {
required: true,
allowMultiples: false,
mustHaveValue: 'non-empty-string',
about: CONSOLE_COMMANDS.scan.args.path.about,
},
exampleUsage: 'scan --path "/full/path/to/folder" --comment "Scan folder for malware"',
exampleInstruction: ENTER_OR_ADD_COMMENT_ARG_INSTRUCTION,
validate: capabilitiesAndPrivilegesValidator(agentType),
mustHaveArgs: true,
args: {
path: {
required: true,
allowMultiples: false,
mustHaveValue: 'non-empty-string',
about: CONSOLE_COMMANDS.scan.args.path.about,
},
...commandCommentArgument(),
},
helpGroupLabel: HELP_GROUPS.responseActions.label,
helpGroupPosition: HELP_GROUPS.responseActions.position,
helpCommandPosition: 8,
helpDisabled: !doesEndpointSupportCommand('scan'),
helpHidden: !getRbacControl({
commandName: 'scan',
privileges: endpointPrivileges,
}),
});
}
...commandCommentArgument(),
},
helpGroupLabel: HELP_GROUPS.responseActions.label,
helpGroupPosition: HELP_GROUPS.responseActions.position,
helpCommandPosition: 8,
helpDisabled: !doesEndpointSupportCommand('scan'),
helpHidden: !getRbacControl({
commandName: 'scan',
privileges: endpointPrivileges,
}),
});
switch (agentType) {
case 'sentinel_one':

View file

@ -46,7 +46,6 @@ describe('When displaying Endpoint Response Actions', () => {
beforeEach(() => {
(ExperimentalFeaturesService.get as jest.Mock).mockReturnValue({
responseActionUploadEnabled: true,
responseActionScanEnabled: true,
});
commands = getEndpointConsoleCommands({
agentType: 'endpoint',

View file

@ -334,11 +334,6 @@ export const useActionsLogFilter = ({
return false;
}
// `scan` - v8.15
if (commandName === 'scan' && !featureFlags.responseActionScanEnabled) {
return false;
}
return true;
}).map((commandName) => ({
key: commandName,

View file

@ -1491,7 +1491,6 @@ describe('Response actions history', () => {
beforeEach(() => {
featureFlags = {
responseActionUploadEnabled: true,
responseActionScanEnabled: false,
};
mockedContext.setExperimentalFlag(featureFlags);
@ -1511,37 +1510,7 @@ describe('Response actions history', () => {
);
});
it('should show a list of actions (without `scan`) when opened', () => {
mockedContext.setExperimentalFlag({
...featureFlags,
responseActionScanEnabled: false,
});
render();
const { getByTestId, getAllByTestId } = renderResult;
userEvent.click(getByTestId(`${testPrefix}-${filterPrefix}-popoverButton`));
const filterList = getByTestId(`${testPrefix}-${filterPrefix}-popoverList`);
expect(filterList).toBeTruthy();
expect(getAllByTestId(`${filterPrefix}-option`).length).toEqual(
RESPONSE_ACTION_API_COMMANDS_NAMES.length - 1
);
expect(getAllByTestId(`${filterPrefix}-option`).map((option) => option.textContent)).toEqual([
'isolate. To check this option, press Enter.',
'release. To check this option, press Enter.',
'kill-process. To check this option, press Enter.',
'suspend-process. To check this option, press Enter.',
'processes. To check this option, press Enter.',
'get-file. To check this option, press Enter.',
'execute. To check this option, press Enter.',
'upload. To check this option, press Enter.',
]);
});
it('should show a list of actions (with `scan`) when opened', () => {
mockedContext.setExperimentalFlag({
...featureFlags,
responseActionScanEnabled: true,
});
render();
const { getByTestId, getAllByTestId } = renderResult;

View file

@ -25,11 +25,13 @@ describe(
{
env: {
ftrConfig: {
kbnServerArgs: [
`--xpack.securitySolution.enableExperimental=${JSON.stringify([
'responseActionScanEnabled',
])}`,
],
// This is not needed for this test, but it's a good example of
// how to enable experimental features in the Cypress tests.
// kbnServerArgs: [
// `--xpack.securitySolution.enableExperimental=${JSON.stringify([
// 'featureFlagName',
// ])}`,
// ],
},
},
tags: ['@ess', '@serverless', '@skipInServerlessMKI'],

View file

@ -18,11 +18,13 @@ describe(
env: {
ftrConfig: {
productTypes: [{ product_line: 'security', product_tier: 'complete' }],
kbnServerArgs: [
`--xpack.securitySolution.enableExperimental=${JSON.stringify([
'responseActionScanEnabled',
])}`,
],
// This is not needed for this test, but it's a good example of
// how to enable experimental features in the Cypress tests.
// kbnServerArgs: [
// `--xpack.securitySolution.enableExperimental=${JSON.stringify([
// 'featureFlagName',
// ])}`,
// ],
},
},
},

View file

@ -24,11 +24,13 @@ describe(
{ product_line: 'security', product_tier: 'complete' },
{ product_line: 'endpoint', product_tier: 'complete' },
],
kbnServerArgs: [
`--xpack.securitySolution.enableExperimental=${JSON.stringify([
'responseActionScanEnabled',
])}`,
],
// This is not needed for this test, but it's a good example of
// how to enable experimental features in the Cypress tests.
// kbnServerArgs: [
// `--xpack.securitySolution.enableExperimental=${JSON.stringify([
// 'featureFlagName',
// ])}`,
// ],
},
},
},

View file

@ -18,11 +18,13 @@ describe(
env: {
ftrConfig: {
productTypes: [{ product_line: 'security', product_tier: 'essentials' }],
kbnServerArgs: [
`--xpack.securitySolution.enableExperimental=${JSON.stringify([
'responseActionScanEnabled',
])}`,
],
// This is not needed for this test, but it's a good example of
// how to enable experimental features in the Cypress tests.
// kbnServerArgs: [
// `--xpack.securitySolution.enableExperimental=${JSON.stringify([
// 'featureFlagName',
// ])}`,
// ],
},
},
},

View file

@ -24,11 +24,13 @@ describe(
{ product_line: 'security', product_tier: 'essentials' },
{ product_line: 'endpoint', product_tier: 'essentials' },
],
kbnServerArgs: [
`--xpack.securitySolution.enableExperimental=${JSON.stringify([
'responseActionScanEnabled',
])}`,
],
// This is not needed for this test, but it's a good example of
// how to enable experimental features in the Cypress tests.
// kbnServerArgs: [
// `--xpack.securitySolution.enableExperimental=${JSON.stringify([
// 'featureFlagName',
// ])}`,
// ],
},
},
},

View file

@ -40,11 +40,13 @@ describe(
{ product_line: 'security', product_tier: 'complete' },
{ product_line: 'endpoint', product_tier: 'complete' },
],
kbnServerArgs: [
`--xpack.securitySolution.enableExperimental=${JSON.stringify([
'responseActionScanEnabled',
])}`,
],
// This is not needed for this test, but it's a good example of
// how to enable experimental features in the Cypress tests.
// kbnServerArgs: [
// `--xpack.securitySolution.enableExperimental=${JSON.stringify([
// 'featureFlagName',
// ])}`,
// ],
},
},
},

View file

@ -461,33 +461,7 @@ describe('Response actions history page', () => {
expect(history.location.search).toEqual('?page=1&pageSize=20');
});
// TODO: remove this test when responseActionScanEnabled is removed
it('should set selected command filter options to URL params (without `responseActionScanEnabled`)', () => {
mockedContext.setExperimentalFlag({
responseActionScanEnabled: false,
});
const filterPrefix = 'actions-filter';
render();
const { getAllByTestId, getByTestId } = renderResult;
userEvent.click(getByTestId(`${testPrefix}-${filterPrefix}-popoverButton`));
const allFilterOptions = getAllByTestId(`${filterPrefix}-option`);
allFilterOptions.forEach((option) => {
option.style.pointerEvents = 'all';
userEvent.click(option);
});
expect(history.location.search).toEqual(
'?commands=isolate%2Crelease%2Ckill-process%2Csuspend-process%2Cprocesses%2Cget-file%2Cexecute%2Cupload'
);
});
it('should set selected command filter options to URL params (with `responseActionScanEnabled`)', () => {
mockedContext.setExperimentalFlag({
responseActionScanEnabled: true,
});
it('should set selected command filter options to URL params', () => {
const filterPrefix = 'actions-filter';
render();
const { getAllByTestId, getByTestId } = renderResult;
@ -631,38 +605,7 @@ describe('Response actions history page', () => {
});
describe('Clear all selected options on a filter', () => {
// TODO: remove this test when responseActionScanEnabled is removed
it('should clear all selected options on `actions` filter (without `responseActionScanEnabled`)', () => {
mockedContext.setExperimentalFlag({
responseActionScanEnabled: false,
});
const filterPrefix = 'actions-filter';
render();
const { getAllByTestId, getByTestId } = renderResult;
userEvent.click(getByTestId(`${testPrefix}-${filterPrefix}-popoverButton`));
const allFilterOptions = getAllByTestId(`${filterPrefix}-option`);
allFilterOptions.forEach((option) => {
option.style.pointerEvents = 'all';
userEvent.click(option);
});
expect(history.location.search).toEqual(
'?commands=isolate%2Crelease%2Ckill-process%2Csuspend-process%2Cprocesses%2Cget-file%2Cexecute%2Cupload'
);
const clearAllButton = getByTestId(`${testPrefix}-${filterPrefix}-clearAllButton`);
clearAllButton.style.pointerEvents = 'all';
userEvent.click(clearAllButton);
expect(history.location.search).toEqual('');
});
it('should clear all selected options on `actions` filter (with `responseActionScanEnabled`)', () => {
mockedContext.setExperimentalFlag({
responseActionScanEnabled: true,
});
it('should clear all selected options on `actions` filter', () => {
const filterPrefix = 'actions-filter';
render();
const { getAllByTestId, getByTestId } = renderResult;

View file

@ -12,10 +12,7 @@ import { getDefaultConfigSettings } from '../common/config_settings';
import type { ConfigType } from './config';
export const createMockConfig = (): ConfigType => {
const enableExperimental: Array<keyof ExperimentalFeatures> = [
'responseActionUploadEnabled',
'responseActionScanEnabled',
];
const enableExperimental: Array<keyof ExperimentalFeatures> = ['responseActionUploadEnabled'];
return {
[SIGNALS_INDEX_KEY]: DEFAULT_SIGNALS_INDEX,

View file

@ -78,7 +78,6 @@ import type { ActionsApiRequestHandlerContext } from '@kbn/actions-plugin/server
import { sentinelOneMock } from '../../services/actions/clients/sentinelone/mocks';
import { ResponseActionsClientError } from '../../services/actions/clients/errors';
import type { EndpointAppContext } from '../../types';
import type { ExperimentalFeatures } from '../../../../common';
jest.mock('../../services', () => {
const realModule = jest.requireActual('../../services');
@ -135,13 +134,6 @@ describe('Response actions', () => {
const docGen = new EndpointDocGenerator();
const setFeatureFlag = (ff: Partial<ExperimentalFeatures>) => {
endpointContext.experimentalFeatures = {
...endpointContext.experimentalFeatures,
...ff,
};
};
beforeEach(() => {
// instantiate... everything
const mockScopedClient = elasticsearchServiceMock.createScopedClusterClient();
@ -174,8 +166,6 @@ describe('Response actions', () => {
licenseService,
});
setFeatureFlag({ responseActionScanEnabled: true });
// add the host isolation route handlers to routerMock
registerResponseActionRoutes(routerMock, endpointContext);

View file

@ -286,28 +286,25 @@ export function registerResponseActionRoutes(
)
);
// 8.15 route
if (endpointContext.experimentalFeatures.responseActionScanEnabled) {
router.versioned
.post({
access: 'public',
path: SCAN_ROUTE,
options: { authRequired: true, tags: ['access:securitySolution'] },
})
.addVersion(
{
version: '2023-10-31',
validate: {
request: ScanActionRequestSchema,
},
router.versioned
.post({
access: 'public',
path: SCAN_ROUTE,
options: { authRequired: true, tags: ['access:securitySolution'] },
})
.addVersion(
{
version: '2023-10-31',
validate: {
request: ScanActionRequestSchema,
},
withEndpointAuthz(
{ all: ['canWriteScanOperations'] },
logger,
responseActionRequestHandler<ResponseActionScanParameters>(endpointContext, 'scan')
)
);
}
},
withEndpointAuthz(
{ all: ['canWriteScanOperations'] },
logger,
responseActionRequestHandler<ResponseActionScanParameters>(endpointContext, 'scan')
)
);
}
function responseActionRequestHandler<T extends EndpointActionDataParameterTypes>(