diff --git a/config/opensearch_dashboards.yml b/config/opensearch_dashboards.yml index 9c6c040433b4..80baeb5b4ae0 100644 --- a/config/opensearch_dashboards.yml +++ b/config/opensearch_dashboards.yml @@ -273,3 +273,9 @@ # Set the value of this setting to true to enable plugin augmentation on Dashboard # vis_augmenter.pluginAugmentationEnabled: true + +# Set the value to true enable workspace feature +# workspace.enabled: false +# Set the value to false to disable permission check on workspace +# Permission check depends on OpenSearch Dashboards has authentication enabled, set it to false if no authentication is configured +# workspace.permission.enabled: true \ No newline at end of file diff --git a/src/plugins/workspace/config.ts b/src/plugins/workspace/config.ts index 79412f5c02ee..70c87ac00cfc 100644 --- a/src/plugins/workspace/config.ts +++ b/src/plugins/workspace/config.ts @@ -7,6 +7,9 @@ import { schema, TypeOf } from '@osd/config-schema'; export const configSchema = schema.object({ enabled: schema.boolean({ defaultValue: false }), + permission: schema.object({ + enabled: schema.boolean({ defaultValue: true }), + }), }); -export type ConfigSchema = TypeOf; +export type WorkspacePluginConfigType = TypeOf; diff --git a/src/plugins/workspace/public/components/workspace_creator/workspace_creator.tsx b/src/plugins/workspace/public/components/workspace_creator/workspace_creator.tsx index 20b91f949422..f1ede156e5a4 100644 --- a/src/plugins/workspace/public/components/workspace_creator/workspace_creator.tsx +++ b/src/plugins/workspace/public/components/workspace_creator/workspace_creator.tsx @@ -17,6 +17,7 @@ export const WorkspaceCreator = () => { services: { application, notifications, http, workspaceClient }, } = useOpenSearchDashboards<{ workspaceClient: WorkspaceClient }>(); + const isPermissionEnabled = application?.capabilities.workspaces.permissionEnabled; const handleWorkspaceFormSubmit = useCallback( async (data: WorkspaceFormSubmitData) => { let result; @@ -76,6 +77,7 @@ export const WorkspaceCreator = () => { onSubmit={handleWorkspaceFormSubmit} opType={WORKSPACE_OP_TYPE_CREATE} permissionFirstRowDeletable + permissionEnabled={isPermissionEnabled} /> )} diff --git a/src/plugins/workspace/public/components/workspace_creator/workspace_form.tsx b/src/plugins/workspace/public/components/workspace_creator/workspace_form.tsx index 13618f13120f..0d6438aaf2b5 100644 --- a/src/plugins/workspace/public/components/workspace_creator/workspace_form.tsx +++ b/src/plugins/workspace/public/components/workspace_creator/workspace_form.tsx @@ -113,6 +113,7 @@ interface WorkspaceFormProps { defaultValues?: WorkspaceFormData; opType?: string; permissionFirstRowDeletable?: boolean; + permissionEnabled?: boolean; } export const WorkspaceForm = ({ @@ -121,6 +122,7 @@ export const WorkspaceForm = ({ defaultValues, opType, permissionFirstRowDeletable, + permissionEnabled, }: WorkspaceFormProps) => { const applications = useApplications(application); const workspaceNameReadOnly = defaultValues?.reserved; @@ -500,17 +502,19 @@ export const WorkspaceForm = ({ )} - - -

Members & permissions

