[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:
parent
513d0e09e1
commit
9e2ebe2040
4 changed files with 31 additions and 33 deletions
|
@ -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();
|
||||||
|
|
|
@ -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>),
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in a new issue