forked from elastic/kibana
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Alerting] Refactor alerts authorization client (elastic#99078)
* WIP - creating alerting authorization client factory and exposing authorization client on plugin start contract * Updating alerting feature privilege builder to handle different alerting types * Passing in alerting authorization type to AlertingActions class string builder * Passing in authorization type in each function call * Passing in exempt consumer ids. Adding authorization type to audit logger * Changing alertType to ruleType * Changing alertType to ruleType * Updating unit tests * Updating unit tests * Passing field names into authorization query builder. Adding kql/es dsl option * Converting to es query if requested * Fixing functional tests * Removing ability to specify feature privilege name in constructor * Fixing some types and tests * Consolidating alerting authorization kuery filter options * Cleanup and tests * Cleanup and tests * Throwing error when AlertingAuthorizationClientFactory is not defined * Renaming authorizationType to entity * Renaming AlertsAuthorization to AlertingAuthorization * Fixing unit tests * Updating privilege string terminology * Updating privilege string terminology Co-authored-by: Kibana Machine <[email protected]>
- Loading branch information
1 parent
9768ee2
commit 8049d95
Showing
50 changed files
with
2,456 additions
and
1,948 deletions.
There are no files selected for viewing
21 changes: 21 additions & 0 deletions
21
x-pack/plugins/alerting/server/alerting_authorization_client_factory.mock.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
}; |
130 changes: 130 additions & 0 deletions
130
x-pack/plugins/alerting/server/alerting_authorization_client_factory.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
}); |
59 changes: 59 additions & 0 deletions
59
x-pack/plugins/alerting/server/alerting_authorization_client_factory.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
}); | ||
} | ||
} |
Oops, something went wrong.