Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Alerting] Refactor alerts authorization client #99078

Merged
merged 30 commits into from
May 18, 2021
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
1170c6e
WIP - creating alerting authorization client factory and exposing aut…
ymao1 Apr 30, 2021
5a1c2c8
Updating alerting feature privilege builder to handle different alert…
ymao1 Apr 30, 2021
cbde0cc
Passing in alerting authorization type to AlertingActions class strin…
ymao1 Apr 30, 2021
a2ffb8d
Merge branch 'master' of https://github.com/elastic/kibana into alert…
ymao1 May 3, 2021
fd1a28b
Passing in authorization type in each function call
ymao1 May 3, 2021
a97e064
Passing in exempt consumer ids. Adding authorization type to audit lo…
ymao1 May 3, 2021
b9ee8ac
Changing alertType to ruleType
ymao1 May 3, 2021
cd6185f
Changing alertType to ruleType
ymao1 May 3, 2021
6daa470
Updating unit tests
ymao1 May 3, 2021
be00344
Updating unit tests
ymao1 May 3, 2021
721576a
Passing field names into authorization query builder. Adding kql/es d…
ymao1 May 3, 2021
e1cd872
Converting to es query if requested
ymao1 May 3, 2021
2007a56
Fixing functional tests
ymao1 May 3, 2021
857b0de
Removing ability to specify feature privilege name in constructor
ymao1 May 3, 2021
56e876c
Merge branch 'master' of https://github.com/elastic/kibana into alert…
ymao1 May 4, 2021
7ef5bcd
Fixing some types and tests
ymao1 May 4, 2021
8359289
Consolidating alerting authorization kuery filter options
ymao1 May 4, 2021
b5a49cd
Cleanup and tests
ymao1 May 4, 2021
0fbaf23
Cleanup and tests
ymao1 May 4, 2021
1792895
Merge branch 'master' of https://github.com/elastic/kibana into alert…
ymao1 May 11, 2021
ee3f226
Throwing error when AlertingAuthorizationClientFactory is not defined
ymao1 May 12, 2021
bfbfae4
Renaming authorizationType to entity
ymao1 May 12, 2021
3abf488
Renaming AlertsAuthorization to AlertingAuthorization
ymao1 May 12, 2021
334030b
Merge branch 'master' of https://github.com/elastic/kibana into alert…
ymao1 May 12, 2021
a04dc1e
Fixing unit tests
ymao1 May 12, 2021
3bafd6d
Merge branch 'master' into alerting/refactor-alerts-authorization
kibanamachine May 13, 2021
91a98ea
Merge branch 'master' of https://github.com/elastic/kibana into alert…
ymao1 May 17, 2021
ce70ff2
Updating privilege string terminology
ymao1 May 17, 2021
918bc00
Updating privilege string terminology
ymao1 May 17, 2021
ad4d1ef
Merge branch 'master' into alerting/refactor-alerts-authorization
kibanamachine May 18, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* 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 { PublicMethodsOf } from '@kbn/utility-types';
import { AlertingAuthorizationClientFactory } from './alerting_authorization_client_factory';

const creatAlertingAuthorizationClientFactoryMock = () => {
const mocked: jest.Mocked<PublicMethodsOf<AlertingAuthorizationClientFactory>> = {
create: jest.fn(),
initialize: jest.fn(),
};
return mocked;
};

