From d19aeae4946f442c7bb7ce9f874fbfc25bf07d2d Mon Sep 17 00:00:00 2001 From: Paul Tavares Date: Tue, 25 May 2021 15:13:46 -0400 Subject: [PATCH 1/6] Generate random isolation values for endpoint metadata --- .../common/endpoint/data_generators/base_data_generator.ts | 6 ++++++ .../security_solution/common/endpoint/generate_data.ts | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/common/endpoint/data_generators/base_data_generator.ts b/x-pack/plugins/security_solution/common/endpoint/data_generators/base_data_generator.ts index c0888a6c2a4bd..8f92135ad6191 100644 --- a/x-pack/plugins/security_solution/common/endpoint/data_generators/base_data_generator.ts +++ b/x-pack/plugins/security_solution/common/endpoint/data_generators/base_data_generator.ts @@ -9,6 +9,7 @@ import seedrandom from 'seedrandom'; import uuid from 'uuid'; const OS_FAMILY = ['windows', 'macos', 'linux']; +const BOOLEANS = [true, false]; /** * A generic base class to assist in creating domain specific data generators. It includes @@ -33,6 +34,11 @@ export class BaseDataGenerator { throw new Error('method not implemented!'); } + /** Generate either `true` or `false` */ + protected randomBoolean(): boolean { + return this.randomChoice(BOOLEANS); + } + /** generate random OS family value */ protected randomOSFamily(): string { return this.randomChoice(OS_FAMILY); 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 4a86d7fd4de77..d77986175e4a3 100644 --- a/x-pack/plugins/security_solution/common/endpoint/generate_data.ts +++ b/x-pack/plugins/security_solution/common/endpoint/generate_data.ts @@ -465,10 +465,10 @@ export class EndpointDocGenerator extends BaseDataGenerator { applied: this.randomChoice(APPLIED_POLICIES), }, configuration: { - isolation: false, + isolation: this.randomBoolean(), }, state: { - isolation: false, + isolation: this.randomBoolean(), }, }, }; From 4d9c717aac31d450933ffa46f4c04dd9a79a00b5 Mon Sep 17 00:00:00 2001 From: Paul Tavares Date: Tue, 25 May 2021 16:25:58 -0400 Subject: [PATCH 2/6] Generator for Fleet Actions --- .../data_generators/base_data_generator.ts | 14 +++++ .../data_generators/fleet_action_generator.ts | 53 +++++++++++++++++++ .../common/endpoint/types/actions.ts | 15 ++++++ 3 files changed, 82 insertions(+) create mode 100644 x-pack/plugins/security_solution/common/endpoint/data_generators/fleet_action_generator.ts diff --git a/x-pack/plugins/security_solution/common/endpoint/data_generators/base_data_generator.ts b/x-pack/plugins/security_solution/common/endpoint/data_generators/base_data_generator.ts index 8f92135ad6191..9e167c9b8db9a 100644 --- a/x-pack/plugins/security_solution/common/endpoint/data_generators/base_data_generator.ts +++ b/x-pack/plugins/security_solution/common/endpoint/data_generators/base_data_generator.ts @@ -10,6 +10,8 @@ import uuid from 'uuid'; const OS_FAMILY = ['windows', 'macos', 'linux']; const BOOLEANS = [true, false]; +/** Array of 14 day offsets */ +const DAY_OFFSETS = Array.from({ length: 14 }, (_, i) => 8.64e7 * (i + 1)); /** * A generic base class to assist in creating domain specific data generators. It includes @@ -34,6 +36,18 @@ export class BaseDataGenerator { throw new Error('method not implemented!'); } + /** Returns a future ISO date string */ + protected randomFutureDate(from?: Date): string { + const now = from ? from.getTime() : Date.now(); + return new Date(now + this.randomChoice(DAY_OFFSETS)).toISOString(); + } + + /** Returns a past ISO date string */ + protected randomPastDate(from?: Date): string { + const now = from ? from.getTime() : Date.now(); + return new Date(now - this.randomChoice(DAY_OFFSETS)).toISOString(); + } + /** Generate either `true` or `false` */ protected randomBoolean(): boolean { return this.randomChoice(BOOLEANS); diff --git a/x-pack/plugins/security_solution/common/endpoint/data_generators/fleet_action_generator.ts b/x-pack/plugins/security_solution/common/endpoint/data_generators/fleet_action_generator.ts new file mode 100644 index 0000000000000..20544ca660669 --- /dev/null +++ b/x-pack/plugins/security_solution/common/endpoint/data_generators/fleet_action_generator.ts @@ -0,0 +1,53 @@ +/* + * 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 { DeepPartial } from 'utility-types'; +import { merge } from 'lodash'; +import { BaseDataGenerator } from './base_data_generator'; +import { EndpointAction, EndpointActionResponse } from '../types'; + +export class FleetActionGenerator extends BaseDataGenerator { + /** Generate an Action */ + generate(overrides: DeepPartial = {}): EndpointAction { + const timeStamp = new Date(this.randomPastDate()); + + return merge( + { + action_id: this.randomUUID(), + '@timestamp': timeStamp.toISOString(), + expiration: this.randomFutureDate(timeStamp), + type: 'INPUT_ACTION', + input_type: 'endpoint', + agents: [this.randomUUID()], + user_id: 'elastic', + data: { + command: 'isolate', + comment: this.randomString(15), + }, + }, + overrides + ); + } + + generateResponse(overrides: DeepPartial = {}): EndpointActionResponse { + return merge( + { + action_data: { + command: 'isolate', + comment: null, + }, + action_id: this.randomUUID(), + agent_id: this.randomUUID(), + started_at: this.randomPastDate(), + completed_at: new Date().toISOString(), + error: 'some error happen', + '@timestamp': new Date().toISOString(), + }, + overrides + ); + } +} diff --git a/x-pack/plugins/security_solution/common/endpoint/types/actions.ts b/x-pack/plugins/security_solution/common/endpoint/types/actions.ts index 99dac5ea5cda6..fcfda9c9a30d9 100644 --- a/x-pack/plugins/security_solution/common/endpoint/types/actions.ts +++ b/x-pack/plugins/security_solution/common/endpoint/types/actions.ts @@ -24,6 +24,21 @@ export interface EndpointAction { }; } +export interface EndpointActionResponse { + '@timestamp': string; + /** The id of the action for which this response is associated with */ + action_id: string; + /** The agent id that sent this action response */ + agent_id: string; + started_at: string; + completed_at: string; + error: string; + action_data: { + command: ISOLATION_ACTIONS; + comment?: string; + }; +} + export type HostIsolationRequestBody = TypeOf; export interface HostIsolationResponse { From 0d4e75d46d0431ea68060f747aa268df9cdc6dc8 Mon Sep 17 00:00:00 2001 From: Paul Tavares Date: Wed, 26 May 2021 15:02:25 -0400 Subject: [PATCH 3/6] Added creation of actions to the index data generator --- .../data_generators/fleet_action_generator.ts | 8 ++-- .../common/endpoint/index_data.ts | 45 +++++++++++++++++++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/security_solution/common/endpoint/data_generators/fleet_action_generator.ts b/x-pack/plugins/security_solution/common/endpoint/data_generators/fleet_action_generator.ts index 20544ca660669..1d71b56704368 100644 --- a/x-pack/plugins/security_solution/common/endpoint/data_generators/fleet_action_generator.ts +++ b/x-pack/plugins/security_solution/common/endpoint/data_generators/fleet_action_generator.ts @@ -34,18 +34,20 @@ export class FleetActionGenerator extends BaseDataGenerator { } generateResponse(overrides: DeepPartial = {}): EndpointActionResponse { + const timeStamp = new Date(); + return merge( { action_data: { command: 'isolate', - comment: null, + comment: '', }, action_id: this.randomUUID(), agent_id: this.randomUUID(), started_at: this.randomPastDate(), - completed_at: new Date().toISOString(), + completed_at: timeStamp.toISOString(), error: 'some error happen', - '@timestamp': new Date().toISOString(), + '@timestamp': timeStamp.toISOString(), }, overrides ); 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 0dc7891560c2d..42dc3cb928713 100644 --- a/x-pack/plugins/security_solution/common/endpoint/index_data.ts +++ b/x-pack/plugins/security_solution/common/endpoint/index_data.ts @@ -28,8 +28,10 @@ import { policyFactory as policyConfigFactory } from './models/policy_config'; import { HostMetadata } from './types'; import { KbnClientWithApiKeySupport } from '../../scripts/endpoint/kbn_client_with_api_key_support'; import { FleetAgentGenerator } from './data_generators/fleet_agent_generator'; +import { FleetActionGenerator } from './data_generators/fleet_action_generator'; const fleetAgentGenerator = new FleetAgentGenerator(); +const fleetActionGenerator = new FleetActionGenerator(); export async function indexHostsAndAlerts( client: Client, @@ -175,6 +177,9 @@ async function indexHostDocs({ }, }, }; + + // Create some actions for this Host + await indexFleetActionsForHost(client, hostMetadata); } await client.index({ @@ -397,3 +402,43 @@ const indexFleetAgentForHost = async ( return agentDoc; }; + +const indexFleetActionsForHost = async ( + esClient: Client, + endpointHost: HostMetadata +): Promise => { + const ES_INDEX_OPTIONS = { headers: { 'X-elastic-product-origin': 'fleet' } }; + const agentId = endpointHost.elastic.agent.id; + + for (let i = 0; i < 5; i++) { + // create an action + const isolateAction = fleetActionGenerator.generate({ + data: { comment: 'data generator: this host is bad' }, + }); + + isolateAction.agents = [agentId]; + + await esClient.index( + { + index: '.fleet-actions', + body: isolateAction, + }, + ES_INDEX_OPTIONS + ); + + // Create an action response for the above + const unIsolateAction = fleetActionGenerator.generateResponse({ + action_id: isolateAction.action_id, + agent_id: agentId, + action_data: { comment: 'data generator: bad host isolated' }, + }); + + await esClient.index( + { + index: '.fleet-actions-results', + body: unIsolateAction, + }, + ES_INDEX_OPTIONS + ); + } +}; From 4d45c0a3adca4ddc9e820ee7dda32b687d1fd893 Mon Sep 17 00:00:00 2001 From: Paul Tavares Date: Wed, 26 May 2021 15:19:05 -0400 Subject: [PATCH 4/6] randomize `data.command` value --- .../data_generators/fleet_action_generator.ts | 13 ++++++++++--- .../security_solution/common/endpoint/index_data.ts | 5 ++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/security_solution/common/endpoint/data_generators/fleet_action_generator.ts b/x-pack/plugins/security_solution/common/endpoint/data_generators/fleet_action_generator.ts index 1d71b56704368..af799de782f48 100644 --- a/x-pack/plugins/security_solution/common/endpoint/data_generators/fleet_action_generator.ts +++ b/x-pack/plugins/security_solution/common/endpoint/data_generators/fleet_action_generator.ts @@ -8,7 +8,9 @@ import { DeepPartial } from 'utility-types'; import { merge } from 'lodash'; import { BaseDataGenerator } from './base_data_generator'; -import { EndpointAction, EndpointActionResponse } from '../types'; +import { EndpointAction, EndpointActionResponse, ISOLATION_ACTIONS } from '../types'; + +const ISOLATION_COMMANDS: ISOLATION_ACTIONS[] = ['isolate', 'unisolate']; export class FleetActionGenerator extends BaseDataGenerator { /** Generate an Action */ @@ -25,7 +27,7 @@ export class FleetActionGenerator extends BaseDataGenerator { agents: [this.randomUUID()], user_id: 'elastic', data: { - command: 'isolate', + command: this.randomIsolateCommand(), comment: this.randomString(15), }, }, @@ -33,13 +35,14 @@ export class FleetActionGenerator extends BaseDataGenerator { ); } + /** Generates an action response */ generateResponse(overrides: DeepPartial = {}): EndpointActionResponse { const timeStamp = new Date(); return merge( { action_data: { - command: 'isolate', + command: this.randomIsolateCommand(), comment: '', }, action_id: this.randomUUID(), @@ -52,4 +55,8 @@ export class FleetActionGenerator extends BaseDataGenerator { overrides ); } + + protected randomIsolateCommand() { + return this.randomChoice(ISOLATION_COMMANDS); + } } 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 42dc3cb928713..01c72a6a9dee9 100644 --- a/x-pack/plugins/security_solution/common/endpoint/index_data.ts +++ b/x-pack/plugins/security_solution/common/endpoint/index_data.ts @@ -430,7 +430,10 @@ const indexFleetActionsForHost = async ( const unIsolateAction = fleetActionGenerator.generateResponse({ action_id: isolateAction.action_id, agent_id: agentId, - action_data: { comment: 'data generator: bad host isolated' }, + action_data: { + command: isolateAction.data.command, + comment: 'data generator: bad host isolated', + }, }); await esClient.index( From 0ffdafe2c68404214a2a20e5f0a946155aa3785e Mon Sep 17 00:00:00 2001 From: Paul Tavares Date: Wed, 26 May 2021 16:02:10 -0400 Subject: [PATCH 5/6] adjustments from PR review --- .../security_solution/common/endpoint/generate_data.ts | 6 ++++-- .../plugins/security_solution/common/endpoint/index_data.ts | 5 +---- 2 files changed, 5 insertions(+), 6 deletions(-) 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 c3780f3cccce6..436f1573639c8 100644 --- a/x-pack/plugins/security_solution/common/endpoint/generate_data.ts +++ b/x-pack/plugins/security_solution/common/endpoint/generate_data.ts @@ -439,6 +439,8 @@ export class EndpointDocGenerator extends BaseDataGenerator { private createHostData(): HostInfo { const hostName = this.randomHostname(); + const isIsolated = this.randomBoolean(); + return { agent: { version: this.randomVersion(), @@ -465,10 +467,10 @@ export class EndpointDocGenerator extends BaseDataGenerator { applied: this.randomChoice(APPLIED_POLICIES), }, configuration: { - isolation: this.randomBoolean(), + isolation: isIsolated, }, state: { - isolation: this.randomBoolean(), + isolation: isIsolated, }, }, }; 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 01c72a6a9dee9..021b9bcb1eccc 100644 --- a/x-pack/plugins/security_solution/common/endpoint/index_data.ts +++ b/x-pack/plugins/security_solution/common/endpoint/index_data.ts @@ -430,10 +430,7 @@ const indexFleetActionsForHost = async ( const unIsolateAction = fleetActionGenerator.generateResponse({ action_id: isolateAction.action_id, agent_id: agentId, - action_data: { - command: isolateAction.data.command, - comment: 'data generator: bad host isolated', - }, + action_data: isolateAction.data, }); await esClient.index( From 9e8bd5407024c297030bc87ebb8b2cb99b747b59 Mon Sep 17 00:00:00 2001 From: Paul Tavares Date: Thu, 27 May 2021 08:37:04 -0400 Subject: [PATCH 6/6] Adjust `.randomBoolean()` --- .../common/endpoint/data_generators/base_data_generator.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/common/endpoint/data_generators/base_data_generator.ts b/x-pack/plugins/security_solution/common/endpoint/data_generators/base_data_generator.ts index 9e167c9b8db9a..d1b107b5396dd 100644 --- a/x-pack/plugins/security_solution/common/endpoint/data_generators/base_data_generator.ts +++ b/x-pack/plugins/security_solution/common/endpoint/data_generators/base_data_generator.ts @@ -9,7 +9,6 @@ import seedrandom from 'seedrandom'; import uuid from 'uuid'; const OS_FAMILY = ['windows', 'macos', 'linux']; -const BOOLEANS = [true, false]; /** Array of 14 day offsets */ const DAY_OFFSETS = Array.from({ length: 14 }, (_, i) => 8.64e7 * (i + 1)); @@ -50,7 +49,7 @@ export class BaseDataGenerator { /** Generate either `true` or `false` */ protected randomBoolean(): boolean { - return this.randomChoice(BOOLEANS); + return Math.random() < 0.5; } /** generate random OS family value */