Skip to content

Commit

Permalink
[Timeline][RBAC] - Add RBAC logic to timeline alerts search strategy (#…
Browse files Browse the repository at this point in the history
…105333)

## Summary
 
Adds RBAC layer to timeline plugin search strategy for alerts.
  • Loading branch information
yctercero authored Jul 28, 2021
1 parent 196eb7b commit 44a9dad
Show file tree
Hide file tree
Showing 64 changed files with 2,496 additions and 605 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ export interface ISearchStart<SearchStrategyRequest extends IKibanaSearchRequest
| [aggs](./kibana-plugin-plugins-data-server.isearchstart.aggs.md) | <code>AggsStart</code> | |
| [asScoped](./kibana-plugin-plugins-data-server.isearchstart.asscoped.md) | <code>(request: KibanaRequest) =&gt; IScopedSearchClient</code> | |
| [getSearchStrategy](./kibana-plugin-plugins-data-server.isearchstart.getsearchstrategy.md) | <code>(name?: string) =&gt; ISearchStrategy&lt;SearchStrategyRequest, SearchStrategyResponse&gt;</code> | Get other registered search strategies by name (or, by default, the Elasticsearch strategy). For example, if a new strategy needs to use the already-registered ES search strategy, it can use this function to accomplish that. |
| [searchAsInternalUser](./kibana-plugin-plugins-data-server.isearchstart.searchasinternaluser.md) | <code>ISearchStrategy</code> | Search as the internal Kibana system user. This is not a registered search strategy as we don't want to allow access from the client. |
| [searchSource](./kibana-plugin-plugins-data-server.isearchstart.searchsource.md) | <code>{</code><br/><code> asScoped: (request: KibanaRequest) =&gt; Promise&lt;ISearchStartSearchSource&gt;;</code><br/><code> }</code> | |

Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [kibana-plugin-plugins-data-server](./kibana-plugin-plugins-data-server.md) &gt; [ISearchStart](./kibana-plugin-plugins-data-server.isearchstart.md) &gt; [searchAsInternalUser](./kibana-plugin-plugins-data-server.isearchstart.searchasinternaluser.md)

## ISearchStart.searchAsInternalUser property

Search as the internal Kibana system user. This is not a registered search strategy as we don't want to allow access from the client.

<b>Signature:</b>

