Skip to content

Commit

Permalink
use alerts and actions clients in Event Log
Browse files Browse the repository at this point in the history
  • Loading branch information
gmmorris committed Jul 27, 2020
1 parent 7296b07 commit 9dba118
Show file tree
Hide file tree
Showing 17 changed files with 179 additions and 96 deletions.
7 changes: 7 additions & 0 deletions x-pack/plugins/actions/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export class ActionsPlugin implements Plugin<Promise<PluginSetupContract>, Plugi
private licenseState: ILicenseState | null = null;
private spaces?: SpacesServiceSetup;
private security?: SecurityPluginSetup;
private eventLogService?: IEventLogService;
private eventLogger?: IEventLogger;
private isESOUsingEphemeralEncryptionKey?: boolean;
private readonly telemetryLogger: Logger;
Expand Down Expand Up @@ -147,6 +148,7 @@ export class ActionsPlugin implements Plugin<Promise<PluginSetupContract>, Plugi
plugins.features.registerFeature(ACTIONS_FEATURE);
setupSavedObjects(core.savedObjects, plugins.encryptedSavedObjects);

this.eventLogService = plugins.eventLog;
plugins.eventLog.registerProviderActions(EVENT_LOG_PROVIDER, Object.values(EVENT_LOG_ACTIONS));
this.eventLogger = plugins.eventLog.getLogger({
event: { provider: EVENT_LOG_PROVIDER },
Expand Down Expand Up @@ -276,6 +278,11 @@ export class ActionsPlugin implements Plugin<Promise<PluginSetupContract>, Plugi
});
};

this.eventLogService!.registerSavedObjectProvider('action', (request) => {
const client = getActionsClientWithRequest(request);
return async (type: string, id: string) => (await client).get({ id });
});

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

