Skip to content

Commit 064fd8e

Browse files
legregoConstanceazasypkincee-chen
authored
[7.x] Removing circular dependency between spaces and security (#81891) (#83841)
* Removing circular dependency between spaces and security * Apply suggestions from code review Co-authored-by: Constance <constancecchen@users.noreply.github.com> Co-authored-by: Aleh Zasypkin <aleh.zasypkin@gmail.com> * Tests refactor - Reorganize top level describes into 3 space-based blocks into based on spaces: - space disabled - spaces plugin unavailable - space enabled (most previous tests go under this new block) with new beforeEach - wrote new tests for uncovered lines 58, 66-69 * Review1: address PR feedback * changing fake requests for alerts/actions * Fixing tests * fixing more tests * Additional testing and refactoring * Apply suggestions from code review Co-authored-by: Aleh Zasypkin <aleh.zasypkin@gmail.com> * Review 2: Address feedback * Make ESLint happy again Co-authored-by: Constance <constancecchen@users.noreply.github.com> Co-authored-by: Aleh Zasypkin <aleh.zasypkin@gmail.com> Co-authored-by: Constance Chen <constance.chen.3@gmail.com> Co-authored-by: Constance <constancecchen@users.noreply.github.com> Co-authored-by: Aleh Zasypkin <aleh.zasypkin@gmail.com> Co-authored-by: Constance Chen <constance.chen.3@gmail.com>
1 parent 537c065 commit 064fd8e

File tree

96 files changed

+2882
-2541
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

96 files changed

+2882
-2541
lines changed

x-pack/plugins/actions/server/lib/action_executor.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ const executeParams = {
3131
request: {} as KibanaRequest,
3232
};
3333

34-
const spacesMock = spacesServiceMock.createSetupContract();
34+
const spacesMock = spacesServiceMock.createStartContract();
3535
const loggerMock = loggingSystemMock.create().get();
3636
const getActionsClientWithRequest = jest.fn();
3737
actionExecutor.initialize({

x-pack/plugins/actions/server/lib/action_executor.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ import {
1515
ProxySettings,
1616
} from '../types';
1717
import { EncryptedSavedObjectsClient } from '../../../encrypted_saved_objects/server';
18-
import { SpacesServiceSetup } from '../../../spaces/server';
18+
import { SpacesServiceStart } from '../../../spaces/server';
1919
import { EVENT_LOG_ACTIONS } from '../plugin';
2020
import { IEvent, IEventLogger, SAVED_OBJECT_REL_PRIMARY } from '../../../event_log/server';
2121
import { ActionsClient } from '../actions_client';
2222
import { ActionExecutionSource } from './action_execution_source';
2323

2424
export interface ActionExecutorContext {
2525
logger: Logger;
26-
spaces?: SpacesServiceSetup;
26+
spaces?: SpacesServiceStart;
2727
getServices: GetServicesFunction;
2828
getActionsClientWithRequest: (
2929
request: KibanaRequest,

x-pack/plugins/actions/server/lib/task_runner_factory.test.ts

Lines changed: 27 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { TaskRunnerFactory } from './task_runner_factory';
1212
import { actionTypeRegistryMock } from '../action_type_registry.mock';
1313
import { actionExecutorMock } from './action_executor.mock';
1414
import { encryptedSavedObjectsMock } from '../../../encrypted_saved_objects/server/mocks';
15-
import { savedObjectsClientMock, loggingSystemMock } from 'src/core/server/mocks';
15+
import { savedObjectsClientMock, loggingSystemMock, httpServiceMock } from 'src/core/server/mocks';
1616
import { eventLoggerMock } from '../../../event_log/server/mocks';
1717
import { ActionTypeDisabledError } from './errors';
1818
import { actionsClientMock } from '../mocks';
@@ -70,7 +70,7 @@ const taskRunnerFactoryInitializerParams = {
7070
actionTypeRegistry,
7171
logger: loggingSystemMock.create().get(),
7272
encryptedSavedObjectsClient: mockedEncryptedSavedObjectsClient,
73-
getBasePath: jest.fn().mockReturnValue(undefined),
73+
basePathService: httpServiceMock.createBasePath(),
7474
getUnsecuredSavedObjectsClient: jest.fn().mockReturnValue(services.savedObjectsClient),
7575
};
7676

@@ -126,27 +126,23 @@ test('executes the task by calling the executor with proper parameters', async (
126126
expect(
127127
mockedEncryptedSavedObjectsClient.getDecryptedAsInternalUser
128128
).toHaveBeenCalledWith('action_task_params', '3', { namespace: 'namespace-test' });
129+
129130
expect(mockedActionExecutor.execute).toHaveBeenCalledWith({
130131
actionId: '2',
131132
params: { baz: true },
132-
request: {
133-
getBasePath: expect.any(Function),
133+
request: expect.objectContaining({
134134
headers: {
135135
// base64 encoded "123:abc"
136136
authorization: 'ApiKey MTIzOmFiYw==',
137137
},
138-
path: '/',
139-
route: { settings: {} },
140-
url: {
141-
href: '/',
142-
},
143-
raw: {
144-
req: {
145-
url: '/',
146-
},
147-
},
148-
},
138+
}),
149139
});
140+
141+
const [executeParams] = mockedActionExecutor.execute.mock.calls[0];
142+
expect(taskRunnerFactoryInitializerParams.basePathService.set).toHaveBeenCalledWith(
143+
executeParams.request,
144+
'/s/test'
145+
);
150146
});
151147

152148
test('cleans up action_task_params object', async () => {
@@ -255,24 +251,19 @@ test('uses API key when provided', async () => {
255251
expect(mockedActionExecutor.execute).toHaveBeenCalledWith({
256252
actionId: '2',
257253
params: { baz: true },
258-
request: {
259-
getBasePath: expect.anything(),
254+
request: expect.objectContaining({
260255
headers: {
261256
// base64 encoded "123:abc"
262257
authorization: 'ApiKey MTIzOmFiYw==',
263258
},
264-
path: '/',
265-
route: { settings: {} },
266-
url: {
267-
href: '/',
268-
},
269-
raw: {
270-
req: {
271-
url: '/',
272-
},
273-
},
274-
},
259+
}),
275260
});
261+
262+
const [executeParams] = mockedActionExecutor.execute.mock.calls[0];
263+
expect(taskRunnerFactoryInitializerParams.basePathService.set).toHaveBeenCalledWith(
264+
executeParams.request,
265+
'/s/test'
266+
);
276267
});
277268

278269
test(`doesn't use API key when not provided`, async () => {
@@ -297,21 +288,16 @@ test(`doesn't use API key when not provided`, async () => {
297288
expect(mockedActionExecutor.execute).toHaveBeenCalledWith({
298289
actionId: '2',
299290
params: { baz: true },
300-
request: {
301-
getBasePath: expect.anything(),
291+
request: expect.objectContaining({
302292
headers: {},
303-
path: '/',
304-
route: { settings: {} },
305-
url: {
306-
href: '/',
307-
},
308-
raw: {
309-
req: {
310-
url: '/',
311-
},
312-
},
313-
},
293+
}),
314294
});
295+
296+
const [executeParams] = mockedActionExecutor.execute.mock.calls[0];
297+
expect(taskRunnerFactoryInitializerParams.basePathService.set).toHaveBeenCalledWith(
298+
executeParams.request,
299+
'/s/test'
300+
);
315301
});
316302

317303
test(`throws an error when license doesn't support the action type`, async () => {

x-pack/plugins/actions/server/lib/task_runner_factory.ts

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,17 @@
55
*/
66

77
import { pick } from 'lodash';
8+
import type { Request } from '@hapi/hapi';
89
import { pipe } from 'fp-ts/lib/pipeable';
910
import { map, fromNullable, getOrElse } from 'fp-ts/lib/Option';
11+
import { addSpaceIdToPath } from '../../../spaces/server';
1012
import {
1113
Logger,
1214
SavedObjectsClientContract,
1315
KibanaRequest,
1416
SavedObjectReference,
15-
} from 'src/core/server';
17+
IBasePath,
18+
} from '../../../../../src/core/server';
1619
import { ActionExecutorContract } from './action_executor';
1720
import { ExecutorError } from './executor_error';
1821
import { RunContext } from '../../../task_manager/server';
@@ -21,7 +24,6 @@ import { ActionTypeDisabledError } from './errors';
2124
import {
2225
ActionTaskParams,
2326
ActionTypeRegistryContract,
24-
GetBasePathFunction,
2527
SpaceIdToNamespaceFunction,
2628
ActionTypeExecutorResult,
2729
} from '../types';
@@ -33,7 +35,7 @@ export interface TaskRunnerContext {
3335
actionTypeRegistry: ActionTypeRegistryContract;
3436
encryptedSavedObjectsClient: EncryptedSavedObjectsClient;
3537
spaceIdToNamespace: SpaceIdToNamespaceFunction;
36-
getBasePath: GetBasePathFunction;
38+
basePathService: IBasePath;
3739
getUnsecuredSavedObjectsClient: (request: KibanaRequest) => SavedObjectsClientContract;
3840
}
3941

@@ -64,7 +66,7 @@ export class TaskRunnerFactory {
6466
logger,
6567
encryptedSavedObjectsClient,
6668
spaceIdToNamespace,
67-
getBasePath,
69+
basePathService,
6870
getUnsecuredSavedObjectsClient,
6971
} = this.taskRunnerContext!;
7072

@@ -87,11 +89,12 @@ export class TaskRunnerFactory {
8789
requestHeaders.authorization = `ApiKey ${apiKey}`;
8890
}
8991

92+
const path = addSpaceIdToPath('/', spaceId);
93+
9094
// Since we're using API keys and accessing elasticsearch can only be done
9195
// via a request, we're faking one with the proper authorization headers.
92-
const fakeRequest = ({
96+
const fakeRequest = KibanaRequest.from(({
9397
headers: requestHeaders,
94-
getBasePath: () => getBasePath(spaceId),
9598
path: '/',
9699
route: { settings: {} },
97100
url: {
@@ -102,7 +105,9 @@ export class TaskRunnerFactory {
102105
url: '/',
103106
},
104107
},
105-
} as unknown) as KibanaRequest;
108+
} as unknown) as Request);
109+
110+
basePathService.set(fakeRequest, path);
106111

107112
let executorResult: ActionTypeExecutorResult<unknown>;
108113
try {

x-pack/plugins/actions/server/plugin.ts

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import {
2727
} from '../../encrypted_saved_objects/server';
2828
import { TaskManagerSetupContract, TaskManagerStartContract } from '../../task_manager/server';
2929
import { LicensingPluginSetup, LicensingPluginStart } from '../../licensing/server';
30-
import { SpacesPluginSetup, SpacesServiceSetup } from '../../spaces/server';
30+
import { SpacesPluginStart } from '../../spaces/server';
3131
import { PluginSetupContract as FeaturesPluginSetup } from '../../features/server';
3232
import { SecurityPluginSetup } from '../../security/server';
3333

@@ -109,7 +109,6 @@ export interface ActionsPluginsSetup {
109109
taskManager: TaskManagerSetupContract;
110110
encryptedSavedObjects: EncryptedSavedObjectsPluginSetup;
111111
licensing: LicensingPluginSetup;
112-
spaces?: SpacesPluginSetup;
113112
eventLog: IEventLogService;
114113
usageCollection?: UsageCollectionSetup;
115114
security?: SecurityPluginSetup;
@@ -119,6 +118,7 @@ export interface ActionsPluginsStart {
119118
encryptedSavedObjects: EncryptedSavedObjectsPluginStart;
120119
taskManager: TaskManagerStartContract;
121120
licensing: LicensingPluginStart;
121+
spaces?: SpacesPluginStart;
122122
}
123123

124124
const includedHiddenTypes = [
@@ -133,12 +133,10 @@ export class ActionsPlugin implements Plugin<Promise<PluginSetupContract>, Plugi
133133

134134
private readonly logger: Logger;
135135
private actionsConfig?: ActionsConfig;
136-
private serverBasePath?: string;
137136
private taskRunnerFactory?: TaskRunnerFactory;
138137
private actionTypeRegistry?: ActionTypeRegistry;
139138
private actionExecutor?: ActionExecutor;
140139
private licenseState: ILicenseState | null = null;
141-
private spaces?: SpacesServiceSetup;
142140
private security?: SecurityPluginSetup;
143141
private eventLogService?: IEventLogService;
144142
private eventLogger?: IEventLogger;
@@ -211,9 +209,7 @@ export class ActionsPlugin implements Plugin<Promise<PluginSetupContract>, Plugi
211209
});
212210
this.taskRunnerFactory = taskRunnerFactory;
213211
this.actionTypeRegistry = actionTypeRegistry;
214-
this.serverBasePath = core.http.basePath.serverBasePath;
215212
this.actionExecutor = actionExecutor;
216-
this.spaces = plugins.spaces?.spacesService;
217213
this.security = plugins.security;
218214

219215
registerBuiltInActionTypes({
@@ -339,7 +335,7 @@ export class ActionsPlugin implements Plugin<Promise<PluginSetupContract>, Plugi
339335
actionExecutor!.initialize({
340336
logger,
341337
eventLogger: this.eventLogger!,
342-
spaces: this.spaces,
338+
spaces: plugins.spaces?.spacesService,
343339
getActionsClientWithRequest,
344340
getServices: this.getServicesFactory(
345341
getScopedSavedObjectsClientWithoutAccessToActions,
@@ -359,12 +355,18 @@ export class ActionsPlugin implements Plugin<Promise<PluginSetupContract>, Plugi
359355
: undefined,
360356
});
361357

358+
const spaceIdToNamespace = (spaceId?: string) => {
359+
return plugins.spaces && spaceId
360+
? plugins.spaces.spacesService.spaceIdToNamespace(spaceId)
361+
: undefined;
362+
};
363+
362364
taskRunnerFactory!.initialize({
363365
logger,
364366
actionTypeRegistry: actionTypeRegistry!,
365367
encryptedSavedObjectsClient,
366-
getBasePath: this.getBasePath,
367-
spaceIdToNamespace: this.spaceIdToNamespace,
368+
basePathService: core.http.basePath,
369+
spaceIdToNamespace,
368370
getUnsecuredSavedObjectsClient: (request: KibanaRequest) =>
369371
this.getUnsecuredSavedObjectsClient(core.savedObjects, request),
370372
});
@@ -474,14 +476,6 @@ export class ActionsPlugin implements Plugin<Promise<PluginSetupContract>, Plugi
474476
};
475477
};
476478

477-
private spaceIdToNamespace = (spaceId?: string): string | undefined => {
478-
return this.spaces && spaceId ? this.spaces.spaceIdToNamespace(spaceId) : undefined;
479-
};
480-
481-
private getBasePath = (spaceId?: string): string => {
482-
return this.spaces && spaceId ? this.spaces.getBasePath(spaceId) : this.serverBasePath!;
483-
};
484-
485479
public stop() {
486480
if (this.licenseState) {
487481
this.licenseState.clean();

x-pack/plugins/actions/server/types.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ export { ActionTypeExecutorResult } from '../common';
2222
export type WithoutQueryAndParams<T> = Pick<T, Exclude<keyof T, 'query' | 'params'>>;
2323
export type GetServicesFunction = (request: KibanaRequest) => Services;
2424
export type ActionTypeRegistryContract = PublicMethodsOf<ActionTypeRegistry>;
25-
export type GetBasePathFunction = (spaceId?: string) => string;
2625
export type SpaceIdToNamespaceFunction = (spaceId?: string) => string | undefined;
2726
export type ActionTypeConfig = Record<string, unknown>;
2827
export type ActionTypeSecrets = Record<string, unknown>;

x-pack/plugins/alerts/server/plugin.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,6 @@ describe('Alerting Plugin', () => {
158158
getActionsClientWithRequest: jest.fn(),
159159
getActionsAuthorizationWithRequest: jest.fn(),
160160
},
161-
spaces: () => null,
162161
encryptedSavedObjects: encryptedSavedObjectsMock.createStart(),
163162
features: mockFeatures(),
164163
} as unknown) as AlertingPluginsStart

0 commit comments

Comments
 (0)