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

Removed agent RBAC filters from dashboard queries #6945

Merged
merged 14 commits into from
Sep 2, 2024
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ All notable changes to the Wazuh app project will be documented in this file.

- Changed the registration id of the Settings application for compatibility with Opensearch Dashboard 2.16.0 [#6938](https:/wazuh/wazuh-dashboard-plugins/pull/6938)

### Removed

- Removed agent RBAC filters from dashboard queries [#6945](https:/wazuh/wazuh-dashboard-plugins/pull/6945)

## Wazuh v4.9.1 - OpenSearch Dashboards 2.13.0 - Revision 00

### Added
Expand Down
Original file line number Diff line number Diff line change
@@ -1,129 +1,130 @@
import { useDataSource } from './use-data-source';
import { renderHook } from '@testing-library/react-hooks';
import {
tDataSourceRepository,
tFilter,
PatternDataSource,
tParsedIndexPattern
import {
tDataSourceRepository,
tFilter,
PatternDataSource,
tParsedIndexPattern,
} from '../index';
import { IndexPatternsService, IndexPattern } from '../../../../../../../src/plugins/data/common';
import {
IndexPatternsService,
IndexPattern,
} from '../../../../../../../src/plugins/data/common';

jest.mock('../../../../kibana-services', () => ({
...(jest.requireActual('../../../../kibana-services') as object),
getDataPlugin: () => ({
// mock indexPatterns getter
indexPatterns: {
get: jest.fn().mockResolvedValue({
fields: {
replaceAll: jest.fn(),
map: jest.fn().mockReturnValue([]),
},
getScriptedFields: jest.fn().mockReturnValue([]),
}),
getFieldsForIndexPattern: jest.fn().mockResolvedValue([]),
updateSavedObject: jest.fn().mockResolvedValue({}),
...(jest.requireActual('../../../../kibana-services') as object),
getDataPlugin: () => ({
// mock indexPatterns getter
indexPatterns: {
get: jest.fn().mockResolvedValue({
fields: {
replaceAll: jest.fn(),
map: jest.fn().mockReturnValue([]),
},
query: {
filterManager: {
getFilters: jest.fn().mockReturnValue([]),
setFilters: jest.fn(),
getUpdates$: jest.fn().mockReturnValue({
subscribe: jest.fn()
})
}
}
}),
getScriptedFields: jest.fn().mockReturnValue([]),
}),
getFieldsForIndexPattern: jest.fn().mockResolvedValue([]),
updateSavedObject: jest.fn().mockResolvedValue({}),
},
query: {
filterManager: {
getFilters: jest.fn().mockReturnValue([]),
setFilters: jest.fn(),
getUpdates$: jest.fn().mockReturnValue({
subscribe: jest.fn(),
}),
},
},
}),
}));

const mockedGetFilters = jest.fn().mockReturnValue([]);

class DataSourceMocked implements PatternDataSource {
constructor(public id: string, public title: string) {
this.id = id;
this.title = title;
}
fields: any[];
patternService: IndexPatternsService;
indexPattern: IndexPattern;
defaultFixedFilters: tFilter[];
filters: tFilter[];
init = jest.fn();
select = jest.fn();
fetch = jest.fn();
getFilters = mockedGetFilters;
setFilters = jest.fn();
getFields = mockedGetFilters
getFixedFilters = mockedGetFilters
getFetchFilters = mockedGetFilters
toJSON(): tParsedIndexPattern {
return {
id: this.id,
title: this.title,
} as tParsedIndexPattern;
}
getClusterManagerFilters = mockedGetFilters
getPinnedAgentFilter = mockedGetFilters
getExcludeManagerFilter = mockedGetFilters
getAllowAgentsFilter = mockedGetFilters
constructor(public id: string, public title: string) {
this.id = id;
this.title = title;
}
fields: any[];
patternService: IndexPatternsService;
indexPattern: IndexPattern;
defaultFixedFilters: tFilter[];
filters: tFilter[];
init = jest.fn();
select = jest.fn();
fetch = jest.fn();
getFilters = mockedGetFilters;
setFilters = jest.fn();
getFields = mockedGetFilters;
getFixedFilters = mockedGetFilters;
getFetchFilters = mockedGetFilters;
toJSON(): tParsedIndexPattern {
return {
id: this.id,
title: this.title,
} as tParsedIndexPattern;
}
getClusterManagerFilters = mockedGetFilters;
getPinnedAgentFilter = mockedGetFilters;
getExcludeManagerFilter = mockedGetFilters;
}

class ExampleRepository implements tDataSourceRepository<tParsedIndexPattern> {
getDefault = jest.fn();
setDefault = jest.fn();
get = jest.fn();
getAll = jest.fn();
getDefault = jest.fn();
setDefault = jest.fn();
get = jest.fn();
getAll = jest.fn();
}

describe('useDataSource hook', () => {
it('shoudl throw ERROR when the repository is not defined', () => {
try {
renderHook(() =>
useDataSource({
DataSource: DataSourceMocked,
repository: undefined as any,
}),
);
} catch (error) {
expect(error).toBeDefined();
expect(error.message).toBe('DataSource and repository are required');
}
});

it('shoudl throw ERROR when the repository is not defined', () => {

try {
renderHook(() => useDataSource({
DataSource: DataSourceMocked,
repository: undefined as any
}));
} catch(error){
expect(error).toBeDefined();
expect(error.message).toBe('DataSource and repository are required');
}

})

it('should throw ERROR when the DataSource is not defined', () => {

try {
renderHook(() => useDataSource({
DataSource: undefined as any,
repository: new ExampleRepository()
}));
} catch(error){
expect(error).toBeDefined();
expect(error.message).toBe('DataSource and repository are required');
}

})

// FIXME:
it.skip('should initialize the hook with only receiving the dataSource and repository', async () => {
const repository = new ExampleRepository();
const indexMocked = {
id: 'test',
title: 'Test'
}
jest.spyOn(repository, 'getAll').mockResolvedValueOnce([indexMocked]);
jest.spyOn(repository, 'getDefault').mockResolvedValueOnce(indexMocked);
const { result, waitForNextUpdate } = renderHook(() => useDataSource({
DataSource: DataSourceMocked,
repository
}));
// wait for the promise to resolve
await waitForNextUpdate();
expect(result.current.isLoading).toBeFalsy();
expect(result.current.dataSource).toBeDefined();
expect(result.current.dataSource?.id).toBe('test');
expect(result.current.dataSource?.title).toBe('Test');
})

it('should throw ERROR when the DataSource is not defined', () => {
try {
renderHook(() =>
useDataSource({
DataSource: undefined as any,
repository: new ExampleRepository(),
}),
);
} catch (error) {
expect(error).toBeDefined();
expect(error.message).toBe('DataSource and repository are required');
}
});

})
// FIXME:
it.skip('should initialize the hook with only receiving the dataSource and repository', async () => {
const repository = new ExampleRepository();
const indexMocked = {
id: 'test',
title: 'Test',
};
jest.spyOn(repository, 'getAll').mockResolvedValueOnce([indexMocked]);
jest.spyOn(repository, 'getDefault').mockResolvedValueOnce(indexMocked);
const { result, waitForNextUpdate } = renderHook(() =>
useDataSource({
DataSource: DataSourceMocked,
repository,
}),
);
// wait for the promise to resolve
await waitForNextUpdate();
expect(result.current.isLoading).toBeFalsy();
expect(result.current.dataSource).toBeDefined();
expect(result.current.dataSource?.id).toBe('test');
expect(result.current.dataSource?.title).toBe('Test');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ class DataSourceMocked implements PatternDataSource {
getClusterManagerFilters = mockedGetFilters;
getPinnedAgentFilter = mockedGetFilters;
getExcludeManagerFilter = mockedGetFilters;
getAllowAgentsFilter = mockedGetFilters;
}

const createFilter = (id: string, value: string, index: string): tFilter => {
Expand Down Expand Up @@ -374,27 +373,6 @@ describe('PatternDataSourceFilterManager', () => {
expect(filter.length).toBe(0);
});

it('should return the filters to fetch the data merging the filters stored and the allowed agents filter', () => {
(store.getState as jest.Mock).mockReturnValue({
appStateReducers: {
allowedAgents: ['001'],
},
});
const filter =
PatternDataSourceFilterManager.getAllowAgentsFilter('index-title');
expect(filter.length).toBe(1);
expect(filter[0].meta.controlledBy).toBe(AUTHORIZED_AGENTS);
});

it('should return the filters to fetch the data merging the filters stored without the allowed agents filter when is not defined', () => {
(store.getState as jest.Mock).mockReturnValue({
appStateReducers: {},
});
const filter =
PatternDataSourceFilterManager.getAllowAgentsFilter('index-title');
expect(filter.length).toBe(0);
});

// FIXME:
it.skip('should return the fixed filters merged with the pinned agent filter when correspond', () => {
// mock store.getState
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,47 +40,6 @@ export function getFilterExcludeManager(indexPatternId: string) {
};
}

/**
* Get the filter that restrict the search to the allowed agents
* @param agentsIds
* @param indexPatternId
* @returns
*/
export function getFilterAllowedAgents(
agentsIds: string[],
indexPatternId: string,
) {
const field = AGENT_ID_KEY;
return {
meta: {
index: indexPatternId,
type: 'phrases',
key: field,
value: agentsIds.toString(),
params: agentsIds,
alias: null,
negate: false,
disabled: false,
controlledBy: AUTHORIZED_AGENTS,
},
query: {
bool: {
should: agentsIds.map(id => {
return {
match_phrase: {
[field]: id,
},
};
}),
minimum_should_match: 1,
},
},
$state: {
store: 'appState',
},
};
}

export enum FILTER_OPERATOR {
IS = 'is',
IS_NOT = 'is not',
Expand Down Expand Up @@ -359,23 +318,6 @@ export class PatternDataSourceFilterManager
return [];
}

/**
* Return the allowed agents related to the user permissions to read data from agents in the
API server
*/
static getAllowAgentsFilter(indexPatternId: string): tFilter[] {
const allowedAgents =
store.getState().appStateReducers?.allowedAgents || [];
if (allowedAgents.length > 0) {
const allowAgentsFilter = getFilterAllowedAgents(
allowedAgents,
indexPatternId,
) as tFilter;
return [allowAgentsFilter];
}
return [];
}

/******************************************************************/
/********************** FILTERS FACTORY ***************************/
/******************************************************************/
Expand Down
Loading
Loading