Filter out non-security jobs when collecting Detections telemetry (#74456)

Our jobs summary call returns all installed jobs regardless of group;
passing groups as jobIds does not perform group filtering.

This adds a helper predicate function on which to filter these results,
and updates tests accordingly.
This commit is contained in:
Ryland Herrick 2020-08-05 18:55:23 -05:00 committed by GitHub
parent dfad75ff1a
commit f5c9aa8860
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 65 additions and 5 deletions

View file

@ -140,6 +140,13 @@ export const UNAUTHENTICATED_USER = 'Unauthenticated';
*/
export const MINIMUM_ML_LICENSE = 'platinum';
/*
Machine Learning constants
*/
export const ML_GROUP_ID = 'security';
export const LEGACY_ML_GROUP_ID = 'siem';
export const ML_GROUP_IDS = [ML_GROUP_ID, LEGACY_ML_GROUP_ID];
/*
Rule notifications options
*/

View file

@ -0,0 +1,30 @@
/*
* 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 { MlSummaryJob } from '../../../ml/common/types/anomaly_detection_jobs';
import { isSecurityJob } from './is_security_job';
describe('isSecurityJob', () => {
it('counts a job with a group of "siem"', () => {
const job = { groups: ['siem', 'other'] } as MlSummaryJob;
expect(isSecurityJob(job)).toEqual(true);
});
it('counts a job with a group of "security"', () => {
const job = { groups: ['security', 'other'] } as MlSummaryJob;
expect(isSecurityJob(job)).toEqual(true);
});
it('counts a job in both "security" and "siem"', () => {
const job = { groups: ['siem', 'security'] } as MlSummaryJob;
expect(isSecurityJob(job)).toEqual(true);
});
it('does not count a job in a related group', () => {
const job = { groups: ['auditbeat', 'process'] } as MlSummaryJob;
expect(isSecurityJob(job)).toEqual(false);
});
});

View file

@ -0,0 +1,11 @@
/*
* 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 { MlSummaryJob } from '../../../ml/common/types/anomaly_detection_jobs';
import { ML_GROUP_IDS } from '../constants';
export const isSecurityJob = (job: MlSummaryJob): boolean =>
job.groups.some((group) => ML_GROUP_IDS.includes(group));

View file

@ -41,7 +41,7 @@ export const getMockJobSummaryResponse = () => [
{
id: 'other_job',
description: 'a job that is custom',
groups: ['auditbeat', 'process'],
groups: ['auditbeat', 'process', 'security'],
processed_record_count: 0,
memory_status: 'ok',
jobState: 'closed',
@ -54,6 +54,19 @@ export const getMockJobSummaryResponse = () => [
{
id: 'another_job',
description: 'another job that is custom',
groups: ['auditbeat', 'process', 'security'],
processed_record_count: 0,
memory_status: 'ok',
jobState: 'opened',
hasDatafeed: true,
datafeedId: 'datafeed-another',
datafeedIndices: ['auditbeat-*'],
datafeedState: 'started',
isSingleMetricViewerJob: true,
},
{
id: 'irrelevant_job',
description: 'a non-security job',
groups: ['auditbeat', 'process'],
processed_record_count: 0,
memory_status: 'ok',

View file

@ -15,6 +15,7 @@ import { MlPluginSetup } from '../../../../ml/server';
import { SIGNALS_ID, INTERNAL_IMMUTABLE_KEY } from '../../../common/constants';
import { DetectionRulesUsage, MlJobsUsage } from './index';
import { isJobStarted } from '../../../common/machine_learning/helpers';
import { isSecurityJob } from '../../../common/machine_learning/is_security_job';
interface DetectionsMetric {
isElastic: boolean;
@ -182,11 +183,9 @@ export const getMlJobsUsage = async (ml: MlPluginSetup | undefined): Promise<MlJ
.modulesProvider(internalMlClient, fakeRequest, fakeSOClient)
.listModules();
const moduleJobs = modules.flatMap((module) => module.jobs);
const jobs = await ml
.jobServiceProvider(internalMlClient, fakeRequest)
.jobsSummary(['siem', 'security']);
const jobs = await ml.jobServiceProvider(internalMlClient, fakeRequest).jobsSummary();
jobsUsage = jobs.reduce((usage, job) => {
jobsUsage = jobs.filter(isSecurityJob).reduce((usage, job) => {
const isElastic = moduleJobs.some((moduleJob) => moduleJob.id === job.id);
const isEnabled = isJobStarted(job.jobState, job.datafeedState);