Expand Down
7 changes: 7 additions & 0 deletions x-pack/plugins/alerts/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ export class AlertingPlugin {
private readonly alertsClientFactory: AlertsClientFactory;
private readonly telemetryLogger: Logger;
private readonly kibanaIndex: Promise<string>;
private eventLogService?: IEventLogService;
private eventLogger?: IEventLogger;

constructor(initializerContext: PluginInitializerContext) {
Expand Down Expand Up @@ -140,6 +141,7 @@ export class AlertingPlugin {

setupSavedObjects(core.savedObjects, plugins.encryptedSavedObjects);

this.eventLogService = plugins.eventLog;
plugins.eventLog.registerProviderActions(EVENT_LOG_PROVIDER, Object.values(EVENT_LOG_ACTIONS));
this.eventLogger = plugins.eventLog.getLogger({
event: { provider: EVENT_LOG_PROVIDER },
Expand Down Expand Up @@ -245,6 +247,11 @@ export class AlertingPlugin {
eventLogger: this.eventLogger!,
});

this.eventLogService!.registerSavedObjectProvider('alert', (request) => {
const client = getAlertsClientWithRequest(request);
return (type: string, id: string) => client.get({ id });
});

scheduleAlertingTelemetry(this.telemetryLogger, plugins.taskManager);

return {
Expand Down
55 changes: 33 additions & 22 deletions x-pack/plugins/event_log/server/event_log_client.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,22 @@
import { KibanaRequest } from 'src/core/server';
import { EventLogClient } from './event_log_client';
import { contextMock } from './es/context.mock';
import { savedObjectsClientMock } from 'src/core/server/mocks';
import { merge } from 'lodash';
import moment from 'moment';

describe('EventLogStart', () => {
describe('findEventsBySavedObject', () => {
test('verifies that the user can access the specified saved object', async () => {
const esContext = contextMock.create();
const savedObjectsClient = savedObjectsClientMock.create();
const savedObjectGetter = jest.fn();

const eventLogClient = new EventLogClient({
esContext,
savedObjectsClient,
savedObjectGetter,
request: FakeRequest(),
});

savedObjectsClient.get.mockResolvedValueOnce({
savedObjectGetter.mockResolvedValueOnce({
id: 'saved-object-id',
type: 'saved-object-type',
attributes: {},
Expand All @@ -31,19 +31,21 @@ describe('EventLogStart', () => {

await eventLogClient.findEventsBySavedObject('saved-object-type', 'saved-object-id');

expect(savedObjectsClient.get).toHaveBeenCalledWith('saved-object-type', 'saved-object-id');
expect(savedObjectGetter).toHaveBeenCalledWith('saved-object-type', 'saved-object-id');
});

test('throws when the user doesnt have permission to access the specified saved object', async () => {
const esContext = contextMock.create();
const savedObjectsClient = savedObjectsClientMock.create();

const savedObjectGetter = jest.fn();

const eventLogClient = new EventLogClient({
esContext,
savedObjectsClient,
savedObjectGetter,
request: FakeRequest(),
});

savedObjectsClient.get.mockRejectedValue(new Error('Fail'));
savedObjectGetter.mockRejectedValue(new Error('Fail'));

expect(
eventLogClient.findEventsBySavedObject('saved-object-type', 'saved-object-id')
Expand All @@ -52,14 +54,16 @@ describe('EventLogStart', () => {

test('fetches all event that reference the saved object', async () => {
const esContext = contextMock.create();
const savedObjectsClient = savedObjectsClientMock.create();

const savedObjectGetter = jest.fn();

const eventLogClient = new EventLogClient({
esContext,
savedObjectsClient,
savedObjectGetter,
request: FakeRequest(),
});

savedObjectsClient.get.mockResolvedValueOnce({
savedObjectGetter.mockResolvedValueOnce({
id: 'saved-object-id',
type: 'saved-object-type',
attributes: {},
Expand Down Expand Up @@ -125,14 +129,16 @@ describe('EventLogStart', () => {

test('fetches all events in time frame that reference the saved object', async () => {
const esContext = contextMock.create();
const savedObjectsClient = savedObjectsClientMock.create();

const savedObjectGetter = jest.fn();

const eventLogClient = new EventLogClient({
esContext,
savedObjectsClient,
savedObjectGetter,
request: FakeRequest(),
});

savedObjectsClient.get.mockResolvedValueOnce({
savedObjectGetter.mockResolvedValueOnce({
id: 'saved-object-id',
type: 'saved-object-type',
attributes: {},
Expand Down Expand Up @@ -206,14 +212,16 @@ describe('EventLogStart', () => {

test('validates that the start date is valid', async () => {
const esContext = contextMock.create();
const savedObjectsClient = savedObjectsClientMock.create();

const savedObjectGetter = jest.fn();

const eventLogClient = new EventLogClient({
esContext,
savedObjectsClient,
savedObjectGetter,
request: FakeRequest(),
});

savedObjectsClient.get.mockResolvedValueOnce({
savedObjectGetter.mockResolvedValueOnce({
id: 'saved-object-id',
type: 'saved-object-type',
attributes: {},
Expand All @@ -236,14 +244,16 @@ describe('EventLogStart', () => {

test('validates that the end date is valid', async () => {
const esContext = contextMock.create();
const savedObjectsClient = savedObjectsClientMock.create();

const savedObjectGetter = jest.fn();

const eventLogClient = new EventLogClient({
esContext,
savedObjectsClient,
savedObjectGetter,
request: FakeRequest(),
});

savedObjectsClient.get.mockResolvedValueOnce({
savedObjectGetter.mockResolvedValueOnce({
id: 'saved-object-id',
type: 'saved-object-type',
attributes: {},
Expand Down Expand Up @@ -297,7 +307,8 @@ function fakeEvent(overrides = {}) {
}

function FakeRequest(): KibanaRequest {
const savedObjectsClient = savedObjectsClientMock.create();
const savedObjectGetter = jest.fn();

return ({
headers: {},
getBasePath: () => '',
Expand All @@ -311,6 +322,6 @@ function FakeRequest(): KibanaRequest {
url: '/',
},
},
getSavedObjectsClient: () => savedObjectsClient,
getSavedObjectsClient: () => savedObjectGetter,
} as unknown) as KibanaRequest;
}
18 changes: 7 additions & 11 deletions x-pack/plugins/event_log/server/event_log_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@

import { Observable } from 'rxjs';
import { schema, TypeOf } from '@kbn/config-schema';
import { LegacyClusterClient, SavedObjectsClientContract, KibanaRequest } from 'src/core/server';
import { LegacyClusterClient, KibanaRequest } from 'src/core/server';
import { SpacesServiceSetup } from '../../spaces/server';

import { EsContext } from './es';
import { IEventLogClient } from './types';
import { QueryEventsBySavedObjectResult } from './es/cluster_client_adapter';
import { SavedObjectGetter } from './saved_object_provider_registry';
export type PluginClusterClient = Pick<LegacyClusterClient, 'callAsInternalUser' | 'asScoped'>;
export type AdminClusterClient$ = Observable<PluginClusterClient>;

Expand Down Expand Up @@ -58,26 +59,21 @@ export type FindOptionsType = Pick<

interface EventLogServiceCtorParams {
esContext: EsContext;
savedObjectsClient: SavedObjectsClientContract;
savedObjectGetter: SavedObjectGetter;
spacesService?: SpacesServiceSetup;
request: KibanaRequest;
}

// note that clusterClient may be null, indicating we can't write to ES
export class EventLogClient implements IEventLogClient {
private esContext: EsContext;
private savedObjectsClient: SavedObjectsClientContract;
private savedObjectGetter: SavedObjectGetter;
private spacesService?: SpacesServiceSetup;
private request: KibanaRequest;

constructor({
esContext,
savedObjectsClient,
spacesService,
request,
}: EventLogServiceCtorParams) {
constructor({ esContext, savedObjectGetter, spacesService, request }: EventLogServiceCtorParams) {
this.esContext = esContext;
this.savedObjectsClient = savedObjectsClient;
this.savedObjectGetter = savedObjectGetter;
this.spacesService = spacesService;
this.request = request;
}
Expand All @@ -93,7 +89,7 @@ export class EventLogClient implements IEventLogClient {
const namespace = space && this.spacesService?.spaceIdToNamespace(space.id);

// verify the user has the required permissions to view this saved object
await this.savedObjectsClient.get(type, id);
await this.savedObjectGetter(type, id);

return await this.esContext.esAdapter.queryEventsBySavedObject(
this.esContext.esNames.alias,
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/event_log/server/event_log_service.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const createEventLogServiceMock = () => {
registerProviderActions: jest.fn(),
isProviderActionRegistered: jest.fn(),
getProviderActions: jest.fn(),
registerSavedObjectProvider: jest.fn(),
getLogger: jest.fn().mockReturnValue(eventLoggerMock.create()),
};
return mock;
Expand Down
5 changes: 5 additions & 0 deletions x-pack/plugins/event_log/server/event_log_service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import { IEventLogConfig } from './types';
import { EventLogService } from './event_log_service';
import { contextMock } from './es/context.mock';
import { loggingSystemMock } from 'src/core/server/mocks';
import { savedObjectProviderRegistryMock } from './saved_object_provider_registry.mock';

const loggingService = loggingSystemMock.create();
const systemLogger = loggingService.get();
const savedObjectProviderRegistry = savedObjectProviderRegistryMock.create();

describe('EventLogService', () => {
const esContext = contextMock.create();
Expand All @@ -21,6 +23,7 @@ describe('EventLogService', () => {
esContext,
systemLogger,
kibanaUUID: '42',
savedObjectProviderRegistry,
config: {
enabled,
logEntries,
Expand Down Expand Up @@ -65,6 +68,7 @@ describe('EventLogService', () => {
esContext,
systemLogger,
kibanaUUID: '42',
savedObjectProviderRegistry,
config: {
enabled: true,
logEntries: true,
Expand Down Expand Up @@ -102,6 +106,7 @@ describe('EventLogService', () => {
esContext,
systemLogger,
kibanaUUID: '42',
savedObjectProviderRegistry,
config: {
enabled: true,
logEntries: true,
Expand Down
16 changes: 15 additions & 1 deletion x-pack/plugins/event_log/server/event_log_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { Plugin } from './plugin';
import { EsContext } from './es';
import { IEvent, IEventLogger, IEventLogService, IEventLogConfig } from './types';
import { EventLogger } from './event_logger';
import { SavedObjectProvider, SavedObjectProviderRegistry } from './saved_object_provider_registry';
export type PluginClusterClient = Pick<LegacyClusterClient, 'callAsInternalUser' | 'asScoped'>;
export type AdminClusterClient$ = Observable<PluginClusterClient>;

Expand All @@ -21,6 +22,7 @@ interface EventLogServiceCtorParams {
esContext: EsContext;
kibanaUUID: string;
systemLogger: SystemLogger;
savedObjectProviderRegistry: PublicMethodsOf<SavedObjectProviderRegistry>;
}

// note that clusterClient may be null, indicating we can't write to ES
Expand All @@ -29,15 +31,23 @@ export class EventLogService implements IEventLogService {
private esContext: EsContext;
private systemLogger: SystemLogger;
private registeredProviderActions: Map<string, Set<string>>;
private savedObjectProviderRegistry: PublicMethodsOf<SavedObjectProviderRegistry>;

public readonly kibanaUUID: string;

constructor({ config, esContext, kibanaUUID, systemLogger }: EventLogServiceCtorParams) {
constructor({
config,
esContext,
kibanaUUID,
systemLogger,
savedObjectProviderRegistry,
}: EventLogServiceCtorParams) {
this.config = config;
this.esContext = esContext;
this.kibanaUUID = kibanaUUID;
this.systemLogger = systemLogger;
this.registeredProviderActions = new Map<string, Set<string>>();
this.savedObjectProviderRegistry = savedObjectProviderRegistry;
}

public isEnabled(): boolean {
Expand Down Expand Up @@ -77,6 +87,10 @@ export class EventLogService implements IEventLogService {
return new Map(this.registeredProviderActions.entries());
}

registerSavedObjectProvider(type: string, provider: SavedObjectProvider) {
return this.savedObjectProviderRegistry.registerProvider(type, provider);
}

getLogger(initialProperties: IEvent): IEventLogger {
return new EventLogger({
esContext: this.esContext,
Expand Down
11 changes: 5 additions & 6 deletions x-pack/plugins/event_log/server/event_log_start_service.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@
*/

import { KibanaRequest } from 'src/core/server';
import { savedObjectsClientMock, savedObjectsServiceMock } from 'src/core/server/mocks';
import { savedObjectsClientMock } from 'src/core/server/mocks';

import { EventLogClientService } from './event_log_start_service';
import { contextMock } from './es/context.mock';
import { savedObjectProviderRegistryMock } from './saved_object_provider_registry.mock';

jest.mock('./event_log_client');

Expand All @@ -17,19 +18,17 @@ describe('EventLogClientService', () => {

describe('getClient', () => {
test('creates a client with a scoped SavedObjects client', () => {
const savedObjectsService = savedObjectsServiceMock.createStartContract();
const savedObjectProviderRegistry = savedObjectProviderRegistryMock.create();
const request = fakeRequest();

const eventLogStartService = new EventLogClientService({
esContext,
savedObjectsService,
savedObjectProviderRegistry,
});

eventLogStartService.getClient(request);

expect(savedObjectsService.getScopedClient).toHaveBeenCalledWith(request, {
includedHiddenTypes: ['action', 'alert'],
});
expect(savedObjectProviderRegistry.getProvidersClient).toHaveBeenCalledWith(request);
});
});
});
Expand Down
Loading

0 comments on commit 9dba118

Please sign in to comment.