Skip to content

Commit

Permalink
delete data source permission
Browse files Browse the repository at this point in the history
Signed-off-by: Qxisylolo <[email protected]>
  • Loading branch information
Qxisylolo committed Dec 31, 2024
1 parent 0561497 commit 225c6c2
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 277 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -690,7 +690,6 @@ describe('WorkspaceSavedObjectsClientWrapper', () => {
},
]);
});

it('should call permission validateSavedObjectsACL with object', async () => {
const { wrapper, permissionControlMock } = generateWorkspaceSavedObjectsClientWrapper();
try {
Expand Down Expand Up @@ -731,197 +730,6 @@ describe('WorkspaceSavedObjectsClientWrapper', () => {
{}
);
});
it('should validate data source or data connection workspace field', async () => {
const { wrapper } = generateWorkspaceSavedObjectsClientWrapper();
const result1 = await wrapper.bulkGet([
{
type: 'data-source',
id: 'workspace-1-data-source',
},
]);

expect(result1.saved_objects).toEqual([
{
id: 'workspace-1-data-source',
type: 'data-source',
attributes: {},
error: {
error: 'Forbidden',
message: 'Invalid data source permission, please associate it to current workspace',
statusCode: 403,
},
workspaces: [],
references: [],
},
]);

const result2 = await wrapper.bulkGet([
{
type: 'data-connection',
id: 'workspace-1-data-connection',
},
]);

expect(result2.saved_objects).toEqual([
{
type: 'data-connection',
id: 'workspace-1-data-connection',
attributes: {},
error: {
error: 'Forbidden',
message: 'Invalid data source permission, please associate it to current workspace',
statusCode: 403,
},
workspaces: [],
references: [],
},
]);

let result = await wrapper.bulkGet([
{
type: 'data-source',
id: 'workspace-2-data-source',
},
]);
expect(result).toEqual({
saved_objects: [
{
attributes: {
title: 'Workspace 2 data source',
},
id: 'workspace-2-data-source',
type: 'data-source',
workspaces: ['mock-request-workspace-id'],
references: [],
},
],
});

result = await await wrapper.bulkGet([
{
type: 'data-connection',
id: 'workspace-2-data-connection',
},
]);
expect(result).toEqual({
saved_objects: [
{
attributes: {
title: 'Workspace 2 data connection',
},
id: 'workspace-2-data-connection',
type: 'data-connection',
workspaces: ['mock-request-workspace-id'],
references: [],
},
],
});
});

it('should not validate data source or data connection when not in workspace', async () => {
const { wrapper, requestMock } = generateWorkspaceSavedObjectsClientWrapper();
updateWorkspaceState(requestMock, { requestWorkspaceId: undefined });
let result = await wrapper.bulkGet([
{
type: 'data-source',
id: 'workspace-1-data-source',
},
]);
expect(result).toEqual({
saved_objects: [
{
attributes: {
title: 'Workspace 1 data source',
},
id: 'workspace-1-data-source',
type: 'data-source',
workspaces: ['workspace-1'],
references: [],
},
],
});

result = await wrapper.bulkGet([
{
type: 'data-connection',
id: 'workspace-1-data-connection',
},
]);
expect(result).toEqual({
saved_objects: [
{
attributes: {
title: 'Workspace 1 data connection',
},
id: 'workspace-1-data-connection',
type: 'data-connection',
workspaces: ['workspace-1'],
references: [],
},
],
});
});

it('should throw permission error when tried to bulk get global data source or data connection', async () => {
const { wrapper, requestMock } = generateWorkspaceSavedObjectsClientWrapper();
updateWorkspaceState(requestMock, { requestWorkspaceId: undefined });

const result = await wrapper.bulkGet([{ type: 'data-source', id: 'global-data-source' }]);
expect(result.saved_objects).toEqual([
{
attributes: {},
id: 'global-data-source',
type: 'data-source',
references: [],
workspaces: [],
error: {
error: 'Forbidden',
message: 'Invalid data source permission, please associate it to current workspace',
statusCode: 403,
},
},
]);
});

it('should throw permission error when tried to bulk get a empty workspace global data source or data connection', async () => {
const { wrapper, requestMock } = generateWorkspaceSavedObjectsClientWrapper();
updateWorkspaceState(requestMock, { requestWorkspaceId: undefined });
const result = await wrapper.bulkGet([
{ type: 'data-source', id: 'global-data-source-empty-workspaces' },
]);
expect(result.saved_objects).toEqual([
{
attributes: {},
id: 'global-data-source-empty-workspaces',
type: 'data-source',
references: [],
workspaces: [],
error: {
error: 'Forbidden',
message: 'Invalid data source permission, please associate it to current workspace',
statusCode: 403,
},
},
]);

const result1 = await wrapper.bulkGet([
{ type: 'data-connection', id: 'global-data-connection-empty-workspaces' },
]);
expect(result1.saved_objects).toEqual([
{
attributes: {},
type: 'data-connection',
id: 'global-data-connection-empty-workspaces',
references: [],
workspaces: [],
error: {
error: 'Forbidden',
message: 'Invalid data source permission, please associate it to current workspace',
statusCode: 403,
},
},
]);
});
});
describe('find', () => {
it('should call client.find with consistent params when ACLSearchParams and workspaceOperator not provided', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,6 @@ const generateSavedObjectsPermissionError = () =>
)
);

const generateDataSourcePermissionError = () =>
SavedObjectsErrorHelpers.decorateForbiddenError(
new Error(
i18n.translate('workspace.saved_objects.data_source.invalidate', {
defaultMessage: 'Invalid data source permission, please associate it to current workspace',
})
)
);
const generateOSDAdminPermissionError = () =>
SavedObjectsErrorHelpers.decorateForbiddenError(
new Error(
Expand Down Expand Up @@ -202,32 +194,6 @@ export class WorkspaceSavedObjectsClientWrapper {
return hasPermission;
}

// Data source is a workspace level object, validate if the request has access to the data source within the requested workspace.
private validateDataSourcePermissions = (
object: SavedObject,
request: OpenSearchDashboardsRequest
) => {
const requestWorkspaceId = getWorkspaceState(request).requestWorkspaceId;
// Deny access if the object is a global data source (no workspaces assigned)
if (!object.workspaces || object.workspaces.length === 0) {
return false;
}
/**
* Allow access if no specific workspace is requested.
* This typically occurs when retrieving data sources or performing operations
* that don't require a specific workspace, such as pages within the
* Data Administration navigation group that include a data source picker.
*/
if (!requestWorkspaceId) {
return true;
}
/*
* Allow access if the requested workspace matches one of the object's assigned workspaces
* This ensures that the user can only access data sources within their current workspace
*/
return object.workspaces.includes(requestWorkspaceId);
};

private getWorkspaceTypeEnabledClient(request: OpenSearchDashboardsRequest) {
return this.getScopedClient?.(request, {
includedHiddenTypes: [WORKSPACE_TYPE],
Expand Down Expand Up @@ -487,65 +453,28 @@ export class WorkspaceSavedObjectsClientWrapper {
let flag = true;
const processedObjects = await Promise.all(
objectToBulkGet.saved_objects.map(async (object) => {
try {
if (validateIsWorkspaceDataSourceAndConnectionObjectType(object.type)) {
const hasPermission = this.validateDataSourcePermissions(
object,
wrapperOptions.request
);
if (!hasPermission) {
flag = false;
ACLAuditor?.increment(ACLAuditorStateKey.VALIDATE_FAILURE, 1);
return {
...object,
workspaces: [],
attributes: {} as T,
error: {
...generateDataSourcePermissionError().output.payload,
statusCode: 403,
},
};
}
}

if (
!(await this.validateWorkspacesAndSavedObjectsPermissions(
object,
wrapperOptions.request,
[WorkspacePermissionMode.LibraryRead, WorkspacePermissionMode.LibraryWrite],
[WorkspacePermissionMode.Write, WorkspacePermissionMode.Read],
false
))
) {
flag = false;
ACLAuditor?.increment(ACLAuditorStateKey.VALIDATE_FAILURE, 1);
return {
...object,
workspaces: [],
attributes: {} as T,
error: {
...generateSavedObjectsPermissionError().output.payload,
statusCode: 403,
},
};
}
return object;
} catch (error) {
if (
!(await this.validateWorkspacesAndSavedObjectsPermissions(
object,
wrapperOptions.request,
[WorkspacePermissionMode.LibraryRead, WorkspacePermissionMode.LibraryWrite],
[WorkspacePermissionMode.Write, WorkspacePermissionMode.Read],
false
))
) {
flag = false;
ACLAuditor?.increment(ACLAuditorStateKey.VALIDATE_FAILURE, 1);

const formattedError = {
message: error?.message || 'unexpected error',
error: error?.error,
statusCode: error.statusCode,
};
return {
...object,
workspaces: [],
attributes: {} as T,
error: formattedError,
error: {
...generateSavedObjectsPermissionError().output.payload,
statusCode: 403,
},
};
}
return object;
})
);

Expand Down

0 comments on commit 225c6c2

Please sign in to comment.