From fcc702f4a4923d74ec56af11830c1d241b3f6b6b Mon Sep 17 00:00:00 2001 From: "konrad.szwarc" Date: Mon, 17 Apr 2023 18:19:45 +0200 Subject: [PATCH] use custom document generator --- .../endpoint_metadata_generator.ts | 5 ++++ .../data_loaders/index_endpoint_hosts.ts | 6 ++-- .../common/endpoint/generate_data.ts | 9 ++---- .../common/endpoint/index_data.ts | 13 +++----- .../public/management/cypress/cypress.d.ts | 13 ++++++-- .../cypress/e2e/mocked_data/isolate.cy.ts | 30 ++++++++++++++----- .../cypress/support/data_loaders.ts | 19 ++++++++++-- .../plugin_handlers/endpoint_data_loader.ts | 15 ++++------ .../public/management/cypress/types.ts | 13 +++++++- .../endpoint_hosts/store/middleware.test.ts | 18 +++++------ .../services/endpoint_response_actions.ts | 3 +- .../apps/endpoint/endpoint_list.ts | 16 ++-------- 12 files changed, 97 insertions(+), 63 deletions(-) diff --git a/x-pack/plugins/security_solution/common/endpoint/data_generators/endpoint_metadata_generator.ts b/x-pack/plugins/security_solution/common/endpoint/data_generators/endpoint_metadata_generator.ts index 8b6b11ac9260e..9910477437e82 100644 --- a/x-pack/plugins/security_solution/common/endpoint/data_generators/endpoint_metadata_generator.ts +++ b/x-pack/plugins/security_solution/common/endpoint/data_generators/endpoint_metadata_generator.ts @@ -20,6 +20,7 @@ export interface GetCustomEndpointMetadataGeneratorOptions { version: string; /** OS type for the generated endpoint hosts */ os: 'macOS' | 'windows' | 'linux'; + isolation: boolean; } /** @@ -33,6 +34,7 @@ export class EndpointMetadataGenerator extends BaseDataGenerator { static custom({ version, os, + isolation, }: Partial = {}): typeof EndpointMetadataGenerator { return class extends EndpointMetadataGenerator { generate(overrides: DeepPartial = {}): HostMetadataInterface { @@ -54,6 +56,9 @@ export class EndpointMetadataGenerator extends BaseDataGenerator { set(overrides, 'host.os', EndpointMetadataGenerator.windowsOSFields); } } + if (isolation !== undefined) { + set(overrides, 'Endpoint.state.isolation', isolation); + } return super.generate(overrides); } diff --git a/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_endpoint_hosts.ts b/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_endpoint_hosts.ts index 7693653c3c5a6..684694bdb5c9a 100644 --- a/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_endpoint_hosts.ts +++ b/x-pack/plugins/security_solution/common/endpoint/data_loaders/index_endpoint_hosts.ts @@ -87,7 +87,7 @@ export async function indexEndpointHostDocs({ policyResponseIndex, enrollFleet, generator, - disableEndpointActionsForHost, + withResponseActions = true, }: { numDocs: number; client: Client; @@ -98,7 +98,7 @@ export async function indexEndpointHostDocs({ policyResponseIndex: string; enrollFleet: boolean; generator: EndpointDocGenerator; - disableEndpointActionsForHost?: boolean; + withResponseActions?: boolean; }): Promise { const timeBetweenDocs = 6 * 3600 * 1000; // 6 hours between metadata documents const timestamp = new Date().getTime(); @@ -193,7 +193,7 @@ export async function indexEndpointHostDocs({ }, }; - if (!disableEndpointActionsForHost) { + if (withResponseActions) { // Create some fleet endpoint actions and .logs-endpoint actions for this Host const actionsResponse = await indexEndpointAndFleetActionsForHost( client, diff --git a/x-pack/plugins/security_solution/common/endpoint/generate_data.ts b/x-pack/plugins/security_solution/common/endpoint/generate_data.ts index 6285c0b6f4309..76ee903eb6889 100644 --- a/x-pack/plugins/security_solution/common/endpoint/generate_data.ts +++ b/x-pack/plugins/security_solution/common/endpoint/generate_data.ts @@ -340,16 +340,14 @@ export class EndpointDocGenerator extends BaseDataGenerator { * * @param seed either a string to seed the random number generator or a random number generator function * @param MetadataGenerator - * @param endpointIsolated */ constructor( seed: string | seedrandom.prng = Math.random().toString(), - MetadataGenerator: typeof EndpointMetadataGenerator = EndpointMetadataGenerator, - endpointIsolated?: boolean + MetadataGenerator: typeof EndpointMetadataGenerator = EndpointMetadataGenerator ) { super(seed); this.metadataGenerator = new MetadataGenerator(seed); - this.commonInfo = this.createHostData(endpointIsolated); + this.commonInfo = this.createHostData(); } /** @@ -410,11 +408,10 @@ export class EndpointDocGenerator extends BaseDataGenerator { }; } - private createHostData(endpointIsolated?: boolean): CommonHostInfo { + private createHostData(): CommonHostInfo { const { agent, elastic, host, Endpoint } = this.metadataGenerator.generate({ Endpoint: { policy: { applied: this.randomChoice(APPLIED_POLICIES) }, - state: { isolation: endpointIsolated }, }, }); diff --git a/x-pack/plugins/security_solution/common/endpoint/index_data.ts b/x-pack/plugins/security_solution/common/endpoint/index_data.ts index 9b8181036521b..8241c1f0f1e10 100644 --- a/x-pack/plugins/security_solution/common/endpoint/index_data.ts +++ b/x-pack/plugins/security_solution/common/endpoint/index_data.ts @@ -48,9 +48,7 @@ export type IndexedHostsAndAlertsResponse = IndexedHostsResponse; * @param fleet * @param options * @param DocGenerator - * @param disableEndpointActionsForHost - * @param bothIsolatedAndNormalEndpoints - * @param endpointIsolated + * @param withResponseActions */ export async function indexHostsAndAlerts( client: Client, @@ -66,9 +64,7 @@ export async function indexHostsAndAlerts( fleet: boolean, options: TreeOptions = {}, DocGenerator: typeof EndpointDocGenerator = EndpointDocGenerator, - disableEndpointActionsForHost = false, - bothIsolatedAndNormalEndpoints = false, - endpointIsolated?: boolean + withResponseActions = true ): Promise { const random = seedrandom(seed); const epmEndpointPackage = await getEndpointPackageInfo(kbnClient); @@ -109,8 +105,7 @@ export async function indexHostsAndAlerts( } for (let i = 0; i < numHosts; i++) { - const isolateHost = bothIsolatedAndNormalEndpoints && i % 2 === 0; - const generator = new DocGenerator(random, undefined, isolateHost ? true : endpointIsolated); + const generator = new DocGenerator(random, undefined); const indexedHosts = await indexEndpointHostDocs({ numDocs, client, @@ -121,7 +116,7 @@ export async function indexHostsAndAlerts( policyResponseIndex, enrollFleet: fleet, generator, - disableEndpointActionsForHost, + withResponseActions, }); mergeAndAppendArrays(response, indexedHosts); diff --git a/x-pack/plugins/security_solution/public/management/cypress/cypress.d.ts b/x-pack/plugins/security_solution/public/management/cypress/cypress.d.ts index a48498a7ee43b..c461f712b75b5 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/cypress.d.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/cypress.d.ts @@ -11,8 +11,11 @@ import type { CasePostRequest } from '@kbn/cases-plugin/common/api'; import type { IndexedEndpointPolicyResponse } from '../../../common/endpoint/data_loaders/index_endpoint_policy_response'; -import type { HostPolicyResponse } from '../../../common/endpoint/types'; -import type { IndexEndpointHostsCyTaskOptions } from './types'; +import type { + HostPolicyResponse, + LogsEndpointActionResponse, +} from '../../../common/endpoint/types'; +import type { IndexEndpointHostsCyTaskOptions, HostActionResponse } from './types'; import type { DeleteIndexedFleetEndpointPoliciesResponse, IndexedFleetEndpointPolicyResponse, @@ -115,6 +118,12 @@ declare global { arg: IndexedEndpointPolicyResponse, options?: Partial ): Chainable; + + task( + name: 'sendHostActionResponse', + arg: HostActionResponse, + options?: Partial + ): Chainable; } } } diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/isolate.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/isolate.cy.ts index e3338586b56fb..3cc2d03854c06 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/isolate.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/isolate.cy.ts @@ -27,16 +27,24 @@ import { indexEndpointRuleAlerts } from '../../tasks/index_endpoint_rule_alerts' describe('Isolate command', () => { describe('from Manage', () => { let endpointData: ReturnTypeFromChainable; + let isolatedEndpointData: ReturnTypeFromChainable; before(() => { indexEndpointHosts({ - count: 4, - disableEndpointActionsForHost: true, - endpointIsolated: false, - bothIsolatedAndNormalEndpoints: true, + count: 2, + withResponseActions: false, + isolation: false, }).then((indexEndpoints) => { endpointData = indexEndpoints; }); + + indexEndpointHosts({ + count: 2, + withResponseActions: false, + isolation: true, + }).then((indexEndpoints) => { + isolatedEndpointData = indexEndpoints; + }); }); after(() => { @@ -45,6 +53,12 @@ describe('Isolate command', () => { // @ts-expect-error ignore setting to undefined endpointData = undefined; } + + if (isolatedEndpointData) { + isolatedEndpointData.cleanup(); + // @ts-expect-error ignore setting to undefined + isolatedEndpointData = undefined; + } }); beforeEach(() => { login(); @@ -71,7 +85,7 @@ describe('Isolate command', () => { let hostname: string; before(() => { - indexEndpointHosts({ disableEndpointActionsForHost: true, endpointIsolated: false }) + indexEndpointHosts({ withResponseActions: false, isolation: false }) .then((indexEndpoints) => { endpointData = indexEndpoints; hostname = endpointData.data.hosts[0].host.name; @@ -196,7 +210,7 @@ describe('Isolate command', () => { caseUrlPath = `${APP_CASES_PATH}/${indexCase.data.id}`; }); - indexEndpointHosts({ disableEndpointActionsForHost: true }) + indexEndpointHosts({ withResponseActions: false, isolation: false }) .then((indexEndpoints) => { endpointData = indexEndpoints; hostname = endpointData.data.hosts[0].host.name; @@ -270,7 +284,7 @@ describe('Isolate command', () => { cy.getByTestSubj('euiFlyoutCloseButton').click(); - cy.getByTestSubj('user-actions').within(() => { + cy.getByTestSubj('user-actions-list').within(() => { cy.contains(isolateComment); cy.get('[aria-label="lock"]').should('exist'); cy.get('[aria-label="lockOpen"]').should('not.exist'); @@ -293,7 +307,7 @@ describe('Isolate command', () => { cy.contains(`Release on host ${hostname} successfully submitted`); cy.getByTestSubj('euiFlyoutCloseButton').click(); - cy.getByTestSubj('user-actions').within(() => { + cy.getByTestSubj('user-actions-list').within(() => { cy.contains(releaseComment); cy.contains(isolateComment); cy.get('[aria-label="lock"]').should('exist'); diff --git a/x-pack/plugins/security_solution/public/management/cypress/support/data_loaders.ts b/x-pack/plugins/security_solution/public/management/cypress/support/data_loaders.ts index b31ee2ec25874..6dd4bedaa8937 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/support/data_loaders.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/support/data_loaders.ts @@ -8,12 +8,17 @@ // / import type { CasePostRequest } from '@kbn/cases-plugin/common/api'; +import { sendEndpointActionResponse } from '../../../../scripts/endpoint/agent_emulator/services/endpoint_response_actions'; import type { IndexedEndpointPolicyResponse } from '../../../../common/endpoint/data_loaders/index_endpoint_policy_response'; import { deleteIndexedEndpointPolicyResponse, indexEndpointPolicyResponse, } from '../../../../common/endpoint/data_loaders/index_endpoint_policy_response'; -import type { HostPolicyResponse } from '../../../../common/endpoint/types'; +import type { + ActionDetails, + HostPolicyResponse, + LogsEndpointActionResponse, +} from '../../../../common/endpoint/types'; import type { IndexEndpointHostsCyTaskOptions } from '../types'; import type { IndexedEndpointRuleAlerts, @@ -95,12 +100,14 @@ export const dataLoaders = ( indexEndpointHosts: async (options: IndexEndpointHostsCyTaskOptions = {}) => { const { kbnClient, esClient } = await stackServicesPromise; - const { count: numHosts, version, os } = options; + const { count: numHosts, version, os, isolation, withResponseActions } = options; return cyLoadEndpointDataHandler(esClient, kbnClient, { numHosts, version, os, + isolation, + withResponseActions, }); }, @@ -140,5 +147,13 @@ export const dataLoaders = ( const { esClient } = await stackServicesPromise; return deleteIndexedEndpointPolicyResponse(esClient, indexedData).then(() => null); }, + + sendHostActionResponse: async (data: { + action: ActionDetails; + state: { state?: 'success' | 'failure' }; + }): Promise => { + const { esClient } = await stackServicesPromise; + return sendEndpointActionResponse(esClient, data.action, { state: data.state.state }); + }, }); }; diff --git a/x-pack/plugins/security_solution/public/management/cypress/support/plugin_handlers/endpoint_data_loader.ts b/x-pack/plugins/security_solution/public/management/cypress/support/plugin_handlers/endpoint_data_loader.ts index dd23898263d17..9d0f5ac135d5d 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/support/plugin_handlers/endpoint_data_loader.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/support/plugin_handlers/endpoint_data_loader.ts @@ -36,8 +36,8 @@ export interface CyLoadEndpointDataOptions enableFleetIntegration: boolean; generatorSeed: string; waitUntilTransformed: boolean; - disableEndpointActionsForHost?: boolean; - endpointIsolated?: boolean; + withResponseActions: boolean; + isolation: boolean; bothIsolatedAndNormalEndpoints?: boolean; } @@ -61,13 +61,12 @@ export const cyLoadEndpointDataHandler = async ( waitUntilTransformed = true, version = kibanaPackageJson.version, os, - disableEndpointActionsForHost, - bothIsolatedAndNormalEndpoints, - endpointIsolated, + withResponseActions, + isolation, } = options; const DocGenerator = EndpointDocGenerator.custom({ - CustomMetadataGenerator: EndpointMetadataGenerator.custom({ version, os }), + CustomMetadataGenerator: EndpointMetadataGenerator.custom({ version, os, isolation }), }); if (waitUntilTransformed) { @@ -92,9 +91,7 @@ export const cyLoadEndpointDataHandler = async ( enableFleetIntegration, undefined, DocGenerator, - disableEndpointActionsForHost, - bothIsolatedAndNormalEndpoints, - endpointIsolated + withResponseActions ); if (waitUntilTransformed) { diff --git a/x-pack/plugins/security_solution/public/management/cypress/types.ts b/x-pack/plugins/security_solution/public/management/cypress/types.ts index 0741f7fab1ad0..97d635a3b6840 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/types.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/types.ts @@ -7,6 +7,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ +import type { ActionDetails } from '../../../common/endpoint/types'; import type { CyLoadEndpointDataOptions } from './support/plugin_handlers/endpoint_data_loader'; type PossibleChainable = @@ -41,5 +42,15 @@ export type ReturnTypeFromChainable = C extends Cyp : never; export type IndexEndpointHostsCyTaskOptions = Partial< - { count: number } & Pick + { count: number; withResponseActions: boolean } & Pick< + CyLoadEndpointDataOptions, + 'version' | 'os' | 'isolation' + > >; + +export interface HostActionResponse { + data: { + action: ActionDetails; + state: { state?: 'success' | 'failure' }; + }; +} diff --git a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.test.ts b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.test.ts index b72d4fa30777d..40abffc508fab 100644 --- a/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.test.ts +++ b/x-pack/plugins/security_solution/public/management/pages/endpoint_hosts/store/middleware.test.ts @@ -256,15 +256,15 @@ describe('endpoint list middleware', () => { query: { agent_ids: [ '0dc3661d-6e67-46b0-af39-6f12b025fcb0', - '34634c58-24b4-4448-80f4-107fb9918494', - '5a1298e3-e607-4bc0-8ef6-6d6a811312f2', - '78c54b13-596d-4891-95f4-80092d04454b', - '445f1fd2-5f81-4ddd-bdb6-f0d1bf2efe90', - 'd77a3fc6-3096-4852-a6ee-f6b09278fbc6', - '892fcccf-1bd8-45a2-a9cc-9a7860a3cb81', - '693a3110-5ba0-4284-a264-5d78301db08c', - '554db084-64fa-4e4a-ba47-2ba713f9932b', - 'c217deb6-674d-4f97-bb1d-a3a04238e6d7', + 'fe16dda9-7f34-434c-9824-b4844880f410', + 'f412728b-929c-48d5-bdb6-5a1298e3e607', + 'd0405ddc-1e7c-48f0-93d7-d55f954bd745', + '46d78dd2-aedf-4d3f-b3a9-da445f1fd25f', + '5aafa558-26b8-4bb4-80e2-ac0644d77a3f', + 'edac2c58-1748-40c3-853c-8fab48c333d7', + '06b7223a-bb2a-428a-9021-f1c0d2267ada', + 'b8daa43b-7f73-4684-9221-dbc8b769405e', + 'fbc06310-7d41-46b8-a5ea-ceed8a993b1a', ], }, }); diff --git a/x-pack/plugins/security_solution/scripts/endpoint/agent_emulator/services/endpoint_response_actions.ts b/x-pack/plugins/security_solution/scripts/endpoint/agent_emulator/services/endpoint_response_actions.ts index 615cbe38baf7f..25c2e5f6327be 100644 --- a/x-pack/plugins/security_solution/scripts/endpoint/agent_emulator/services/endpoint_response_actions.ts +++ b/x-pack/plugins/security_solution/scripts/endpoint/agent_emulator/services/endpoint_response_actions.ts @@ -40,6 +40,8 @@ const ES_INDEX_OPTIONS = { headers: { 'X-elastic-product-origin': 'fleet' } }; export const fleetActionGenerator = new FleetActionGenerator(); +export const endpointActionGenerator = new EndpointActionGenerator(); + export const sleep = (ms: number = 1000) => new Promise((r) => setTimeout(r, ms)); export const fetchEndpointActionList = async ( @@ -116,7 +118,6 @@ export const sendEndpointActionResponse = async ( action: ActionDetails, { state }: { state?: 'success' | 'failure' } = {} ): Promise => { - const endpointActionGenerator = new EndpointActionGenerator(); const endpointResponse = endpointActionGenerator.generateResponse({ agent: { id: action.agents[0] }, EndpointActions: { diff --git a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts index 0bfb0cc5bba1d..2efd2bf52309b 100644 --- a/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts +++ b/x-pack/test/security_solution_endpoint/apps/endpoint/endpoint_list.ts @@ -33,27 +33,17 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { 'Actions', ], [ - 'Host-dpu1a2r2yi', + 'Host-9qenwrl9ko', 'x', 'x', 'Warning', 'Linux', - '10.2.17.24, 10.56.215.200,10.254.196.130', - 'x', - 'x', - '', - ], - [ - 'Host-rs9wp4o6l9', - 'x', - 'x', - 'Success', - 'Linux', - '10.138.79.131, 10.170.160.154', + '10.56.228.101, 10.201.120.140,10.236.180.146', 'x', 'x', '', ], + ['Host-qw2bti801m', 'x', 'x', 'Failure', 'Linux', '10.244.59.227', 'x', 'x', ''], [ 'Host-u5jy6j0pwb', 'x',