Skip to content

Commit

Permalink
Support disable permission check on workspace (opensearch-project#228)
Browse files Browse the repository at this point in the history
* support disable permission check for workspace

Signed-off-by: Hailong Cui <ihailong@amazon.com>

* fix typos

Signed-off-by: Hailong Cui <ihailong@amazon.com>

---------

Signed-off-by: Hailong Cui <ihailong@amazon.com>
  • Loading branch information
Hailong-am committed Oct 16, 2023
1 parent dd486e9 commit 2964934
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 28 deletions.
6 changes: 6 additions & 0 deletions config/opensearch_dashboards.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
5 changes: 4 additions & 1 deletion src/plugins/workspace/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<typeof configSchema>;
export type WorkspacePluginConfigType = TypeOf<typeof configSchema>;
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -76,6 +77,7 @@ export const WorkspaceCreator = () => {
onSubmit={handleWorkspaceFormSubmit}
opType={WORKSPACE_OP_TYPE_CREATE}
permissionFirstRowDeletable
permissionEnabled={isPermissionEnabled}
/>
)}
</EuiPageContent>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ interface WorkspaceFormProps {
defaultValues?: WorkspaceFormData;
opType?: string;
permissionFirstRowDeletable?: boolean;
permissionEnabled?: boolean;
}

export const WorkspaceForm = ({
Expand All @@ -121,6 +122,7 @@ export const WorkspaceForm = ({
defaultValues,
opType,
permissionFirstRowDeletable,
permissionEnabled,
}: WorkspaceFormProps) => {
const applications = useApplications(application);
const workspaceNameReadOnly = defaultValues?.reserved;
Expand Down Expand Up @@ -500,17 +502,19 @@ export const WorkspaceForm = ({
</EuiPanel>
)}
<EuiSpacer />
<EuiPanel>
<EuiTitle size="s">
<h2>Members & permissions</h2>
</EuiTitle>
<WorkspacePermissionSettingPanel
errors={formErrors.permissions}
value={permissionSettings}
onChange={setPermissionSettings}
firstRowDeletable={permissionFirstRowDeletable}
/>
</EuiPanel>
{permissionEnabled && (
<EuiPanel>
<EuiTitle size="s">
<h2>Members & permissions</h2>
</EuiTitle>
<WorkspacePermissionSettingPanel
errors={formErrors.permissions}
value={permissionSettings}
onChange={setPermissionSettings}
firstRowDeletable={permissionFirstRowDeletable}
/>
</EuiPanel>
)}
<EuiSpacer />
<EuiText textAlign="right">
{opType === WORKSPACE_OP_TYPE_CREATE && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -191,6 +193,7 @@ export const WorkspaceUpdater = () => {
onSubmit={handleWorkspaceFormSubmit}
defaultValues={currentWorkspaceFormData}
opType={WORKSPACE_OP_TYPE_UPDATE}
permissionEnabled={isPermissionEnabled}
/>
)}
</EuiPageContent>
Expand Down
3 changes: 3 additions & 0 deletions src/plugins/workspace/server/integration_tests/routes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ describe('workspace service', () => {
osd: {
workspace: {
enabled: true,
permission: {
enabled: false,
},
},
},
},
Expand Down
48 changes: 32 additions & 16 deletions src/plugins/workspace/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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<WorkspacePluginConfigType>;

private proxyWorkspaceTrafficToRealHandler(setupDeps: CoreSetup) {
/**
Expand All @@ -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<WorkspacePluginConfigType>();
}

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);

Expand All @@ -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,
Expand Down

0 comments on commit 2964934

Please sign in to comment.