Skip to content

Commit

Permalink
[Security Solution][Detections] Update telemetry to use ML contract (#…
Browse files Browse the repository at this point in the history
…71665) (#71733)

* Update security solution telemetry to use ML providers

This interface recently changed and we're now able to use the ML
contract to retrieve these values. A few unnecessary arguments are
stubbed as we're in a non-user, non-request context.

* Simplify our capabilities stub assignment

This is more legible but still gets the point across; the intermediate
variable was explicit but ultimately unnnecessary.

* Update tests following telemetry refactor

We're not calling different methods, so our mocks need to change
slightly.
  • Loading branch information
rylnd authored Jul 14, 2020
1 parent 65fae1d commit 6548f34
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { TypeOf } from '@kbn/config-schema';
import { DataRecognizer } from '../../models/data_recognizer';
import { SharedServicesChecks } from '../shared_services';
import { moduleIdParamSchema, setupModuleBodySchema } from '../../routes/schemas/modules';
import { HasMlCapabilities } from '../../lib/capabilities';

export type ModuleSetupPayload = TypeOf<typeof moduleIdParamSchema> &
TypeOf<typeof setupModuleBodySchema>;
Expand Down Expand Up @@ -40,8 +41,14 @@ export function getModulesProvider({
request: KibanaRequest,
savedObjectsClient: SavedObjectsClientContract
) {
const hasMlCapabilities = getHasMlCapabilities(request);
let hasMlCapabilities: HasMlCapabilities;
if (request.params === 'DummyKibanaRequest') {
hasMlCapabilities = () => Promise.resolve();
} else {
hasMlCapabilities = getHasMlCapabilities(request);
}
const dr = dataRecognizerFactory(mlClusterClient, savedObjectsClient, request);

return {
async recognize(...args) {
isFullLicense();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ const createMockMlSystemProvider = () =>
export const mlServicesMock = {
create: () =>
(({
modulesProvider: jest.fn(),
jobServiceProvider: jest.fn(),
mlSystemProvider: createMockMlSystemProvider(),
mlClient: createMockClient(),
} as unknown) as jest.Mocked<MlPluginSetup>),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,6 @@

import { LegacyAPICaller } from '../../../../../../src/core/server';
import { elasticsearchServiceMock } from '../../../../../../src/core/server/mocks';
import { jobServiceProvider } from '../../../../ml/server/models/job_service';
import { DataRecognizer } from '../../../../ml/server/models/data_recognizer';
import { mlServicesMock } from '../../lib/machine_learning/mocks';
import {
getMockJobSummaryResponse,
Expand All @@ -16,9 +14,6 @@ import {
} from './detections.mocks';
import { fetchDetectionsUsage } from './index';

jest.mock('../../../../ml/server/models/job_service');
jest.mock('../../../../ml/server/models/data_recognizer');

describe('Detections Usage', () => {
describe('fetchDetectionsUsage()', () => {
let callClusterMock: jest.Mocked<LegacyAPICaller>;
Expand Down Expand Up @@ -79,12 +74,12 @@ describe('Detections Usage', () => {
it('tallies jobs data given jobs results', async () => {
const mockJobSummary = jest.fn().mockResolvedValue(getMockJobSummaryResponse());
const mockListModules = jest.fn().mockResolvedValue(getMockListModulesResponse());
(jobServiceProvider as jest.Mock).mockImplementation(() => ({
jobsSummary: mockJobSummary,
}));
(DataRecognizer as jest.Mock).mockImplementation(() => ({
mlMock.modulesProvider.mockReturnValue(({
listModules: mockListModules,
}));
} as unknown) as ReturnType<typeof mlMock.modulesProvider>);
mlMock.jobServiceProvider.mockReturnValue({
jobsSummary: mockJobSummary,
});

const result = await fetchDetectionsUsage('', callClusterMock, mlMock);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,12 @@
*/

import { SearchParams } from 'elasticsearch';
import { ILegacyScopedClusterClient, KibanaRequest } from 'kibana/server';

import { LegacyAPICaller, SavedObjectsClient } from '../../../../../../src/core/server';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { jobServiceProvider } from '../../../../ml/server/models/job_service';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { DataRecognizer } from '../../../../ml/server/models/data_recognizer';
import {
LegacyAPICaller,
SavedObjectsClient,
KibanaRequest,
} from '../../../../../../src/core/server';
import { MlPluginSetup } from '../../../../ml/server';
import { SIGNALS_ID, INTERNAL_IMMUTABLE_KEY } from '../../../common/constants';
import { DetectionRulesUsage, MlJobsUsage } from './index';
Expand Down Expand Up @@ -164,25 +163,20 @@ export const getRulesUsage = async (
export const getMlJobsUsage = async (ml: MlPluginSetup | undefined): Promise<MlJobsUsage> => {
let jobsUsage: MlJobsUsage = initialMlJobsUsage;

// Fake objects to be passed to ML functions.
// TODO - These ML functions should come from ML's setup contract
// and not be imported directly.
const fakeScopedClusterClient = {
callAsCurrentUser: ml?.mlClient.callAsInternalUser,
callAsInternalUser: ml?.mlClient.callAsInternalUser,
} as ILegacyScopedClusterClient;
const fakeSavedObjectsClient = {} as SavedObjectsClient;
const fakeRequest = {} as KibanaRequest;

if (ml) {
try {
const modules = await new DataRecognizer(
fakeScopedClusterClient,
fakeSavedObjectsClient,
fakeRequest
).listModules();
const fakeRequest = { headers: {}, params: 'DummyKibanaRequest' } as KibanaRequest;
const fakeSOClient = {} as SavedObjectsClient;
const internalMlClient = {
callAsCurrentUser: ml?.mlClient.callAsInternalUser,
callAsInternalUser: ml?.mlClient.callAsInternalUser,
};

const modules = await ml
.modulesProvider(internalMlClient, fakeRequest, fakeSOClient)
.listModules();
const moduleJobs = modules.flatMap((module) => module.jobs);
const jobs = await jobServiceProvider(fakeScopedClusterClient).jobsSummary(['siem']);
const jobs = await ml.jobServiceProvider(internalMlClient, fakeRequest).jobsSummary(['siem']);

jobsUsage = jobs.reduce((usage, job) => {
const isElastic = moduleJobs.some((moduleJob) => moduleJob.id === job.id);
Expand Down

0 comments on commit 6548f34

Please sign in to comment.