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

[Security] Alert Telemetry for the Security app #77200

Merged
merged 27 commits into from
Sep 30, 2020
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
e2250a9
Empty recurring task
tsg Aug 17, 2020
da753fe
Added processEvents with tests
tsg Aug 18, 2020
6335857
SendIfDue + tests
tsg Aug 19, 2020
c302fdd
Connect telemetry in the detection engine
tsg Sep 7, 2020
5e14df8
Respect opt-in status
tsg Sep 10, 2020
7bcf141
test fixes + test for telemetry disabled
tsg Sep 10, 2020
483e3cf
Various type fixes
tsg Sep 18, 2020
0cd31af
Merge branch 'master' into telemetry_events
elasticmachine Sep 18, 2020
65a5078
Add cluster_uuid and cluster_name
tsg Sep 21, 2020
fb6b3ea
Filter by endpoint alerts
tsg Sep 22, 2020
2fdc70c
type fixes + tests
tsg Sep 23, 2020
725fc54
mege master
tsg Sep 23, 2020
069147f
fix types
tsg Sep 23, 2020
896ca96
merge master
tsg Sep 28, 2020
0ae4046
Refactor processEvents
tsg Sep 28, 2020
2f31f49
Send events to the telemetry server
tsg Sep 29, 2020
f8309c9
Small refactoring
tsg Sep 29, 2020
b2df3a8
Add license fields
tsg Sep 29, 2020
e6a2d71
Update x-pack/plugins/security_solution/server/lib/detection_engine/s…
tsg Sep 29, 2020
722e68d
Move undefined check in the function to simplify top level code
tsg Sep 29, 2020
5f25435
Correct datastream to data_stream
tsg Sep 29, 2020
1a29cbd
Incorporated Xavier's feedback + add license header
tsg Sep 30, 2020
0dda88c
Test fix + minor changes
tsg Sep 30, 2020
23fbe32
Commented out verbose debug logs
tsg Sep 30, 2020
52390cf
Merge branch 'master' into telemetry_events
elasticmachine Sep 30, 2020
d0d52f4
Merge branch 'master' into telemetry_events
elasticmachine Sep 30, 2020
e8b364d
Merge branch 'master' into telemetry_events
elasticmachine Sep 30, 2020
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
3 changes: 2 additions & 1 deletion x-pack/plugins/security_solution/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
"spaces",
"usageCollection",
"lists",
"home"
"home",
"telemetry"
],
"server": true,
"ui": true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ describe('searchAfterAndBulkCreate', () => {
exceptionsList: [exceptionItem],
services: mockService,
logger: mockLogger,
eventsTelemetry: undefined,
id: sampleRuleGuid,
inputIndexPattern,
signalsIndex: DEFAULT_SIGNALS_INDEX,
Expand Down Expand Up @@ -255,6 +256,7 @@ describe('searchAfterAndBulkCreate', () => {
exceptionsList: [exceptionItem],
services: mockService,
logger: mockLogger,
eventsTelemetry: undefined,
id: sampleRuleGuid,
inputIndexPattern,
signalsIndex: DEFAULT_SIGNALS_INDEX,
Expand Down Expand Up @@ -334,6 +336,7 @@ describe('searchAfterAndBulkCreate', () => {
exceptionsList: [exceptionItem],
services: mockService,
logger: mockLogger,
eventsTelemetry: undefined,
id: sampleRuleGuid,
inputIndexPattern,
signalsIndex: DEFAULT_SIGNALS_INDEX,
Expand Down Expand Up @@ -394,6 +397,7 @@ describe('searchAfterAndBulkCreate', () => {
exceptionsList: [exceptionItem],
services: mockService,
logger: mockLogger,
eventsTelemetry: undefined,
id: sampleRuleGuid,
inputIndexPattern,
signalsIndex: DEFAULT_SIGNALS_INDEX,
Expand Down Expand Up @@ -452,6 +456,7 @@ describe('searchAfterAndBulkCreate', () => {
exceptionsList: [exceptionItem],
services: mockService,
logger: mockLogger,
eventsTelemetry: undefined,
id: sampleRuleGuid,
inputIndexPattern,
signalsIndex: DEFAULT_SIGNALS_INDEX,
Expand Down Expand Up @@ -535,6 +540,7 @@ describe('searchAfterAndBulkCreate', () => {
exceptionsList: [exceptionItem],
services: mockService,
logger: mockLogger,
eventsTelemetry: undefined,
id: sampleRuleGuid,
inputIndexPattern,
signalsIndex: DEFAULT_SIGNALS_INDEX,
Expand Down Expand Up @@ -615,6 +621,7 @@ describe('searchAfterAndBulkCreate', () => {
exceptionsList: [],
services: mockService,
logger: mockLogger,
eventsTelemetry: undefined,
id: sampleRuleGuid,
inputIndexPattern,
signalsIndex: DEFAULT_SIGNALS_INDEX,
Expand Down Expand Up @@ -664,6 +671,7 @@ describe('searchAfterAndBulkCreate', () => {
ruleParams: sampleParams,
services: mockService,
logger: mockLogger,
eventsTelemetry: undefined,
id: sampleRuleGuid,
inputIndexPattern,
signalsIndex: DEFAULT_SIGNALS_INDEX,
Expand Down Expand Up @@ -719,6 +727,7 @@ describe('searchAfterAndBulkCreate', () => {
ruleParams: sampleParams,
services: mockService,
logger: mockLogger,
eventsTelemetry: undefined,
id: sampleRuleGuid,
inputIndexPattern,
signalsIndex: DEFAULT_SIGNALS_INDEX,
Expand Down Expand Up @@ -790,6 +799,7 @@ describe('searchAfterAndBulkCreate', () => {
ruleParams: sampleParams,
services: mockService,
logger: mockLogger,
eventsTelemetry: undefined,
id: sampleRuleGuid,
inputIndexPattern,
signalsIndex: DEFAULT_SIGNALS_INDEX,
Expand Down Expand Up @@ -898,6 +908,7 @@ describe('searchAfterAndBulkCreate', () => {
exceptionsList: [],
services: mockService,
logger: mockLogger,
eventsTelemetry: undefined,
id: sampleRuleGuid,
inputIndexPattern,
signalsIndex: DEFAULT_SIGNALS_INDEX,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import { singleSearchAfter } from './single_search_after';
import { singleBulkCreate } from './single_bulk_create';
import { filterEventsAgainstList } from './filter_events_with_list';
import { sendAlertTelemetryEvents } from './send_telemetry_events';
import {
createSearchAfterReturnType,
createSearchAfterReturnTypeFromResponse,
Expand All @@ -25,6 +26,7 @@ export const searchAfterAndBulkCreate = async ({
services,
listClient,
logger,
eventsTelemetry,
id,
inputIndexPattern,
signalsIndex,
Expand Down Expand Up @@ -188,6 +190,14 @@ export const searchAfterAndBulkCreate = async ({
logger.debug(
buildRuleMessage(`filteredEvents.hits.hits: ${filteredEvents.hits.hits.length}`)
);

sendAlertTelemetryEvents(
logger,
eventsTelemetry,
filteredEvents,
ruleParams,
buildRuleMessage
);
}

// we are guaranteed to have searchResult hits at this point
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { selectEvents } from './send_telemetry_events';

describe('sendAlertTelemetry', () => {
it('selectEvents', () => {
const filteredEvents = {
took: 0,
timed_out: false,
_shards: {
total: 1,
successful: 1,
failed: 0,
skipped: 0,
},
hits: {
total: 2,
max_score: 0,
hits: [
{
_index: 'x',
_type: 'x',
_id: 'x',
_score: 0,
_source: {
'@timestamp': 'x',
key1: 'hello',
data_stream: {
dataset: 'endpoint.events',
},
},
},
{
_index: 'x',
_type: 'x',
_id: 'x',
_score: 0,
_source: {
'@timestamp': 'x',
key2: 'hello',
data_stream: {
dataset: 'endpoint.alerts',
other: 'x',
},
},
},
{
_index: 'x',
_type: 'x',
_id: 'x',
_score: 0,
_source: {
'@timestamp': 'x',
key3: 'hello',
data_stream: {},
},
},
],
},
};

const sources = selectEvents(filteredEvents);
expect(sources).toStrictEqual([
{
'@timestamp': 'x',
key2: 'hello',
data_stream: {
dataset: 'endpoint.alerts',
other: 'x',
},
},
]);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { TelemetryEventsSender, TelemetryEvent } from '../../telemetry/sender';
import { RuleTypeParams } from '../types';
import { BuildRuleMessage } from './rule_messages';
import { SignalSearchResponse, SignalSource } from './types';
import { Logger } from '../../../../../../../src/core/server';

export interface SearchResultWithSource {
_source: SignalSource;
}

export function selectEvents(filteredEvents: SignalSearchResponse): TelemetryEvent[] {
const sources = filteredEvents.hits.hits.map(function (
obj: SearchResultWithSource
): TelemetryEvent {
return obj._source;
});

// Filter out non-endpoint alerts
return sources.filter((obj: TelemetryEvent) => obj.data_stream?.dataset === 'endpoint.alerts');
}

export function sendAlertTelemetryEvents(
logger: Logger,
eventsTelemetry: TelemetryEventsSender | undefined,
filteredEvents: SignalSearchResponse,
ruleParams: RuleTypeParams,
buildRuleMessage: BuildRuleMessage
) {
if (eventsTelemetry === undefined) {
return;
}

const sources = selectEvents(filteredEvents);

try {
eventsTelemetry.queueTelemetryEvents(sources);
} catch (exc) {
logger.error(buildRuleMessage(`[-] queing telemetry events failed ${exc}`));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ describe('rules_notification_alert_type', () => {

alert = signalRulesAlertType({
logger,
eventsTelemetry: undefined,
version,
ml: mlMock,
lists: listMock.createSetup(),
Expand Down Expand Up @@ -344,6 +345,7 @@ describe('rules_notification_alert_type', () => {
payload = getPayload(ruleAlert, alertServices) as jest.Mocked<RuleExecutorOptions>;
alert = signalRulesAlertType({
logger,
eventsTelemetry: undefined,
version,
ml: undefined,
lists: undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,21 @@ import { ruleStatusServiceFactory } from './rule_status_service';
import { buildRuleMessageFactory } from './rule_messages';
import { ruleStatusSavedObjectsClientFactory } from './rule_status_saved_objects_client';
import { getNotificationResultsLink } from '../notifications/utils';
import { TelemetryEventsSender } from '../../telemetry/sender';
import { buildEqlSearchRequest } from '../../../../common/detection_engine/get_query_filter';
import { bulkInsertSignals } from './single_bulk_create';
import { buildSignalFromEvent, buildSignalGroupFromSequence } from './build_bulk_body';
import { createThreatSignals } from './threat_mapping/create_threat_signals';

export const signalRulesAlertType = ({
logger,
eventsTelemetry,
version,
ml,
lists,
}: {
logger: Logger;
eventsTelemetry: TelemetryEventsSender | undefined;
version: string;
ml: SetupPlugins['ml'];
lists: SetupPlugins['lists'] | undefined;
Expand Down Expand Up @@ -369,6 +372,7 @@ export const signalRulesAlertType = ({
previousStartedAt,
listClient,
logger,
eventsTelemetry,
alertId,
outputIndex,
params,
Expand Down Expand Up @@ -409,6 +413,7 @@ export const signalRulesAlertType = ({
ruleParams: params,
services,
logger,
eventsTelemetry,
id: alertId,
inputIndexPattern: inputIndex,
signalsIndex: outputIndex,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export const createThreatSignal = async ({
previousStartedAt,
listClient,
logger,
eventsTelemetry,
alertId,
outputIndex,
params,
Expand Down Expand Up @@ -77,6 +78,7 @@ export const createThreatSignal = async ({
ruleParams: params,
services,
logger,
eventsTelemetry,
id: alertId,
inputIndexPattern: inputIndex,
signalsIndex: outputIndex,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export const createThreatSignals = async ({
previousStartedAt,
listClient,
logger,
eventsTelemetry,
alertId,
outputIndex,
params,
Expand Down Expand Up @@ -79,6 +80,7 @@ export const createThreatSignals = async ({
previousStartedAt,
listClient,
logger,
eventsTelemetry,
alertId,
outputIndex,
params,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { AlertServices } from '../../../../../../alerts/server';
import { ExceptionListItemSchema } from '../../../../../../lists/common/schemas';
import { ILegacyScopedClusterClient, Logger } from '../../../../../../../../src/core/server';
import { RuleAlertAction } from '../../../../../common/detection_engine/types';
import { TelemetryEventsSender } from '../../../telemetry/sender';
import { BuildRuleMessage } from '../rule_messages';
import { SearchAfterAndBulkCreateReturnType } from '../types';

Expand All @@ -38,6 +39,7 @@ export interface CreateThreatSignalsOptions {
previousStartedAt: Date | null;
listClient: ListClient;
logger: Logger;
eventsTelemetry: TelemetryEventsSender | undefined;
alertId: string;
outputIndex: string;
params: RuleTypeParams;
Expand Down Expand Up @@ -73,6 +75,7 @@ export interface CreateThreatSignalOptions {
previousStartedAt: Date | null;
listClient: ListClient;
logger: Logger;
eventsTelemetry: TelemetryEventsSender | undefined;
alertId: string;
outputIndex: string;
params: RuleTypeParams;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { ListClient } from '../../../../../lists/server';
import { Logger } from '../../../../../../../src/core/server';
import { ExceptionListItemSchema } from '../../../../../lists/common/schemas';
import { BuildRuleMessage } from './rule_messages';
import { TelemetryEventsSender } from '../../telemetry/sender';

// used for gap detection code
// eslint-disable-next-line @typescript-eslint/naming-convention
Expand Down Expand Up @@ -211,6 +212,7 @@ export interface SearchAfterAndBulkCreateParams {
listClient: ListClient;
exceptionsList: ExceptionListItemSchema[];
logger: Logger;
eventsTelemetry: TelemetryEventsSender | undefined;
id: string;
inputIndexPattern: string[];
signalsIndex: string;
Expand Down
Loading