Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Endpoint] Sample data generator CLI script #59952

Merged
merged 22 commits into from
Mar 16, 2020
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion x-pack/plugins/endpoint/common/generate_data.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ describe('data generator', () => {
const timestamp = new Date().getTime();
const root = generator.generateEvent({ timestamp });
const generations = 2;
const events = generator.generateDescendantsTree(root, generations);
const events = [root, ...generator.generateDescendantsTree(root, generations)];
const rootNode = buildResolverTree(events);
const visitedEvents = countResolverEvents(rootNode, generations);
expect(visitedEvents).toEqual(events.length);
Expand Down
111 changes: 45 additions & 66 deletions x-pack/plugins/endpoint/common/generate_data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import uuid from 'uuid';
import seedrandom from 'seedrandom';
import { AlertEvent, EndpointEvent, EndpointMetadata, OSFields } from './types';
import { AlertEvent, EndpointEvent, EndpointMetadata, OSFields, HostFields } from './types';

export type Event = AlertEvent | EndpointEvent;

Expand Down Expand Up @@ -67,31 +67,51 @@ const FILE_OPERATIONS: string[] = ['creation', 'open', 'rename', 'execution', 'd
// These are from the v1 schemas and aren't all valid ECS event categories, still in flux
const OTHER_EVENT_CATEGORIES: string[] = ['driver', 'file', 'library', 'network', 'registry'];

interface HostInfo {
agent: {
version: string;
id: string;
};
host: HostFields;
endpoint: {
policy: {
id: string;
};
};
}

export class EndpointDocGenerator {
agentId: string;
hostId: string;
hostname: string;
macAddress: string[];
ip: string[];
agentVersion: string;
os: OSFields;
policy: { name: string; id: string };
commonInfo: HostInfo;
random: seedrandom.prng;

constructor(seed = Math.random().toString()) {
this.random = seedrandom(seed);
this.hostId = this.seededUUIDv4();
this.agentId = this.seededUUIDv4();
this.hostname = this.randomHostname();
this.ip = this.randomArray(3, () => this.randomIP());
this.macAddress = this.randomArray(3, () => this.randomMac());
this.agentVersion = this.randomVersion();
this.os = this.randomChoice(OS);
this.policy = this.randomChoice(POLICIES);
this.commonInfo = this.createHostData();
}

public randomizeIPs() {
this.ip = this.randomArray(3, () => this.randomIP());
// This function will create new values for all the host fields, so documents from a different endpoint can be created
// This provides a convenient way to make documents from multiple endpoints that are all tied to a single seed value
public randomizeHostData() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could probably have the constructor call this function so the calls aren't duplicated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea. The compiler complained that the class variables weren't definitely assigned when I called it as it was so I pulled the fields into a new structure. It's now returned by the private function below and assigned in this function and the constructor.

this.commonInfo = this.createHostData();
}

private createHostData(): HostInfo {
return {
agent: {
version: this.randomVersion(),
id: this.seededUUIDv4(),
},
host: {
id: this.seededUUIDv4(),
hostname: this.randomHostname(),
ip: this.randomArray(3, () => this.randomIP()),
mac: this.randomArray(3, () => this.randomMac()),
os: this.randomChoice(OS),
},
endpoint: {
policy: this.randomChoice(POLICIES),
},
};
}

public generateEndpointMetadata(ts = new Date().getTime()): EndpointMetadata {
Expand All @@ -100,22 +120,7 @@ export class EndpointDocGenerator {
event: {
created: ts,
},
endpoint: {
policy: {
id: this.policy.id,
},
},
agent: {
version: this.agentVersion,
id: this.agentId,
},
host: {
id: this.hostId,
hostname: this.hostname,
ip: this.ip,
mac: this.macAddress,
os: this.os,
},
...this.commonInfo,
};
}

Expand All @@ -125,11 +130,8 @@ export class EndpointDocGenerator {
parentEntityID?: string
): AlertEvent {
return {
...this.commonInfo,
'@timestamp': ts,
agent: {
id: this.agentId,
version: this.agentVersion,
},
event: {
action: this.randomChoice(FILE_OPERATIONS),
kind: 'alert',
Expand All @@ -139,11 +141,6 @@ export class EndpointDocGenerator {
module: 'endpoint',
type: 'creation',
},
endpoint: {
policy: {
id: this.policy.id,
},
},
file: {
owner: 'SYSTEM',
name: 'fake_malware.exe',
Expand All @@ -169,13 +166,6 @@ export class EndpointDocGenerator {
},
temp_file_path: 'C:/temp/fake_malware.exe',
},
host: {
id: this.hostId,
hostname: this.hostname,
ip: this.ip,
mac: this.macAddress,
os: this.os,
},
process: {
pid: 2,
name: 'malware writer',
Expand Down Expand Up @@ -243,11 +233,7 @@ export class EndpointDocGenerator {
public generateEvent(options: EventOptions = {}): EndpointEvent {
return {
'@timestamp': options.timestamp ? options.timestamp : new Date().getTime(),
agent: {
id: this.agentId,
version: this.agentVersion,
type: 'endpoint',
},
agent: this.commonInfo.agent,
ecs: {
version: '1.4.0',
},
Expand All @@ -257,13 +243,7 @@ export class EndpointDocGenerator {
type: options.eventType ? options.eventType : 'creation',
id: this.seededUUIDv4(),
},
host: {
id: this.hostId,
hostname: this.hostname,
ip: this.ip,
mac: this.macAddress,
os: this.os,
},
host: this.commonInfo.host,
process: {
entity_id: options.entityID ? options.entityID : this.randomString(10),
parent: options.parentEntityID ? { entity_id: options.parentEntityID } : undefined,
Expand Down Expand Up @@ -323,14 +303,13 @@ export class EndpointDocGenerator {
percentNodesWithRelated = 100,
percentChildrenTerminated = 100
): Event[] {
let events: Event[] = [root];
let events: Event[] = [];
let parents = [root];
let timestamp = root['@timestamp'];
for (let i = 0; i < generations; i++) {
const newParents: EndpointEvent[] = [];
parents.forEach(element => {
// const numChildren = randomN(maxChildrenPerNode);
const numChildren = maxChildrenPerNode;
const numChildren = this.randomN(maxChildrenPerNode);
for (let j = 0; j < numChildren; j++) {
timestamp = timestamp + 1000;
const child = this.generateEvent({
Expand Down
Loading