Saved Object Mapping for Entity Source Sync Configuration (#219680)

## Summary

This PR introduces a new Saved Object mapping for Monitoring Entity
Source Configurations to support Privileged User Monitoring.

###  Implemented
* Saved object mapping schema aligned with the [current
spec](https://docs.google.com/document/d/1-c6A82p2CCjYz8Mb6tL6R7BXXemQ4mpWZliKqki0SWo/edit?tab=t.0#heading=h.4axxr154e1lc)
* DescriptorClient to handle saved object methods
* OpenAPI schema and generated types
* Implemented Data Client - SO operations exposed via GET and POST API
* Created route and registered with privmonRoutes
* Data Client Unit Testing
* Rename typename of "monitoring_entity_source-sync" ->
"entity-analytics-monitoring-entity-source"

[Figma
](https://www.figma.com/board/yBr1pBDGu4JqNxb5ZrULtk/MonEntitySourceSyncTask?node-id=0-1&p=f&t=4hQaGsdvOpghi4QS-0)-
currently working in the pink box


## Testing Steps: 
1. privilegeMonitoringEnabled: true - set this flag
2. From Dev tools - create a saved object via POST (below) and view this
saved object via GET (also below):


```
POST kbn:/api/entity_analytics/monitoring/entity_source
{
  "type": "some-type-here",
  "name": "name-here",
  "managed": false,
  "indexPattern": "logs-*",
  "enabled": true,
  "integrationName": "Okta",
 "matchers": [
    {
      "fields": ["user.role"],
      "values": ["admin"]
    }
  ],
  "filter": {}
}

```
**Expected output:** 
``` 
{
  "type": "some-type-here",
  "name": "name-here",
  "managed": false,
  "indexPattern": "logs-*",
  "enabled": true,
  "integrationName": "Okta",
  "matchers": [
    {
      "fields": [
        "user.role"
      ],
      "values": [
        "admin"
      ]
    }
  ],
  "filter": {}
}
```
GET Example
```
GET kbn:/api/entity_analytics/monitoring/entity_source
```
Output for get, expected to be the same as that for POST.

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Charlotte Alexandra Wilson 2025-06-05 17:16:05 +01:00 committed by GitHub
parent cd02c54c74
commit a3de6d82ba
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 761 additions and 4 deletions

View file

@ -309,6 +309,19 @@
"schemaVersion"
],
"enterprise_search_telemetry": [],
"entity-analytics-monitoring-entity-source": [
"enabled",
"error",
"filter",
"indexPattern",
"integrationName",
"managed",
"matchers",
"matchers.fields",
"matchers.values",
"name",
"type"
],
"entity-definition": [
"description",
"filter",
@ -828,6 +841,19 @@
"job.job_id",
"model_id"
],
"monitoring-entity-source": [
"enabled",
"error",
"filter",
"indexPattern",
"integrationName",
"managed",
"matchers",
"matchers.fields",
"matchers.values",
"name",
"type"
],
"monitoring-telemetry": [
"reportedClusterUuids"
],

View file

@ -1059,6 +1059,37 @@
"dynamic": false,
"properties": {}
},
"entity-analytics-monitoring-entity-source": {
"dynamic": false,
"properties": {
"enabled": {
"type": "boolean"
},
"error": {
"type": "keyword"
},
"filter": {
"dynamic": false,
"type": "object"
},
"integrationName": {
"type": "keyword"
},
"managed": {
"type": "boolean"
},
"matchers": {
"dynamic": false,
"type": "object"
},
"name": {
"type": "keyword"
},
"type": {
"type": "keyword"
}
}
},
"entity-definition": {
"dynamic": false,
"properties": {

View file

@ -10,5 +10,5 @@
export { registerCoreObjectTypes } from './registration';
// set minimum number of registered saved objects to ensure no object types are removed after 8.8
// declared in internal implementation exclicilty to prevent unintended changes.
export const SAVED_OBJECT_TYPES_COUNT = 133 as const;
// declared in internal implementation explicitly to prevent unintended changes.
export const SAVED_OBJECT_TYPES_COUNT = 134 as const;

View file

@ -96,6 +96,7 @@ describe('checking migration metadata changes on all registered SO types', () =>
"endpoint:unified-user-artifact-manifest": "71c7fcb52c658b21ea2800a6b6a76972ae1c776e",
"endpoint:user-artifact-manifest": "1c3533161811a58772e30cdc77bac4631da3ef2b",
"enterprise_search_telemetry": "9ac912e1417fc8681e0cd383775382117c9e3d3d",
"entity-analytics-monitoring-entity-source": "207ca6f7ed3a04ebe33d81675a09e253446fe897",
"entity-definition": "1c6bff35c423d5dc5650bc806cf2899e4706a0bc",
"entity-discovery-api-key": "c267a65c69171d1804362155c1378365f5acef88",
"entity-engine-status": "09f6a617020708e4f638137e5ef35bd9534133be",

View file

@ -56,6 +56,7 @@ const previouslyRegisteredTypes = [
'endpoint:user-artifact-manifest',
'endpoint:unified-user-artifact-manifest',
'enterprise_search_telemetry',
'entity-analytics-monitoring-entity-source',
'entity-definition',
'entity-discovery-api-key',
'epm-packages',

View file

@ -0,0 +1,55 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
/*
* NOTICE: Do not edit this file manually.
* This file is automatically generated by the OpenAPI Generator, @kbn/openapi-generator.
*
* info:
* title: Monitoring Entity Source Schema
* version: 1
*/
import { z } from '@kbn/zod';
export type MonitoringEntitySourceDescriptor = z.infer<typeof MonitoringEntitySourceDescriptor>;
export const MonitoringEntitySourceDescriptor = z.object({
type: z.string(),
name: z.string(),
managed: z.boolean().optional(),
indexPattern: z.string().optional(),
enabled: z.boolean().optional(),
error: z.string().optional(),
integrationName: z.string().optional(),
matchers: z
.array(
z.object({
fields: z.array(z.string()),
values: z.array(z.string()),
})
)
.optional(),
filter: z.object({}).optional(),
});
export type MonitoringEntitySourceResponse = z.infer<typeof MonitoringEntitySourceResponse>;
export const MonitoringEntitySourceResponse = z.object({
id: z.string().optional(),
name: z.string().optional(),
type: z.string().optional(),
indexPattern: z.string().optional(),
integrationName: z.string().optional(),
enabled: z.boolean().optional(),
matchers: z
.array(
z.object({
fields: z.array(z.string()),
values: z.array(z.string()),
})
)
.optional(),
});

View file

@ -0,0 +1,145 @@
openapi: 3.0.0
info:
title: Monitoring Entity Source Schema
description: Schema for managing entity source configurations in the monitoring system.
version: "1"
paths:
/api/entity_analytics/monitoring/entity_source:
post:
operationId: createEntitySource
summary: Create a new entity source configuration
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/MonitoringEntitySourceDescriptor"
responses:
"200":
description: Entity source created successfully
content:
application/json:
schema:
$ref: "#/components/schemas/MonitoringEntitySourceResponse"
/api/entity_analytics/monitoring/entity_source/{id}:
get:
operationId: getEntitySource
summary: Get an entity source configuration by ID
parameters:
- name: id
in: path
required: true
schema:
type: string
responses:
"200":
description: Entity source details retrieved
content:
application/json:
schema:
$ref: "#/components/schemas/MonitoringEntitySourceResponse"
put:
operationId: updateEntitySource
summary: Update an entity source configuration
parameters:
- name: id
in: path
required: true
schema:
type: string
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/MonitoringEntitySourceDescriptor"
responses:
"200":
description: Entity source updated successfully
delete:
operationId: deleteEntitySource
summary: Delete an entity source configuration
parameters:
- name: id
in: path
required: true
schema:
type: string
responses:
"200":
description: Entity source deleted successfully
components:
schemas:
MonitoringEntitySourceDescriptor:
type: object
required: [type, name]
properties:
type:
type: string
name:
type: string
managed:
type: boolean
indexPattern:
type: string
enabled:
type: boolean
error:
type: string
integrationName:
type: string
matchers:
type: array
items:
type: object
required:
- fields
- values
properties:
fields:
type: array
items:
type: string
values:
type: array
items:
type: string
filter:
type: object
MonitoringEntitySourceResponse:
type: object
properties:
id:
type: string
name:
type: string
type:
type: string
indexPattern:
type: string
integrationName:
type: string
enabled:
type: boolean
matchers:
type: array
items:
type: object
required:
- fields
- values
properties:
fields:
type: array
items:
type: string
values:
type: array
items:
type: string

View file

@ -191,6 +191,7 @@ const createSecuritySolutionRequestContextMock = (
getEntityStoreApiKeyManager: jest.fn(),
getEntityStoreDataClient: jest.fn(() => clients.entityStoreDataClient),
getPrivilegeMonitoringDataClient: jest.fn(() => clients.privilegeMonitorDataClient),
getMonitoringEntitySourceDataClient: jest.fn(),
getSiemRuleMigrationsClient: jest.fn(() => clients.siemRuleMigrationsClient),
getInferenceClient: jest.fn(() => clients.getInferenceClient()),
getAssetInventoryClient: jest.fn(() => clients.assetInventoryDataClient),

View file

@ -0,0 +1,135 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { MonitoringEntitySourceDataClient } from './monitoring_entity_source_data_client';
import {
savedObjectsClientMock,
elasticsearchServiceMock,
loggingSystemMock,
} from '@kbn/core/server/mocks';
import { monitoringEntitySourceTypeName } from './saved_object/monitoring_entity_source_type';
import type { SavedObject, SavedObjectsFindResponse } from '@kbn/core/server';
describe('MonitoringEntitySourceDataClient', () => {
const mockSavedObjectClient = savedObjectsClientMock.create();
const clusterClientMock = elasticsearchServiceMock.createScopedClusterClient();
const loggerMock = loggingSystemMock.createLogger();
const namespace = 'test-namespace';
loggerMock.debug = jest.fn();
const defaultOpts = {
logger: loggerMock,
clusterClient: clusterClientMock,
namespace: 'test-namespace',
soClient: mockSavedObjectClient,
kibanaVersion: '8.0.0',
};
const testDescriptor = {
type: 'test-type',
name: 'Test Source',
matchers: [
{
fields: ['user.role'],
values: ['admin'],
},
],
filter: {},
};
let dataClient: MonitoringEntitySourceDataClient;
beforeEach(() => {
jest.clearAllMocks();
dataClient = new MonitoringEntitySourceDataClient(defaultOpts);
});
describe('init', () => {
it('should initialize Monitoring Entity Source Sync Config Successfully', async () => {
defaultOpts.soClient.find.mockResolvedValue({
total: 0,
saved_objects: [],
} as unknown as SavedObjectsFindResponse<unknown, unknown>);
defaultOpts.soClient.create.mockResolvedValue({
id: `entity-analytics-monitoring-entity-source-${namespace}`,
type: monitoringEntitySourceTypeName,
attributes: testDescriptor,
references: [],
});
const result = await dataClient.init(testDescriptor);
expect(defaultOpts.soClient.create).toHaveBeenCalledWith(
monitoringEntitySourceTypeName,
testDescriptor,
{ id: `entity-analytics-monitoring-entity-source-${namespace}` }
);
expect(result).toEqual(testDescriptor);
});
});
describe('get', () => {
it('should get Monitoring Entity Source Sync Config Successfully', async () => {
const getResponse = {
id: `entity-analytics-monitoring-entity-source-${namespace}`,
type: monitoringEntitySourceTypeName,
attributes: testDescriptor,
references: [],
};
defaultOpts.soClient.get.mockResolvedValue(getResponse as unknown as SavedObject<unknown>);
const result = await dataClient.get();
expect(defaultOpts.soClient.get).toHaveBeenCalledWith(
monitoringEntitySourceTypeName,
`entity-analytics-monitoring-entity-source-${namespace}`
);
expect(result).toEqual(getResponse.attributes);
});
});
describe('update', () => {
it('should update Monitoring Entity Source Sync Config Successfully', async () => {
const existingDescriptor = {
total: 1,
saved_objects: [{ attributes: testDescriptor }],
} as unknown as SavedObjectsFindResponse<unknown, unknown>;
defaultOpts.soClient.find.mockResolvedValue(
existingDescriptor as unknown as SavedObjectsFindResponse<unknown, unknown>
);
defaultOpts.soClient.update.mockResolvedValue({
id: `entity-analytics-monitoring-entity-source-${namespace}`,
type: monitoringEntitySourceTypeName,
attributes: { ...testDescriptor, name: 'Updated Source' },
references: [],
});
const updatedDescriptor = { ...testDescriptor, name: 'Updated Source' };
const result = await dataClient.init(testDescriptor);
expect(defaultOpts.soClient.update).toHaveBeenCalledWith(
monitoringEntitySourceTypeName,
`entity-analytics-monitoring-entity-source-${namespace}`,
testDescriptor,
{ refresh: 'wait_for' }
);
expect(result).toEqual(updatedDescriptor);
});
});
describe('delete', () => {
it('should delete Monitoring Entity Source Sync Config Successfully', async () => {
await dataClient.delete();
expect(mockSavedObjectClient.delete).toHaveBeenCalledWith(
monitoringEntitySourceTypeName,
`entity-analytics-monitoring-entity-source-${namespace}`
);
});
});
});

View file

@ -0,0 +1,68 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { IScopedClusterClient, Logger, SavedObjectsClientContract } from '@kbn/core/server';
import type {
MonitoringEntitySourceDescriptor,
MonitoringEntitySourceResponse,
} from '../../../../common/api/entity_analytics/privilege_monitoring/monitoring_entity_source/monitoring_entity_source.gen';
import { MonitoringEntitySourceDescriptorClient } from './saved_object/monitoring_entity_source';
interface MonitoringEntitySourceDataClientOpts {
logger: Logger;
clusterClient: IScopedClusterClient;
soClient: SavedObjectsClientContract;
namespace: string;
}
export class MonitoringEntitySourceDataClient {
private monitoringEntitySourceClient: MonitoringEntitySourceDescriptorClient;
constructor(private readonly opts: MonitoringEntitySourceDataClientOpts) {
this.monitoringEntitySourceClient = new MonitoringEntitySourceDescriptorClient({
soClient: this.opts.soClient,
namespace: this.opts.namespace,
});
}
public async init(
input: MonitoringEntitySourceDescriptor
): Promise<MonitoringEntitySourceResponse> {
const descriptor = await this.monitoringEntitySourceClient.create(input);
this.log('debug', 'Initializing MonitoringEntitySourceDataClient Saved Object');
return descriptor;
}
public async get(): Promise<MonitoringEntitySourceResponse> {
this.log('debug', 'Getting Monitoring Entity Source Sync saved object');
return this.monitoringEntitySourceClient.get();
}
public async update(update: Partial<MonitoringEntitySourceResponse>) {
this.log('debug', 'Updating Monitoring Entity Source Sync saved object');
const sanitizedUpdate = {
...update,
matchers: update.matchers?.map((matcher) => ({
fields: matcher.fields ?? [],
values: matcher.values ?? [],
})),
};
return this.monitoringEntitySourceClient.update(sanitizedUpdate);
}
public async delete() {
this.log('debug', 'Deleting Monitoring Entity Source Sync saved object');
return this.monitoringEntitySourceClient.delete();
}
private log(level: Exclude<keyof Logger, 'get' | 'log' | 'isLevelEnabled'>, msg: string) {
this.opts.logger[level](
`[Monitoring Entity Source Sync][namespace: ${this.opts.namespace}] ${msg}`
);
}
}

View file

@ -0,0 +1,103 @@
/* eslint-disable @kbn/eslint/require-license-header */
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { buildSiemResponse } from '@kbn/lists-plugin/server/routes/utils';
import { transformError } from '@kbn/securitysolution-es-utils';
import type { IKibanaResponse, Logger } from '@kbn/core/server';
import type { MonitoringEntitySourceResponse } from '../../../../../common/api/entity_analytics/privilege_monitoring/monitoring_entity_source/monitoring_entity_source.gen';
import { API_VERSIONS, APP_ID } from '../../../../../common/constants';
import type { EntityAnalyticsRoutesDeps } from '../../types';
import { MonitoringEntitySourceDescriptor } from '../../../../../common/api/entity_analytics/privilege_monitoring/monitoring_entity_source/monitoring_entity_source.gen';
export const monitoringEntitySourceRoute = (
router: EntityAnalyticsRoutesDeps['router'],
logger: Logger,
config: EntityAnalyticsRoutesDeps['config']
) => {
router.versioned
.post({
access: 'public',
path: '/api/entity_analytics/monitoring/entity_source',
security: {
authz: {
requiredPrivileges: ['securitySolution', `${APP_ID}-entity-analytics`],
},
},
})
.addVersion(
{
version: API_VERSIONS.public.v1,
validate: {
request: {
body: MonitoringEntitySourceDescriptor,
},
},
},
async (
context,
request,
response
): Promise<IKibanaResponse<MonitoringEntitySourceResponse>> => {
const siemResponse = buildSiemResponse(response);
try {
const secSol = await context.securitySolution;
const client = secSol.getMonitoringEntitySourceDataClient();
const body = await client.init(request.body);
return response.ok({ body });
} catch (e) {
const error = transformError(e);
logger.error(`Error creating monitoring entity source sync config: ${error.message}`);
return siemResponse.error({
statusCode: error.statusCode,
body: error.message,
});
}
}
);
router.versioned
.get({
access: 'public',
path: '/api/entity_analytics/monitoring/entity_source',
security: {
authz: {
requiredPrivileges: ['securitySolution', `${APP_ID}-entity-analytics`],
},
},
})
.addVersion(
{
version: API_VERSIONS.public.v1,
validate: {},
},
async (
context,
request,
response
): Promise<IKibanaResponse<MonitoringEntitySourceResponse>> => {
const siemResponse = buildSiemResponse(response);
try {
const secSol = await context.securitySolution;
const client = secSol.getMonitoringEntitySourceDataClient();
const body = await client.get();
return response.ok({ body });
} catch (e) {
const error = transformError(e);
logger.error(`Error getting monitoring entity source sync config: ${error.message}`);
return siemResponse.error({
statusCode: error.statusCode,
body: error.message,
});
}
}
);
};

View file

@ -8,6 +8,7 @@
import type { EntityAnalyticsRoutesDeps } from '../../types';
import { healthCheckPrivilegeMonitoringRoute } from './health';
import { initPrivilegeMonitoringEngineRoute } from './init';
import { monitoringEntitySourceRoute } from './monitoring_entity_source';
import { searchPrivilegeMonitoringIndicesRoute } from './search_indices';
import {
@ -28,6 +29,7 @@ export const registerPrivilegeMonitoringRoutes = ({
initPrivilegeMonitoringEngineRoute(router, logger, config);
healthCheckPrivilegeMonitoringRoute(router, logger, config);
searchPrivilegeMonitoringIndicesRoute(router, logger, config);
monitoringEntitySourceRoute(router, logger, config);
getUserRoute(router, logger);
createUserRoute(router, logger);
deleteUserRoute(router, logger);

View file

@ -0,0 +1,93 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { SavedObjectsClientContract } from '@kbn/core/server';
import { monitoringEntitySourceTypeName } from './monitoring_entity_source_type';
export interface MonitoringEntitySourceDependencies {
soClient: SavedObjectsClientContract;
namespace: string;
}
export interface MonitoringEntitySourceDescriptor {
type: string;
name: string;
managed?: boolean;
indexPattern?: string;
enabled?: boolean;
error?: string;
integrationName?: string;
matchers?: Array<{
fields: string[];
values: string[];
}>;
filter?: Record<string, unknown>;
}
export class MonitoringEntitySourceDescriptorClient {
constructor(private readonly dependencies: MonitoringEntitySourceDependencies) {}
getSavedObjectId() {
return `entity-analytics-monitoring-entity-source-${this.dependencies.namespace}`;
}
async create(attributes: MonitoringEntitySourceDescriptor) {
const entitySourceDescriptor = await this.find();
if (entitySourceDescriptor.total === 1) {
const { attributes: updated } =
await this.dependencies.soClient.update<MonitoringEntitySourceDescriptor>(
monitoringEntitySourceTypeName,
this.getSavedObjectId(),
attributes,
{ refresh: 'wait_for' }
);
return updated;
}
const { attributes: created } =
await this.dependencies.soClient.create<MonitoringEntitySourceDescriptor>(
monitoringEntitySourceTypeName,
attributes,
{ id: this.getSavedObjectId() }
);
return created;
}
async update(monitoringEntitySource: Partial<MonitoringEntitySourceDescriptor>) {
const id = this.getSavedObjectId();
const { attributes } =
await this.dependencies.soClient.update<MonitoringEntitySourceDescriptor>(
monitoringEntitySourceTypeName,
id,
monitoringEntitySource,
{ refresh: 'wait_for' }
);
return attributes;
}
async find() {
return this.dependencies.soClient.find<MonitoringEntitySourceDescriptor>({
type: monitoringEntitySourceTypeName,
namespaces: [this.dependencies.namespace],
});
}
async get() {
const id = this.getSavedObjectId();
const { attributes } = await this.dependencies.soClient.get<MonitoringEntitySourceDescriptor>(
monitoringEntitySourceTypeName,
id
);
return attributes;
}
async delete() {
const id = this.getSavedObjectId();
await this.dependencies.soClient.delete(monitoringEntitySourceTypeName, id);
}
}

View file

@ -0,0 +1,51 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import type { SavedObjectsType } from '@kbn/core/server';
import { SECURITY_SOLUTION_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server';
export const monitoringEntitySourceTypeName = 'entity-analytics-monitoring-entity-source';
export const monitoringEntitySourceTypeNameMappings: SavedObjectsType['mappings'] = {
dynamic: false,
properties: {
type: {
type: 'keyword',
},
name: {
type: 'keyword',
},
managed: {
type: 'boolean',
},
enabled: {
type: 'boolean',
},
error: {
type: 'keyword',
},
integrationName: {
type: 'keyword',
},
matchers: {
type: 'object',
dynamic: false,
},
filter: {
dynamic: false,
type: 'object',
},
},
};
export const monitoringEntitySourceType: SavedObjectsType = {
name: monitoringEntitySourceTypeName,
indexPattern: SECURITY_SOLUTION_SAVED_OBJECT_INDEX,
hidden: false,
namespaceType: 'multiple-isolated',
mappings: monitoringEntitySourceTypeNameMappings,
};

View file

@ -11,6 +11,7 @@ import type { KibanaRequest, Logger, RequestHandlerContext } from '@kbn/core/ser
import type { BuildFlavor } from '@kbn/config';
import { EntityDiscoveryApiKeyType } from '@kbn/entityManager-plugin/server/saved_objects';
import { MonitoringEntitySourceDataClient } from './lib/entity_analytics/privilege_monitoring/monitoring_entity_source_data_client';
import { DEFAULT_SPACE_ID } from '../common/constants';
import type { Immutable } from '../common/endpoint/types';
import type { EndpointAuthz } from '../common/endpoint/types/authz';
@ -255,7 +256,6 @@ export class RequestContextFactory implements IRequestContextFactory {
})
),
getPrivilegeMonitoringDataClient: memoize(() => {
// TODO:add soClient with ApiKeyType as with getEntityStoreDataClient
return new PrivilegeMonitoringDataClient({
logger: options.logger,
clusterClient: coreContext.elasticsearch.client,
@ -265,7 +265,14 @@ export class RequestContextFactory implements IRequestContextFactory {
auditLogger: getAuditLogger(),
kibanaVersion: options.kibanaVersion,
telemetry: core.analytics,
// TODO: add apiKeyManager
});
}),
getMonitoringEntitySourceDataClient: memoize(() => {
return new MonitoringEntitySourceDataClient({
logger: options.logger,
clusterClient: coreContext.elasticsearch.client,
namespace: getSpaceId(),
soClient: coreContext.savedObjects.client,
});
}),
getEntityStoreDataClient: memoize(() => {

View file

@ -18,6 +18,7 @@ import { manifestType, unifiedManifestType } from './endpoint/lib/artifacts/save
import { riskEngineConfigurationType } from './lib/entity_analytics/risk_engine/saved_object';
import { entityEngineDescriptorType } from './lib/entity_analytics/entity_store/saved_object';
import { privilegeMonitoringType } from './lib/entity_analytics/privilege_monitoring/saved_object/privilege_monitoring_type';
import { monitoringEntitySourceType } from './lib/entity_analytics/privilege_monitoring/saved_object/monitoring_entity_source_type';
const types = [
noteType,
@ -31,6 +32,7 @@ const types = [
riskEngineConfigurationType,
entityEngineDescriptorType,
privilegeMonitoringType,
monitoringEntitySourceType,
protectionUpdatesNoteType,
promptType,
];

View file

@ -43,6 +43,7 @@ import type { AssetInventoryDataClient } from './lib/asset_inventory/asset_inven
import type { PrivilegeMonitoringDataClient } from './lib/entity_analytics/privilege_monitoring/privilege_monitoring_data_client';
import type { ApiKeyManager } from './lib/entity_analytics/entity_store/auth/api_key';
import type { ProductFeaturesService } from './lib/product_features_service';
import type { MonitoringEntitySourceDataClient } from './lib/entity_analytics/privilege_monitoring/monitoring_entity_source_data_client';
export { AppClient };
export interface SecuritySolutionApiRequestHandlerContext {
@ -69,6 +70,7 @@ export interface SecuritySolutionApiRequestHandlerContext {
getAssetCriticalityDataClient: () => AssetCriticalityDataClient;
getEntityStoreDataClient: () => EntityStoreDataClient;
getPrivilegeMonitoringDataClient: () => PrivilegeMonitoringDataClient;
getMonitoringEntitySourceDataClient: () => MonitoringEntitySourceDataClient;
getSiemRuleMigrationsClient: () => SiemRuleMigrationsClient;
getInferenceClient: () => InferenceClient;
getAssetInventoryClient: () => AssetInventoryDataClient;

View file

@ -386,6 +386,18 @@ export default function ({ getService }: FtrProviderContext) {
"saved_object:privilege-monitoring-status/delete",
"saved_object:privilege-monitoring-status/bulk_delete",
"saved_object:privilege-monitoring-status/share_to_space",
"saved_object:entity-analytics-monitoring-entity-source/bulk_get",
"saved_object:entity-analytics-monitoring-entity-source/get",
"saved_object:entity-analytics-monitoring-entity-source/find",
"saved_object:entity-analytics-monitoring-entity-source/open_point_in_time",
"saved_object:entity-analytics-monitoring-entity-source/close_point_in_time",
"saved_object:entity-analytics-monitoring-entity-source/create",
"saved_object:entity-analytics-monitoring-entity-source/bulk_create",
"saved_object:entity-analytics-monitoring-entity-source/update",
"saved_object:entity-analytics-monitoring-entity-source/bulk_update",
"saved_object:entity-analytics-monitoring-entity-source/delete",
"saved_object:entity-analytics-monitoring-entity-source/bulk_delete",
"saved_object:entity-analytics-monitoring-entity-source/share_to_space",
"saved_object:policy-settings-protection-updates-note/bulk_get",
"saved_object:policy-settings-protection-updates-note/get",
"saved_object:policy-settings-protection-updates-note/find",
@ -1242,6 +1254,18 @@ export default function ({ getService }: FtrProviderContext) {
"saved_object:privilege-monitoring-status/delete",
"saved_object:privilege-monitoring-status/bulk_delete",
"saved_object:privilege-monitoring-status/share_to_space",
"saved_object:entity-analytics-monitoring-entity-source/bulk_get",
"saved_object:entity-analytics-monitoring-entity-source/get",
"saved_object:entity-analytics-monitoring-entity-source/find",
"saved_object:entity-analytics-monitoring-entity-source/open_point_in_time",
"saved_object:entity-analytics-monitoring-entity-source/close_point_in_time",
"saved_object:entity-analytics-monitoring-entity-source/create",
"saved_object:entity-analytics-monitoring-entity-source/bulk_create",
"saved_object:entity-analytics-monitoring-entity-source/update",
"saved_object:entity-analytics-monitoring-entity-source/bulk_update",
"saved_object:entity-analytics-monitoring-entity-source/delete",
"saved_object:entity-analytics-monitoring-entity-source/bulk_delete",
"saved_object:entity-analytics-monitoring-entity-source/share_to_space",
"saved_object:policy-settings-protection-updates-note/bulk_get",
"saved_object:policy-settings-protection-updates-note/get",
"saved_object:policy-settings-protection-updates-note/find",
@ -1869,6 +1893,11 @@ export default function ({ getService }: FtrProviderContext) {
"saved_object:privilege-monitoring-status/find",
"saved_object:privilege-monitoring-status/open_point_in_time",
"saved_object:privilege-monitoring-status/close_point_in_time",
"saved_object:entity-analytics-monitoring-entity-source/bulk_get",
"saved_object:entity-analytics-monitoring-entity-source/get",
"saved_object:entity-analytics-monitoring-entity-source/find",
"saved_object:entity-analytics-monitoring-entity-source/open_point_in_time",
"saved_object:entity-analytics-monitoring-entity-source/close_point_in_time",
"saved_object:policy-settings-protection-updates-note/bulk_get",
"saved_object:policy-settings-protection-updates-note/get",
"saved_object:policy-settings-protection-updates-note/find",
@ -2243,6 +2272,11 @@ export default function ({ getService }: FtrProviderContext) {
"saved_object:privilege-monitoring-status/find",
"saved_object:privilege-monitoring-status/open_point_in_time",
"saved_object:privilege-monitoring-status/close_point_in_time",
"saved_object:entity-analytics-monitoring-entity-source/bulk_get",
"saved_object:entity-analytics-monitoring-entity-source/get",
"saved_object:entity-analytics-monitoring-entity-source/find",
"saved_object:entity-analytics-monitoring-entity-source/open_point_in_time",
"saved_object:entity-analytics-monitoring-entity-source/close_point_in_time",
"saved_object:policy-settings-protection-updates-note/bulk_get",
"saved_object:policy-settings-protection-updates-note/get",
"saved_object:policy-settings-protection-updates-note/find",