-
- -
+ {permissionEnabled && ( + + +

Members & permissions

+
+ +
+ )} {opType === WORKSPACE_OP_TYPE_CREATE && ( diff --git a/src/plugins/workspace/public/components/workspace_updater/workspace_updater.tsx b/src/plugins/workspace/public/components/workspace_updater/workspace_updater.tsx index 46dd5f6a6e2b..42240d4536d7 100644 --- a/src/plugins/workspace/public/components/workspace_updater/workspace_updater.tsx +++ b/src/plugins/workspace/public/components/workspace_updater/workspace_updater.tsx @@ -46,6 +46,8 @@ export const WorkspaceUpdater = () => { services: { application, workspaces, notifications, http, workspaceClient }, } = useOpenSearchDashboards<{ workspaceClient: WorkspaceClient }>(); + const isPermissionEnabled = application?.capabilities.workspaces.permissionEnabled; + const currentWorkspace = useObservable(workspaces ? workspaces.currentWorkspace$ : of(null)); const hideDeleteButton = !!currentWorkspace?.reserved; // hide delete button for reserved workspace const [deleteWorkspaceModalVisible, setDeleteWorkspaceModalVisible] = useState(false); @@ -191,6 +193,7 @@ export const WorkspaceUpdater = () => { onSubmit={handleWorkspaceFormSubmit} defaultValues={currentWorkspaceFormData} opType={WORKSPACE_OP_TYPE_UPDATE} + permissionEnabled={isPermissionEnabled} /> )} diff --git a/src/plugins/workspace/server/integration_tests/routes.test.ts b/src/plugins/workspace/server/integration_tests/routes.test.ts index a83c908b7d10..8e711cb46c01 100644 --- a/src/plugins/workspace/server/integration_tests/routes.test.ts +++ b/src/plugins/workspace/server/integration_tests/routes.test.ts @@ -27,6 +27,9 @@ describe('workspace service', () => { osd: { workspace: { enabled: true, + permission: { + enabled: false, + }, }, }, }, diff --git a/src/plugins/workspace/server/plugin.ts b/src/plugins/workspace/server/plugin.ts index 798ea103101f..6a6f26856090 100644 --- a/src/plugins/workspace/server/plugin.ts +++ b/src/plugins/workspace/server/plugin.ts @@ -2,6 +2,8 @@ * Copyright OpenSearch Contributors * SPDX-License-Identifier: Apache-2.0 */ +import { Observable } from 'rxjs'; +import { first } from 'rxjs/operators'; import { PluginInitializerContext, CoreSetup, @@ -20,11 +22,12 @@ import { SavedObjectsPermissionControlContract, } from './permission_control/client'; import { registerPermissionCheckRoutes } from './permission_control/routes'; - +import { WorkspacePluginConfigType } from '../config'; export class WorkspacePlugin implements Plugin<{}, {}> { private readonly logger: Logger; private client?: IWorkspaceDBImpl; private permissionControl?: SavedObjectsPermissionControlContract; + private readonly config$: Observable; private proxyWorkspaceTrafficToRealHandler(setupDeps: CoreSetup) { /** @@ -44,31 +47,39 @@ export class WorkspacePlugin implements Plugin<{}, {}> { } constructor(initializerContext: PluginInitializerContext) { - this.logger = initializerContext.logger.get('plugins', 'workspace'); + this.logger = initializerContext.logger.get(); + this.config$ = initializerContext.config.create(); } public async setup(core: CoreSetup) { this.logger.debug('Setting up Workspaces service'); + const config: WorkspacePluginConfigType = await this.config$.pipe(first()).toPromise(); + const isPermissionControlEnabled = + config.permission.enabled === undefined ? true : config.permission.enabled; this.client = new WorkspaceClientWithSavedObject(core, this.logger); await this.client.setup(core); - this.permissionControl = new SavedObjectsPermissionControl(this.logger); - registerPermissionCheckRoutes({ - http: core.http, - permissionControl: this.permissionControl, - }); + this.logger.info('Workspace permission control enabled:' + isPermissionControlEnabled); + if (isPermissionControlEnabled) { + this.permissionControl = new SavedObjectsPermissionControl(this.logger); - const workspaceSavedObjectsClientWrapper = new WorkspaceSavedObjectsClientWrapper( - this.permissionControl - ); + registerPermissionCheckRoutes({ + http: core.http, + permissionControl: this.permissionControl, + }); - core.savedObjects.addClientWrapper( - 0, - WORKSPACE_SAVED_OBJECTS_CLIENT_WRAPPER_ID, - workspaceSavedObjectsClientWrapper.wrapperFactory - ); + const workspaceSavedObjectsClientWrapper = new WorkspaceSavedObjectsClientWrapper( + this.permissionControl + ); + + core.savedObjects.addClientWrapper( + 0, + WORKSPACE_SAVED_OBJECTS_CLIENT_WRAPPER_ID, + workspaceSavedObjectsClientWrapper.wrapperFactory + ); + } this.proxyWorkspaceTrafficToRealHandler(core); @@ -82,7 +93,12 @@ export class WorkspacePlugin implements Plugin<{}, {}> { new SavedObjectsClient(repositoryFactory.createInternalRepository()) ); - core.capabilities.registerProvider(() => ({ workspaces: { enabled: true } })); + core.capabilities.registerProvider(() => ({ + workspaces: { + enabled: true, + permissionEnabled: isPermissionControlEnabled, + }, + })); return { client: this.client,