```typescript
searchAsInternalUser: ISearchStrategy;
```
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/*
* 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.
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

/**
Expand All @@ -13,7 +14,18 @@
* This doesn't work in combination with the `xpack.ruleRegistry.index`
* setting, with which the user can change the index prefix.
*/
export const mapConsumerToIndexName = {

export const ALERTS_CONSUMERS = {
APM: 'apm',
LOGS: 'logs',
INFRASTRUCTURE: 'infrastructure',
OBSERVABILITY: 'observability',
SIEM: 'siem',
SYNTHETICS: 'synthetics',
} as const;
export type ALERTS_CONSUMERS = typeof ALERTS_CONSUMERS[keyof typeof ALERTS_CONSUMERS];

export const mapConsumerToIndexName: Record<ALERTS_CONSUMERS, string | string[]> = {
apm: '.alerts-observability-apm',
logs: '.alerts-observability.logs',
infrastructure: '.alerts-observability.metrics',
Expand Down
1 change: 1 addition & 0 deletions packages/kbn-rule-data-utils/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@
*/

export * from './technical_field_names';
export * from './alerts_as_data_rbac';
1 change: 1 addition & 0 deletions src/plugins/data/server/search/mocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export function createSearchSetupMock(): jest.Mocked<ISearchSetup> {
export function createSearchStartMock(): jest.Mocked<ISearchStart> {
return {
aggs: searchAggsStartMock(),
searchAsInternalUser: createSearchRequestHandlerContext(),
getSearchStrategy: jest.fn(),
asScoped: jest.fn().mockReturnValue(createSearchRequestHandlerContext()),
searchSource: searchSourceMock.createStartContract(),
Expand Down
13 changes: 13 additions & 0 deletions src/plugins/data/server/search/search_service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
private searchStrategies: StrategyMap = {};
private sessionService: ISearchSessionService;
private asScoped!: ISearchStart['asScoped'];
private searchAsInternalUser!: ISearchStrategy;

constructor(
private initializerContext: PluginInitializerContext<ConfigSchema>,
Expand Down Expand Up @@ -156,6 +157,17 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
)
);

// We don't want to register this because we don't want the client to be able to access this
// strategy, but we do want to expose it to other server-side plugins
// see x-pack/plugins/security_solution/server/search_strategy/timeline/index.ts
// for example use case
this.searchAsInternalUser = enhancedEsSearchStrategyProvider(
this.initializerContext.config.legacy.globalConfig$,
this.logger,
usage,
true
);

this.registerSearchStrategy(EQL_SEARCH_STRATEGY, eqlSearchStrategyProvider(this.logger));

registerBsearchRoute(
Expand Down Expand Up @@ -220,6 +232,7 @@ export class SearchService implements Plugin<ISearchSetup, ISearchStart> {
uiSettings,
indexPatterns,
}),
searchAsInternalUser: this.searchAsInternalUser,
getSearchStrategy: this.getSearchStrategy,
asScoped: this.asScoped,
searchSource: {
Expand Down
5 changes: 5 additions & 0 deletions src/plugins/data/server/search/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,11 @@ export interface ISearchStart<
SearchStrategyResponse extends IKibanaSearchResponse = IEsSearchResponse
> {
aggs: AggsStart;
/**
* Search as the internal Kibana system user. This is not a registered search strategy as we don't
* want to allow access from the client.
*/
searchAsInternalUser: ISearchStrategy;
/**
* Get other registered search strategies by name (or, by default, the Elasticsearch strategy).
* For example, if a new strategy needs to use the already-registered ES search strategy, it can
Expand Down
3 changes: 2 additions & 1 deletion src/plugins/data/server/server.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -1048,6 +1048,7 @@ export interface ISearchStart<SearchStrategyRequest extends IKibanaSearchRequest
// (undocumented)
asScoped: (request: KibanaRequest) => IScopedSearchClient;
getSearchStrategy: (name?: string) => ISearchStrategy<SearchStrategyRequest, SearchStrategyResponse>;
searchAsInternalUser: ISearchStrategy;
// (undocumented)
searchSource: {
asScoped: (request: KibanaRequest) => Promise<ISearchStartSearchSource>;
Expand Down Expand Up @@ -1518,7 +1519,7 @@ export function usageProvider(core: CoreSetup_2): SearchUsage;
// src/plugins/data/server/index.ts:280:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/index.ts:281:1 - (ae-forgotten-export) The symbol "calcAutoIntervalLessThan" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/plugin.ts:81:74 - (ae-forgotten-export) The symbol "DataEnhancements" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/search/types.ts:115:5 - (ae-forgotten-export) The symbol "ISearchStartSearchSource" needs to be exported by the entry point index.d.ts
// src/plugins/data/server/search/types.ts:120:5 - (ae-forgotten-export) The symbol "ISearchStartSearchSource" needs to be exported by the entry point index.d.ts

// (No @packageDocumentation comment for this package)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ const securityPluginStart = securityMock.createStart();
const alertingAuthorizationClientFactoryParams: jest.Mocked<AlertingAuthorizationClientFactoryOpts> = {
ruleTypeRegistry: ruleTypeRegistryMock.create(),
getSpace: jest.fn(),
getSpaceId: jest.fn(),
features,
};

Expand Down Expand Up @@ -73,6 +74,7 @@ test('creates an alerting authorization client with proper constructor arguments
features: alertingAuthorizationClientFactoryParams.features,
auditLogger: expect.any(AlertingAuthorizationAuditLogger),
getSpace: expect.any(Function),
getSpaceId: expect.any(Function),
exemptConsumerIds: [],
});

Expand Down Expand Up @@ -100,6 +102,7 @@ test('creates an alerting authorization client with proper constructor arguments
features: alertingAuthorizationClientFactoryParams.features,
auditLogger: expect.any(AlertingAuthorizationAuditLogger),
getSpace: expect.any(Function),
getSpaceId: expect.any(Function),
exemptConsumerIds: ['exemptConsumerA', 'exemptConsumerB'],
});

Expand All @@ -122,6 +125,7 @@ test('creates an alerting authorization client with proper constructor arguments
features: alertingAuthorizationClientFactoryParams.features,
auditLogger: expect.any(AlertingAuthorizationAuditLogger),
getSpace: expect.any(Function),
getSpaceId: expect.any(Function),
exemptConsumerIds: [],
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export interface AlertingAuthorizationClientFactoryOpts {
securityPluginSetup?: SecurityPluginSetup;
securityPluginStart?: SecurityPluginStart;
getSpace: (request: KibanaRequest) => Promise<Space | undefined>;
getSpaceId: (request: KibanaRequest) => string | undefined;
features: FeaturesPluginStart;
}

Expand All @@ -29,6 +30,7 @@ export class AlertingAuthorizationClientFactory {
private securityPluginSetup?: SecurityPluginSetup;
private features!: FeaturesPluginStart;
private getSpace!: (request: KibanaRequest) => Promise<Space | undefined>;
private getSpaceId!: (request: KibanaRequest) => string | undefined;

public initialize(options: AlertingAuthorizationClientFactoryOpts) {
if (this.isInitialized) {
Expand All @@ -40,6 +42,7 @@ export class AlertingAuthorizationClientFactory {
this.securityPluginSetup = options.securityPluginSetup;
this.securityPluginStart = options.securityPluginStart;
this.features = options.features;
this.getSpaceId = options.getSpaceId;
}

public create(request: KibanaRequest, exemptConsumerIds: string[] = []): AlertingAuthorization {
Expand All @@ -48,6 +51,7 @@ export class AlertingAuthorizationClientFactory {
authorization: securityPluginStart?.authz,
request,
getSpace: this.getSpace,
getSpaceId: this.getSpaceId,
ruleTypeRegistry: this.ruleTypeRegistry,
features: features!,
auditLogger: new AlertingAuthorizationAuditLogger(
Expand Down
Loading

0 comments on commit 44a9dad

Please sign in to comment.