Skip to content

Commit

Permalink
WIP for adjusting the find_by_ids event log route
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisronline committed Jul 30, 2021
1 parent 677abd6 commit 34dcc33
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 36 deletions.
23 changes: 14 additions & 9 deletions x-pack/plugins/actions/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import {
ElasticsearchServiceStart,
SavedObjectsClientContract,
SavedObjectsBulkGetObject,
SavedObjectsBaseOptions,
} from '../../../../src/core/server';

import {
Expand Down Expand Up @@ -356,20 +357,24 @@ export class ActionsPlugin implements Plugin<PluginSetupContract, PluginStartCon
// as authorizationContext which would then set a Legacy AuthorizationMode
const secureGetActionsClientWithRequest = (request: KibanaRequest) =>
getActionsClientWithRequest(request);
const getScopedSavedObjectsClientWithoutAccessToActions = (request: KibanaRequest) =>
core.savedObjects.getScopedClient(request);

this.eventLogService!.registerSavedObjectProvider('action', (request) => {
const client = secureGetActionsClientWithRequest(request);
return (objects?: SavedObjectsBulkGetObject[]) =>
objects
? Promise.all(
objects.map(async (objectItem) => await (await client).get({ id: objectItem.id }))
)
: Promise.resolve([]);
const soClient = getScopedSavedObjectsClientWithoutAccessToActions(request);
return {
bulkGetter: (objects?: SavedObjectsBulkGetObject[]) =>
objects
? Promise.all(
objects.map(async (objectItem) => await (await client).get({ id: objectItem.id }))
)
: Promise.resolve([]),
resolver: (type: string, id: string, options?: SavedObjectsBaseOptions) =>
soClient.resolve(type, id, options),
};
});

const getScopedSavedObjectsClientWithoutAccessToActions = (request: KibanaRequest) =>
core.savedObjects.getScopedClient(request);

actionExecutor!.initialize({
logger,
eventLogger: this.eventLogger!,
Expand Down
18 changes: 13 additions & 5 deletions x-pack/plugins/alerting/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
ServiceStatus,
SavedObjectsBulkGetObject,
ServiceStatusLevels,
SavedObjectsBaseOptions,
} from '../../../../src/core/server';
import type { AlertingRequestHandlerContext } from './types';
import { defineRoutes } from './routes';
Expand Down Expand Up @@ -368,6 +369,7 @@ export class AlertingPlugin {
return alertingAuthorizationClientFactory!.create(request);
};

const internalSavedObjectsRepository = core.savedObjects.createInternalRepository(['alert']);
taskRunnerFactory.initialize({
logger,
getServices: this.getServicesFactory(core.savedObjects, core.elasticsearch),
Expand All @@ -377,7 +379,7 @@ export class AlertingPlugin {
encryptedSavedObjectsClient,
basePathService: core.http.basePath,
eventLogger: this.eventLogger!,
internalSavedObjectsRepository: core.savedObjects.createInternalRepository(['alert']),
internalSavedObjectsRepository,
alertTypeRegistry: this.alertTypeRegistry!,
kibanaBaseUrl: this.kibanaBaseUrl,
supportsEphemeralTasks: plugins.taskManager.supportsEphemeralTasks(),
Expand All @@ -386,10 +388,16 @@ export class AlertingPlugin {

this.eventLogService!.registerSavedObjectProvider('alert', (request) => {
const client = getRulesClientWithRequest(request);
return (objects?: SavedObjectsBulkGetObject[]) =>
objects
? Promise.all(objects.map(async (objectItem) => await client.get({ id: objectItem.id })))
: Promise.resolve([]);
return {
bulkGetter: (objects?: SavedObjectsBulkGetObject[]) =>
objects
? Promise.all(
objects.map(async (objectItem) => await client.get({ id: objectItem.id }))
)
: Promise.resolve([]),
resolver: (type: string, id: string, options?: SavedObjectsBaseOptions) =>
internalSavedObjectsRepository.resolve(type, id, options),
};
});

scheduleAlertingTelemetry(this.telemetryLogger, plugins.taskManager);
Expand Down
27 changes: 23 additions & 4 deletions x-pack/plugins/event_log/server/event_log_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ import { SpacesServiceStart } from '../../spaces/server';
import { EsContext } from './es';
import { IEventLogClient } from './types';
import { QueryEventsBySavedObjectResult } from './es/cluster_client_adapter';
import { SavedObjectBulkGetterResult } from './saved_object_provider_registry';
import {
SavedObjectBulkGetterResult,
SavedObjectIdResolverResult,
} from './saved_object_provider_registry';
export type PluginClusterClient = Pick<IClusterClient, 'asInternalUser'>;
export type AdminClusterClient$ = Observable<PluginClusterClient>;

Expand Down Expand Up @@ -61,15 +64,21 @@ export type FindOptionsType = Pick<

interface EventLogServiceCtorParams {
esContext: EsContext;
savedObjectGetter: SavedObjectBulkGetterResult;
savedObjectGetter: {
bulkGetter: SavedObjectBulkGetterResult;
resolver: SavedObjectIdResolverResult;
};
spacesService?: SpacesServiceStart;
request: KibanaRequest;
}

// note that clusterClient may be null, indicating we can't write to ES
export class EventLogClient implements IEventLogClient {
private esContext: EsContext;
private savedObjectGetter: SavedObjectBulkGetterResult;
private savedObjectGetter: {
bulkGetter: SavedObjectBulkGetterResult;
resolver: SavedObjectIdResolverResult;
};
private spacesService?: SpacesServiceStart;
private request: KibanaRequest;

Expand All @@ -90,8 +99,18 @@ export class EventLogClient implements IEventLogClient {
const space = await this.spacesService?.getActiveSpace(this.request);
const namespace = space && this.spacesService?.spaceIdToNamespace(space.id);

// Pass ids through the SO resolve API to ensure they point to the right SO
let resolvedIds = ids;
try {
resolvedIds = (await Promise.all(
ids.map((id) => this.savedObjectGetter.resolver(type, id, { namespace }))
)) as string[];
} catch (err) {
throw err;
}

// verify the user has the required permissions to view this saved objects
await this.savedObjectGetter(type, ids);
await this.savedObjectGetter.bulkGetter(type, resolvedIds);

return await this.esContext.esAdapter.queryEventsBySavedObjects(
this.esContext.esNames.indexPattern,
Expand Down
5 changes: 4 additions & 1 deletion x-pack/plugins/event_log/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,10 @@ export class Plugin implements CorePlugin<IEventLogService, IEventLogClientServi

this.savedObjectProviderRegistry.registerDefaultProvider((request) => {
const client = core.savedObjects.getScopedClient(request);
return client.bulkGet.bind(client);
return {
bulkGetter: client.bulkGet.bind(client),
resolver: client.resolve.bind(client),
};
});

this.eventLogClientService = new EventLogClientService({
Expand Down
69 changes: 52 additions & 17 deletions x-pack/plugins/event_log/server/saved_object_provider_registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@
*/

import { i18n } from '@kbn/i18n';
import { KibanaRequest, SavedObjectsClientContract } from 'src/core/server';
import {
KibanaRequest,
SavedObjectsBaseOptions,
SavedObjectsClientContract,
} from 'src/core/server';

import { fromNullable, getOrElse } from 'fp-ts/lib/Option';
import { pipe } from 'fp-ts/lib/pipeable';
Expand All @@ -19,9 +23,23 @@ export type SavedObjectBulkGetter = (
...params: Parameters<SavedObjectsClientContract['bulkGet']>
) => Promise<unknown>;

export type SavedObjectResolver = (
...params: Parameters<SavedObjectsClientContract['resolve']>
) => Promise<unknown>;

export type SavedObjectBulkGetterResult = (type: string, ids: string[]) => Promise<unknown>;
export type SavedObjectIdResolverResult = (
type: string,
id: string,
options?: SavedObjectsBaseOptions | undefined
) => Promise<unknown> | undefined;

export type SavedObjectProvider = (request: KibanaRequest) => SavedObjectBulkGetter;
interface SavedObjectCombinedApi {
bulkGetter: SavedObjectBulkGetter;
resolver: SavedObjectResolver;
}

export type SavedObjectProvider = (request: KibanaRequest) => SavedObjectCombinedApi;

export class SavedObjectProviderRegistry {
private providers = new Map<string, SavedObjectProvider>();
Expand All @@ -42,7 +60,9 @@ export class SavedObjectProviderRegistry {
this.providers.set(type, provider);
}

public getProvidersClient(request: KibanaRequest): SavedObjectBulkGetterResult {
public getProvidersClient(
request: KibanaRequest
): { bulkGetter: SavedObjectBulkGetterResult; resolver: SavedObjectIdResolverResult } {
if (!this.defaultProvider) {
throw new Error(
i18n.translate(
Expand All @@ -60,21 +80,36 @@ export class SavedObjectProviderRegistry {

// would be nice to have a simple version support in API:
// curl -X GET "localhost:9200/my-index-000001/_mget?pretty" -H 'Content-Type: application/json' -d' { "ids" : ["1", "2"] } '
const scopedProviders = new Map<string, SavedObjectBulkGetter>();
const scopedProviders = new Map<string, SavedObjectCombinedApi>();
const defaultGetter = this.defaultProvider(request);
return (type: string, ids: string[]) => {
const objects = ids.map((id: string) => ({ type, id }));
const getter = pipe(
fromNullable(scopedProviders.get(type)),
getOrElse(() => {
const client = this.providers.has(type)
? this.providers.get(type)!(request)
: defaultGetter;
scopedProviders.set(type, client);
return client;
})
);
return getter(objects);
return {
bulkGetter: (type: string, ids: string[]) => {
const objects = ids.map((id: string) => ({ type, id }));
const getter = pipe(
fromNullable(scopedProviders.get(type)),
getOrElse(() => {
const client = this.providers.has(type)
? this.providers.get(type)!(request)
: defaultGetter;
scopedProviders.set(type, client);
return client;
})
);
return getter.bulkGetter(objects);
},
resolver: (type: string, id: string, options?: SavedObjectsBaseOptions) => {
const getter = pipe(
fromNullable(scopedProviders.get(type)),
getOrElse(() => {
const client = this.providers.has(type)
? this.providers.get(type)!(request)
: defaultGetter;
scopedProviders.set(type, client);
return client;
})
);
return getter.resolver(type, id, options);
},
};
}
}

0 comments on commit 34dcc33

Please sign in to comment.