export const alertingAuthorizationClientFactoryMock = {
createFactory: creatAlertingAuthorizationClientFactoryMock,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/*
* 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 { Request } from '@hapi/hapi';
import { alertTypeRegistryMock } from './alert_type_registry.mock';
import { KibanaRequest } from '../../../../src/core/server';
import { savedObjectsClientMock } from '../../../../src/core/server/mocks';
import { securityMock } from '../../security/server/mocks';
import { ALERTS_FEATURE_ID } from '../common';
import {
AlertingAuthorizationClientFactory,
AlertingAuthorizationClientFactoryOpts,
} from './alerting_authorization_client_factory';
import { featuresPluginMock } from '../../features/server/mocks';

jest.mock('./authorization/alerting_authorization');
jest.mock('./authorization/audit_logger');

const savedObjectsClient = savedObjectsClientMock.create();
const features = featuresPluginMock.createStart();

const securityPluginSetup = securityMock.createSetup();
const securityPluginStart = securityMock.createStart();

const alertingAuthorizationClientFactoryParams: jest.Mocked<AlertingAuthorizationClientFactoryOpts> = {
alertTypeRegistry: alertTypeRegistryMock.create(),
getSpace: jest.fn(),
features,
};

const fakeRequest = ({
app: {},
headers: {},
getBasePath: () => '',
path: '/',
route: { settings: {} },
url: {
href: '/',
},
raw: {
req: {
url: '/',
},
},
getSavedObjectsClient: () => savedObjectsClient,
} as unknown) as Request;

beforeEach(() => {
jest.resetAllMocks();
});

test('creates an alerting authorization client with proper constructor arguments when security is enabled', async () => {
const factory = new AlertingAuthorizationClientFactory();
factory.initialize({
securityPluginSetup,
securityPluginStart,
...alertingAuthorizationClientFactoryParams,
});
const request = KibanaRequest.from(fakeRequest);
const { AlertingAuthorizationAuditLogger } = jest.requireMock('./authorization/audit_logger');

factory.create(request);

const { AlertingAuthorization } = jest.requireMock('./authorization/alerting_authorization');
expect(AlertingAuthorization).toHaveBeenCalledWith({
request,
authorization: securityPluginStart.authz,
alertTypeRegistry: alertingAuthorizationClientFactoryParams.alertTypeRegistry,
features: alertingAuthorizationClientFactoryParams.features,
auditLogger: expect.any(AlertingAuthorizationAuditLogger),
getSpace: expect.any(Function),
exemptConsumerIds: [],
});

expect(AlertingAuthorizationAuditLogger).toHaveBeenCalled();
expect(securityPluginSetup.audit.getLogger).toHaveBeenCalledWith(ALERTS_FEATURE_ID);
});

test('creates an alerting authorization client with proper constructor arguments when exemptConsumerIds are specified', async () => {
const factory = new AlertingAuthorizationClientFactory();
factory.initialize({
securityPluginSetup,
securityPluginStart,
...alertingAuthorizationClientFactoryParams,
});
const request = KibanaRequest.from(fakeRequest);
const { AlertingAuthorizationAuditLogger } = jest.requireMock('./authorization/audit_logger');

factory.create(request, ['exemptConsumerA', 'exemptConsumerB']);

const { AlertingAuthorization } = jest.requireMock('./authorization/alerting_authorization');
expect(AlertingAuthorization).toHaveBeenCalledWith({
request,
authorization: securityPluginStart.authz,
alertTypeRegistry: alertingAuthorizationClientFactoryParams.alertTypeRegistry,
features: alertingAuthorizationClientFactoryParams.features,
auditLogger: expect.any(AlertingAuthorizationAuditLogger),
getSpace: expect.any(Function),
exemptConsumerIds: ['exemptConsumerA', 'exemptConsumerB'],
});

expect(AlertingAuthorizationAuditLogger).toHaveBeenCalled();
expect(securityPluginSetup.audit.getLogger).toHaveBeenCalledWith(ALERTS_FEATURE_ID);
});

test('creates an alerting authorization client with proper constructor arguments', async () => {
const factory = new AlertingAuthorizationClientFactory();
factory.initialize(alertingAuthorizationClientFactoryParams);
const request = KibanaRequest.from(fakeRequest);
const { AlertingAuthorizationAuditLogger } = jest.requireMock('./authorization/audit_logger');

factory.create(request);

const { AlertingAuthorization } = jest.requireMock('./authorization/alerting_authorization');
expect(AlertingAuthorization).toHaveBeenCalledWith({
request,
alertTypeRegistry: alertingAuthorizationClientFactoryParams.alertTypeRegistry,
features: alertingAuthorizationClientFactoryParams.features,
auditLogger: expect.any(AlertingAuthorizationAuditLogger),
getSpace: expect.any(Function),
exemptConsumerIds: [],
});

expect(AlertingAuthorizationAuditLogger).toHaveBeenCalled();
expect(securityPluginSetup.audit.getLogger).not.toHaveBeenCalled();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
* 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 { KibanaRequest } from 'src/core/server';
import { ALERTS_FEATURE_ID } from '../common';
import { AlertTypeRegistry } from './types';
import { SecurityPluginSetup, SecurityPluginStart } from '../../security/server';
import { PluginStartContract as FeaturesPluginStart } from '../../features/server';
import { AlertingAuthorization } from './authorization/alerting_authorization';
import { AlertingAuthorizationAuditLogger } from './authorization/audit_logger';
import { Space } from '../../spaces/server';

export interface AlertingAuthorizationClientFactoryOpts {
alertTypeRegistry: AlertTypeRegistry;
securityPluginSetup?: SecurityPluginSetup;
securityPluginStart?: SecurityPluginStart;
getSpace: (request: KibanaRequest) => Promise<Space | undefined>;
features: FeaturesPluginStart;
}

export class AlertingAuthorizationClientFactory {
private isInitialized = false;
private alertTypeRegistry!: AlertTypeRegistry;
private securityPluginStart?: SecurityPluginStart;
private securityPluginSetup?: SecurityPluginSetup;
private features!: FeaturesPluginStart;
private getSpace!: (request: KibanaRequest) => Promise<Space | undefined>;

public initialize(options: AlertingAuthorizationClientFactoryOpts) {
if (this.isInitialized) {
throw new Error('AlertingAuthorizationClientFactory already initialized');
}
this.isInitialized = true;
this.getSpace = options.getSpace;
this.alertTypeRegistry = options.alertTypeRegistry;
this.securityPluginSetup = options.securityPluginSetup;
this.securityPluginStart = options.securityPluginStart;
this.features = options.features;
}

public create(request: KibanaRequest, exemptConsumerIds: string[] = []): AlertingAuthorization {
const { securityPluginSetup, securityPluginStart, features } = this;
return new AlertingAuthorization({
authorization: securityPluginStart?.authz,
request,
getSpace: this.getSpace,
alertTypeRegistry: this.alertTypeRegistry,
features: features!,
auditLogger: new AlertingAuthorizationAuditLogger(
securityPluginSetup?.audit.getLogger(ALERTS_FEATURE_ID)
),
exemptConsumerIds,
});
}
}
Loading