[Security Solution][Detections] Update telemetry to use ML contract (#71665)

* 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.
This commit is contained in:
Ryland Herrick 2020-07-14 14:20:24 -05:00 committed by GitHub
parent 513d0e09e1
commit 9e2ebe2040
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 31 additions and 33 deletions

View file

@ -13,6 +13,7 @@ import { TypeOf } from '@kbn/config-schema';
import { DataRecognizer } from '../../models/data_recognizer'; import { DataRecognizer } from '../../models/data_recognizer';
import { SharedServicesChecks } from '../shared_services'; import { SharedServicesChecks } from '../shared_services';
import { moduleIdParamSchema, setupModuleBodySchema } from '../../routes/schemas/modules'; import { moduleIdParamSchema, setupModuleBodySchema } from '../../routes/schemas/modules';
import { HasMlCapabilities } from '../../lib/capabilities';
export type ModuleSetupPayload = TypeOf<typeof moduleIdParamSchema> & export type ModuleSetupPayload = TypeOf<typeof moduleIdParamSchema> &
TypeOf<typeof setupModuleBodySchema>; TypeOf<typeof setupModuleBodySchema>;
@ -40,8 +41,14 @@ export function getModulesProvider({
request: KibanaRequest, request: KibanaRequest,
savedObjectsClient: SavedObjectsClientContract 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); const dr = dataRecognizerFactory(mlClusterClient, savedObjectsClient, request);
return { return {
async recognize(...args) { async recognize(...args) {
isFullLicense(); isFullLicense();

View file

@ -16,6 +16,8 @@ const createMockMlSystemProvider = () =>
export const mlServicesMock = { export const mlServicesMock = {
create: () => create: () =>
(({ (({
modulesProvider: jest.fn(),
jobServiceProvider: jest.fn(),
mlSystemProvider: createMockMlSystemProvider(), mlSystemProvider: createMockMlSystemProvider(),
mlClient: createMockClient(), mlClient: createMockClient(),
} as unknown) as jest.Mocked<MlPluginSetup>), } as unknown) as jest.Mocked<MlPluginSetup>),

View file

@ -6,8 +6,6 @@
import { LegacyAPICaller } from '../../../../../../src/core/server'; import { LegacyAPICaller } from '../../../../../../src/core/server';
import { elasticsearchServiceMock } from '../../../../../../src/core/server/mocks'; 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 { mlServicesMock } from '../../lib/machine_learning/mocks';
import { import {
getMockJobSummaryResponse, getMockJobSummaryResponse,
@ -16,9 +14,6 @@ import {
} from './detections.mocks'; } from './detections.mocks';
import { fetchDetectionsUsage } from './index'; import { fetchDetectionsUsage } from './index';
jest.mock('../../../../ml/server/models/job_service');
jest.mock('../../../../ml/server/models/data_recognizer');
describe('Detections Usage', () => { describe('Detections Usage', () => {
describe('fetchDetectionsUsage()', () => { describe('fetchDetectionsUsage()', () => {
let callClusterMock: jest.Mocked<LegacyAPICaller>; let callClusterMock: jest.Mocked<LegacyAPICaller>;
@ -79,12 +74,12 @@ describe('Detections Usage', () => {
it('tallies jobs data given jobs results', async () => { it('tallies jobs data given jobs results', async () => {
const mockJobSummary = jest.fn().mockResolvedValue(getMockJobSummaryResponse()); const mockJobSummary = jest.fn().mockResolvedValue(getMockJobSummaryResponse());
const mockListModules = jest.fn().mockResolvedValue(getMockListModulesResponse()); const mockListModules = jest.fn().mockResolvedValue(getMockListModulesResponse());
(jobServiceProvider as jest.Mock).mockImplementation(() => ({ mlMock.modulesProvider.mockReturnValue(({
jobsSummary: mockJobSummary,
}));
(DataRecognizer as jest.Mock).mockImplementation(() => ({
listModules: mockListModules, listModules: mockListModules,
})); } as unknown) as ReturnType<typeof mlMock.modulesProvider>);
mlMock.jobServiceProvider.mockReturnValue({
jobsSummary: mockJobSummary,
});
const result = await fetchDetectionsUsage('', callClusterMock, mlMock); const result = await fetchDetectionsUsage('', callClusterMock, mlMock);

View file

@ -5,13 +5,12 @@
*/ */
import { SearchParams } from 'elasticsearch'; import { SearchParams } from 'elasticsearch';
import { ILegacyScopedClusterClient, KibanaRequest } from 'kibana/server';
import { LegacyAPICaller, SavedObjectsClient } from '../../../../../../src/core/server'; import {
// eslint-disable-next-line @kbn/eslint/no-restricted-paths LegacyAPICaller,
import { jobServiceProvider } from '../../../../ml/server/models/job_service'; SavedObjectsClient,
// eslint-disable-next-line @kbn/eslint/no-restricted-paths KibanaRequest,
import { DataRecognizer } from '../../../../ml/server/models/data_recognizer'; } from '../../../../../../src/core/server';
import { MlPluginSetup } from '../../../../ml/server'; import { MlPluginSetup } from '../../../../ml/server';
import { SIGNALS_ID, INTERNAL_IMMUTABLE_KEY } from '../../../common/constants'; import { SIGNALS_ID, INTERNAL_IMMUTABLE_KEY } from '../../../common/constants';
import { DetectionRulesUsage, MlJobsUsage } from './index'; import { DetectionRulesUsage, MlJobsUsage } from './index';
@ -164,25 +163,20 @@ export const getRulesUsage = async (
export const getMlJobsUsage = async (ml: MlPluginSetup | undefined): Promise<MlJobsUsage> => { export const getMlJobsUsage = async (ml: MlPluginSetup | undefined): Promise<MlJobsUsage> => {
let jobsUsage: MlJobsUsage = initialMlJobsUsage; 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) { if (ml) {
try { try {
const modules = await new DataRecognizer( const fakeRequest = { headers: {}, params: 'DummyKibanaRequest' } as KibanaRequest;
fakeScopedClusterClient, const fakeSOClient = {} as SavedObjectsClient;
fakeSavedObjectsClient, const internalMlClient = {
fakeRequest callAsCurrentUser: ml?.mlClient.callAsInternalUser,
).listModules(); callAsInternalUser: ml?.mlClient.callAsInternalUser,
};
const modules = await ml
.modulesProvider(internalMlClient, fakeRequest, fakeSOClient)
.listModules();
const moduleJobs = modules.flatMap((module) => module.jobs); 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) => { jobsUsage = jobs.reduce((usage, job) => {
const isElastic = moduleJobs.some((moduleJob) => moduleJob.id === job.id); const isElastic = moduleJobs.some((moduleJob) => moduleJob.id === job.id);