[Security Solution] Endpoint/Prebuilt Alert Counter (#136557)

* alert counter

* stub telemetry usage

* accurate count

* accurate count for mock

* handle edge case when agg is undefined

* [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix'

* clarify counter name

* linting errors for mock data

* [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix'

* linting

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
JD Kurma 2022-07-25 16:01:04 -04:00 committed by GitHub
parent 242c91a432
commit 45db88e0e6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 3437 additions and 4 deletions

View file

@ -14,6 +14,7 @@ import type { SecurityTelemetryTaskConfig } from '../task';
import type { PackagePolicy } from '@kbn/fleet-plugin/common/types/models/package_policy';
import { stubEndpointAlertResponse, stubProcessTree, stubFetchTimelineEvents } from './timeline';
import { stubEndpointMetricsResponse } from './metrics';
import { prebuiltRuleAlertsResponse } from './prebuilt_rule_alerts';
export const createMockTelemetryEventsSender = (
enableTelemetry?: boolean,
@ -85,6 +86,7 @@ export const createMockTelemetryReceiver = (
fetchDiagnosticAlerts: jest.fn().mockReturnValue(diagnosticsAlert ?? jest.fn()),
fetchEndpointMetrics: jest.fn().mockReturnValue(stubEndpointMetricsResponse),
fetchEndpointPolicyResponses: jest.fn(),
fetchPrebuiltRuleAlerts: jest.fn().mockReturnValue(prebuiltRuleAlertsResponse),
fetchTrustedApplications: jest.fn(),
fetchEndpointList: jest.fn(),
fetchDetectionRules: jest.fn().mockReturnValue({ body: null }),

View file

@ -284,6 +284,11 @@ export const stubEndpointAlertResponse = () => {
},
],
},
aggregations: {
endpoint_alert_count: {
value: 1,
},
},
};
};

View file

@ -142,7 +142,7 @@ export interface ITelemetryReceiver {
type: string;
};
fetchPrebuiltRuleAlerts(): Promise<TelemetryEvent[]>;
fetchPrebuiltRuleAlerts(): Promise<{ events: TelemetryEvent[]; count: number }>;
fetchTimelineEndpointAlerts(
interval: number
@ -650,6 +650,13 @@ export class TelemetryReceiver implements ITelemetryReceiver {
],
},
},
aggs: {
prebuilt_rule_alert_count: {
cardinality: {
field: 'event.id',
},
},
},
},
};
@ -660,7 +667,11 @@ export class TelemetryReceiver implements ITelemetryReceiver {
h._source != null ? ([h._source] as TelemetryEvent[]) : []
);
return telemetryEvents;
const aggregations = response.body?.aggregations as unknown as {
prebuilt_rule_alert_count: { value: number };
};
return { events: telemetryEvents, count: aggregations?.prebuilt_rule_alert_count.value ?? 0 };
}
public async fetchTimelineEndpointAlerts(interval: number) {
@ -710,6 +721,13 @@ export class TelemetryReceiver implements ITelemetryReceiver {
],
},
},
aggs: {
endpoint_alert_count: {
cardinality: {
field: 'event.id',
},
},
},
},
};

View file

@ -8,6 +8,12 @@
import { loggingSystemMock } from '@kbn/core/server/mocks';
import { createTelemetryPrebuiltRuleAlertsTaskConfig } from './prebuilt_rule_alerts';
import { createMockTelemetryEventsSender, createMockTelemetryReceiver } from '../__mocks__';
import { usageCountersServiceMock } from '@kbn/usage-collection-plugin/server/usage_counters/usage_counters_service.mock';
const usageCountersServiceSetup = usageCountersServiceMock.createSetupContract();
const telemetryUsageCounter = usageCountersServiceSetup.createUsageCounter(
'testTelemetryUsageCounter'
);
describe('security telemetry - detection rule alerts task test', () => {
let logger: ReturnType<typeof loggingSystemMock.createLogger>;
@ -22,6 +28,9 @@ describe('security telemetry - detection rule alerts task test', () => {
current: new Date().toISOString(),
};
const mockTelemetryEventsSender = createMockTelemetryEventsSender();
mockTelemetryEventsSender.getTelemetryUsageCluster = jest
.fn()
.mockReturnValue(telemetryUsageCounter);
const mockTelemetryReceiver = createMockTelemetryReceiver();
const telemetryDetectionRuleAlertsTaskConfig = createTelemetryPrebuiltRuleAlertsTaskConfig(1);
@ -32,5 +41,11 @@ describe('security telemetry - detection rule alerts task test', () => {
mockTelemetryEventsSender,
testTaskExecutionPeriod
);
expect(mockTelemetryReceiver.fetchPrebuiltRuleAlerts).toHaveBeenCalled();
expect(mockTelemetryEventsSender.getTelemetryUsageCluster).toHaveBeenCalled();
expect(mockTelemetryEventsSender.getTelemetryUsageCluster()?.incrementCounter).toBeCalledTimes(
1
);
expect(mockTelemetryEventsSender.sendOnDemand).toHaveBeenCalled();
});
});

View file

@ -43,7 +43,15 @@ export function createTelemetryPrebuiltRuleAlertsTaskConfig(maxTelemetryBatch: n
? licenseInfoPromise.value
: ({} as ESLicense | undefined);
const telemetryEvents = await receiver.fetchPrebuiltRuleAlerts();
const { events: telemetryEvents, count: totalPrebuiltAlertCount } =
await receiver.fetchPrebuiltRuleAlerts();
sender.getTelemetryUsageCluster()?.incrementCounter({
counterName: 'telemetry_prebuilt_rule_alerts',
counterType: 'prebuilt_alert_count',
incrementBy: totalPrebuiltAlertCount,
});
if (telemetryEvents.length === 0) {
logger.debug('no prebuilt rule alerts retrieved');
return 0;

View file

@ -68,8 +68,16 @@ export function createTelemetryTimelineTaskConfig() {
const endpointAlerts = await receiver.fetchTimelineEndpointAlerts(3);
// No EP Alerts -> Nothing to do
const aggregations = endpointAlerts?.aggregations as unknown as {
endpoint_alert_count: { value: number };
};
sender.getTelemetryUsageCluster()?.incrementCounter({
counterName: 'telemetry_endpoint_alert',
counterType: 'endpoint_alert_count',
incrementBy: aggregations?.endpoint_alert_count.value,
});
// No EP Alerts -> Nothing to do
if (
endpointAlerts.hits.hits?.length === 0 ||
endpointAlerts.hits.hits?.length === undefined