Skip to content

Commit

Permalink
feat: add attribute check
Browse files Browse the repository at this point in the history
Signed-off-by: tygao <[email protected]>
  • Loading branch information
raintygao committed Aug 18, 2023
1 parent a1cc4f7 commit 54a84dc
Showing 1 changed file with 127 additions and 124 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,12 @@ export class WorkspaceSavedObjectsClientWrapper {
}
private async validateSingleObjectPermissions(
id: string | undefined,
type: string,
request: OpenSearchDashboardsRequest,
permissionMode: WorkspacePermissionMode | WorkspacePermissionMode[],
type = WORKSPACE_TYPE
permissionMode: WorkspacePermissionMode | WorkspacePermissionMode[]
) {
//PermissionMode here is an array which is merged by workspace type required permission and other saved object required permission.

Check failure on line 74 in src/plugins/workspace/server/saved_objects/workspace_saved_objects_client_wrapper.ts

View workflow job for this annotation

GitHub Actions / Build and Verify on Linux (ciGroup1)

Expected exception block, space or tab after '//' in comment
//So we only need to do one permission check no matter its type.

Check failure on line 75 in src/plugins/workspace/server/saved_objects/workspace_saved_objects_client_wrapper.ts

View workflow job for this annotation

GitHub Actions / Build and Verify on Linux (ciGroup1)

Expected exception block, space or tab after '//' in comment
if (!id) {
return;
}
Expand All @@ -89,15 +91,15 @@ export class WorkspaceSavedObjectsClientWrapper {
}

private async validateMultiObjectsPermissions(
objects: string[] | undefined,
objects: Pick<SavedObject, 'id' | 'type'>[],

Check failure on line 94 in src/plugins/workspace/server/saved_objects/workspace_saved_objects_client_wrapper.ts

View workflow job for this annotation

GitHub Actions / Build and Verify on Linux (ciGroup1)

Array type using 'T[]' is forbidden for non-simple types. Use 'Array<T>' instead
request: OpenSearchDashboardsRequest,
permissionMode: WorkspacePermissionMode | WorkspacePermissionMode[],
type = WORKSPACE_TYPE
permissionMode: WorkspacePermissionMode | WorkspacePermissionMode[]
) {
if (!objects) {
return;
}
for (const id of objects) {
//PermissionMode here is an array which is merged by workspace type required permission and other saved object required permission.

Check failure on line 98 in src/plugins/workspace/server/saved_objects/workspace_saved_objects_client_wrapper.ts

View workflow job for this annotation

GitHub Actions / Build and Verify on Linux (ciGroup1)

Expected exception block, space or tab after '//' in comment
//So we only need to do one permission check no matter its type.

Check failure on line 99 in src/plugins/workspace/server/saved_objects/workspace_saved_objects_client_wrapper.ts

View workflow job for this annotation

GitHub Actions / Build and Verify on Linux (ciGroup1)

Expected exception block, space or tab after '//' in comment
let permitted = true;

for (const { id, type } of objects) {
if (
!(await this.permissionControl.validate(
request,
Expand All @@ -108,9 +110,35 @@ export class WorkspaceSavedObjectsClientWrapper {
this.formatWorkspacePermissionModeToStringArray(permissionMode)
))
) {
throw generateWorkspacePermissionError();
permitted = false;
break;
}
return permitted;
}
}

private async validateMultiWorkspacesPermissions(
workspacesIds: string[],
request: OpenSearchDashboardsRequest,
permissionMode: WorkspacePermissionMode | WorkspacePermissionMode[]
) {
const workspaces = workspacesIds.map((id) => ({ id, type: WORKSPACE_TYPE }));
return await this.validateMultiObjectsPermissions(workspaces, request, permissionMode);
}

private async validateWorkspaceAttributesPermitted<T = unknown>(
attributes: Partial<T> | T,
request: OpenSearchDashboardsRequest,
permissionMode: WorkspacePermissionMode | WorkspacePermissionMode[]
) {
if (isWorkspacesLikeAttributes(attributes)) {
return await this.validateMultiWorkspacesPermissions(
attributes.workspaces,
request,
permissionMode
);
}
return false;
}

private async validateAtLeastOnePermittedWorkspaces(
Expand All @@ -137,9 +165,7 @@ export class WorkspaceSavedObjectsClientWrapper {
break;
}
}
if (!permitted) {
throw generateWorkspacePermissionError();
}
return permitted;
}

/**
Expand All @@ -158,25 +184,23 @@ export class WorkspaceSavedObjectsClientWrapper {
id: string,
options: SavedObjectsDeleteOptions = {}
) => {
if (this.isRelatedToWorkspace(type)) {
await this.validateSingleObjectPermissions(id, wrapperOptions.request, [
WorkspacePermissionMode.Management,
]);
} else {
await this.validateSingleObjectPermissions(
id,
wrapperOptions.request,
[WorkspacePermissionMode.Write],
type
);
}

const objectToDeleted = await wrapperOptions.client.get(type, id, options);
await this.validateMultiObjectsPermissions(
objectToDeleted.workspaces,
const workspacePermitted = await this.validateMultiWorkspacesPermissions(
objectToDeleted.workspaces!,
wrapperOptions.request,
WorkspacePermissionMode.Management
);

if (!workspacePermitted) {
const objectsPermitted = await this.validateMultiObjectsPermissions(
[{ type, id }],
wrapperOptions.request,
[WorkspacePermissionMode.Management, WorkspacePermissionMode.Write]
);
if (!objectsPermitted) {
throw generateSavedObjectsPermissionError();
}
}
return await wrapperOptions.client.delete(type, id, options);
};

Expand All @@ -186,17 +210,17 @@ export class WorkspaceSavedObjectsClientWrapper {
attributes: Partial<T>,
options: SavedObjectsUpdateOptions = {}
): Promise<SavedObjectsUpdateResponse<T>> => {
if (this.isRelatedToWorkspace(type)) {
await this.validateSingleObjectPermissions(id, wrapperOptions.request, [
const workspacePermitted = await this.validateWorkspaceAttributesPermitted(
attributes,
wrapperOptions.request,
WorkspacePermissionMode.Management
);

if (!workspacePermitted) {
await this.validateSingleObjectPermissions(id, type, wrapperOptions.request, [
WorkspacePermissionMode.Management,
WorkspacePermissionMode.Write,
]);
} else {
await this.validateSingleObjectPermissions(
id,
wrapperOptions.request,
[WorkspacePermissionMode.Write],
type
);
}
return await wrapperOptions.client.update(type, id, attributes, options);
};
Expand All @@ -205,35 +229,21 @@ export class WorkspaceSavedObjectsClientWrapper {
objects: Array<SavedObjectsBulkUpdateObject<T>>,
options?: SavedObjectsBulkUpdateOptions
): Promise<SavedObjectsBulkUpdateResponse<T>> => {
const workspaceIds: string[] = [];
const nonWorkspaceObjects: Array<SavedObjectsBulkUpdateObject<T>> = [];
objects.forEach((obj) => {
if (this.isRelatedToWorkspace(obj.type)) {
workspaceIds.push(obj.id);
} else {
nonWorkspaceObjects.push(obj);
}
});

const permittedWorkspaceIds =
(await this.permissionControl.getPermittedWorkspaceIds(wrapperOptions.request, [
WorkspacePermissionMode.Management,
])) ?? [];
const workspacePermitted = workspaceIds.every((id) => permittedWorkspaceIds.includes(id));
if (!workspacePermitted) {
throw generateWorkspacePermissionError();
}
for (const object of objects) {
const workspacePermitted = await this.validateWorkspaceAttributesPermitted(
object.attributes,
wrapperOptions.request,
WorkspacePermissionMode.Management
);

// saved_objects
const objectsPermitted = await this.permissionControl.batchValidate(
wrapperOptions.request,
nonWorkspaceObjects.map((savedObj) => ({
...savedObj,
})),
[WorkspacePermissionMode.Write]
);
if (!objectsPermitted) {
throw generateSavedObjectsPermissionError();
if (!workspacePermitted) {
await this.validateSingleObjectPermissions(
object.id,
object.type,
wrapperOptions.request,
[WorkspacePermissionMode.Management, WorkspacePermissionMode.Write]
);
}
}

return await wrapperOptions.client.bulkUpdate(objects, options);
Expand All @@ -244,10 +254,14 @@ export class WorkspaceSavedObjectsClientWrapper {
options: SavedObjectsCreateOptions = {}
): Promise<SavedObjectsBulkResponse<T>> => {
if (options.workspaces) {
await this.validateMultiObjectsPermissions(options.workspaces, wrapperOptions.request, [
WorkspacePermissionMode.Write,
WorkspacePermissionMode.Management,
]);
const permitted = await this.validateMultiWorkspacesPermissions(
options.workspaces,
wrapperOptions.request,
[WorkspacePermissionMode.Write, WorkspacePermissionMode.Management]
);
if (!permitted) {
throw generateSavedObjectsPermissionError();
}
}
return await wrapperOptions.client.bulkCreate(objects, options);
};
Expand All @@ -257,13 +271,15 @@ export class WorkspaceSavedObjectsClientWrapper {
attributes: T,
options?: SavedObjectsCreateOptions
) => {
if (isWorkspacesLikeAttributes(attributes)) {
await this.validateMultiObjectsPermissions(
attributes.workspaces,
wrapperOptions.request,
WorkspacePermissionMode.Management
);
const workspacePermitted = await this.validateWorkspaceAttributesPermitted(
attributes,
wrapperOptions.request,
WorkspacePermissionMode.Management
);
if (!workspacePermitted) {
throw generateWorkspacePermissionError();
}

return await wrapperOptions.client.create(type, attributes, options);
};

Expand All @@ -272,73 +288,60 @@ export class WorkspaceSavedObjectsClientWrapper {
id: string,
options: SavedObjectsBaseOptions = {}
): Promise<SavedObject<T>> => {
if (this.isRelatedToWorkspace(type)) {
await this.validateSingleObjectPermissions(id, wrapperOptions.request, [
WorkspacePermissionMode.LibraryRead,
WorkspacePermissionMode.Management,
]);
} else {
await this.validateSingleObjectPermissions(
id,
wrapperOptions.request,
[WorkspacePermissionMode.Read],
type
);
}

const objectToGet = await wrapperOptions.client.get<T>(type, id, options);
await this.validateAtLeastOnePermittedWorkspaces(
const workspacePermitted = await this.validateAtLeastOnePermittedWorkspaces(
objectToGet.workspaces,
wrapperOptions.request,
WorkspacePermissionMode.Read
);

if (!workspacePermitted) {
await this.validateSingleObjectPermissions(id, type, wrapperOptions.request, [
WorkspacePermissionMode.LibraryRead,
WorkspacePermissionMode.LibraryWrite,
WorkspacePermissionMode.Management,
WorkspacePermissionMode.Read,
WorkspacePermissionMode.Write,
]);
}
return objectToGet;
};

const bulkGetWithWorkspacePermissionControl = async <T = unknown>(
objects: SavedObjectsBulkGetObject[] = [],
options: SavedObjectsBaseOptions = {}
): Promise<SavedObjectsBulkResponse<T>> => {
const workspaceIds: string[] = [];
const nonWorkspaceObjects: SavedObjectsBulkGetObject[] = [];
objects.forEach((obj) => {
if (this.isRelatedToWorkspace(obj.type)) {
workspaceIds.push(obj.id);
} else {
nonWorkspaceObjects.push(obj);
}
});

const permittedWorkspaceIds =
(await this.permissionControl.getPermittedWorkspaceIds(wrapperOptions.request, [
WorkspacePermissionMode.LibraryRead,
WorkspacePermissionMode.Management,
])) ?? [];
const workspacePermitted = workspaceIds.every((id) => permittedWorkspaceIds.includes(id));
if (!workspacePermitted) {
throw generateWorkspacePermissionError();
}

// saved_objects
const objectsPermitted = await this.permissionControl.batchValidate(
wrapperOptions.request,
nonWorkspaceObjects.map((savedObj) => ({
...savedObj,
})),
[WorkspacePermissionMode.Read]
);
if (!objectsPermitted) {
throw generateSavedObjectsPermissionError();
}

const nonWorkspacePermittedObjects = [];
const objectToBulkGet = await wrapperOptions.client.bulkGet<T>(objects, options);

for (const object of objectToBulkGet.saved_objects) {
await this.validateAtLeastOnePermittedWorkspaces(
const workspacePermitted = await this.validateAtLeastOnePermittedWorkspaces(
object.workspaces,
wrapperOptions.request,
WorkspacePermissionMode.Read
);
if (!workspacePermitted) {
nonWorkspacePermittedObjects.push(object);
}
}

if (nonWorkspacePermittedObjects.length > 0) {
const objectsPermitted = this.permissionControl.batchValidate(
wrapperOptions.request,
nonWorkspacePermittedObjects,
[
WorkspacePermissionMode.LibraryRead,
WorkspacePermissionMode.LibraryWrite,
WorkspacePermissionMode.Management,
WorkspacePermissionMode.Write,
WorkspacePermissionMode.Read,
]
);
if (!objectsPermitted) {
throw generateSavedObjectsPermissionError();
}
}

return objectToBulkGet;
};

Expand Down Expand Up @@ -424,7 +427,7 @@ export class WorkspaceSavedObjectsClientWrapper {
options: SavedObjectsAddToWorkspacesOptions = {}
) => {
// target workspaces
await this.validateMultiObjectsPermissions(targetWorkspaces, wrapperOptions.request, [
await this.validateMultiWorkspacesPermissions(targetWorkspaces, wrapperOptions.request, [
WorkspacePermissionMode.LibraryWrite,
WorkspacePermissionMode.Management,
]);
Expand Down

0 comments on commit 54a84dc

Please sign in to comment.