Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Workspace]Deny get or bulkGet for global data source #8043

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions changelogs/fragments/8043.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
feat:
- [Workspace]Deny get or bulkGet for global data source ([#8043](https://github.com/opensearch-project/OpenSearch-Dashboards/pull/8043))
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ const generateWorkspaceSavedObjectsClientWrapper = (role = NO_DASHBOARD_ADMIN) =
id: 'global-data-source',
attributes: { title: 'Global data source' },
},
{
type: DATA_SOURCE_SAVED_OBJECT_TYPE,
id: 'global-data-source-empty-workspaces',
attributes: { title: 'Global data source empty workspaces' },
workspaces: [],
},
{
type: DATA_SOURCE_SAVED_OBJECT_TYPE,
id: 'workspace-1-data-source',
Expand Down Expand Up @@ -620,6 +626,33 @@ describe('WorkspaceSavedObjectsClientWrapper', () => {
workspaces: ['workspace-1'],
});
});

it('should throw permission error when tried to access a global data source', async () => {
const { wrapper } = generateWorkspaceSavedObjectsClientWrapper();
let errorCatched;
try {
await wrapper.get('data-source', 'global-data-source');
} catch (e) {
errorCatched = e;
}
expect(errorCatched?.message).toEqual(
'Invalid data source permission, please associate it to current workspace'
);
});

it('should throw permission error when tried to access a empty workspaces global data source', async () => {
const { wrapper, requestMock } = generateWorkspaceSavedObjectsClientWrapper();
updateWorkspaceState(requestMock, { requestWorkspaceId: undefined });
let errorCatched;
try {
await wrapper.get('data-source', 'global-data-source-empty-workspaces');
} catch (e) {
errorCatched = e;
}
expect(errorCatched?.message).toEqual(
'Invalid data source permission, please associate it to current workspace'
);
});
});
describe('bulk get', () => {
it("should call permission validate with object's workspace and throw permission error", async () => {
Expand Down Expand Up @@ -744,6 +777,36 @@ describe('WorkspaceSavedObjectsClientWrapper', () => {
],
});
});

it('should throw permission error when tried to bulk get global data source', async () => {
const { wrapper, requestMock } = generateWorkspaceSavedObjectsClientWrapper();
updateWorkspaceState(requestMock, { requestWorkspaceId: undefined });
let errorCatched;
try {
await wrapper.bulkGet([{ type: 'data-source', id: 'global-data-source' }]);
} catch (e) {
errorCatched = e;
}
expect(errorCatched?.message).toEqual(
'Invalid data source permission, please associate it to current workspace'
);
});

it('should throw permission error when tried to bulk get a empty workspace global data source', async () => {
const { wrapper, requestMock } = generateWorkspaceSavedObjectsClientWrapper();
updateWorkspaceState(requestMock, { requestWorkspaceId: undefined });
let errorCatched;
try {
await wrapper.bulkGet([
{ type: 'data-source', id: 'global-data-source-empty-workspaces' },
]);
} catch (e) {
errorCatched = e;
}
expect(errorCatched?.message).toEqual(
'Invalid data source permission, please associate it to current workspace'
);
});
});
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 @@ -204,7 +204,24 @@ export class WorkspaceSavedObjectsClientWrapper {
request: OpenSearchDashboardsRequest
) => {
const requestWorkspaceId = getWorkspaceState(request).requestWorkspaceId;
return !requestWorkspaceId || !!object.workspaces?.includes(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) {
Expand Down
Loading