Skip to content

Commit

Permalink
Fix ability to filter form FIM details (#7119)
Browse files Browse the repository at this point in the history
* fix(fim): fix ability to filter from flyout details in FIM inventory

- Fix FIM inventory flyout filters for Files and Registry tabs
- Add ability to filter from Last analysis and Last modified fields from
  Registry details
- Add ability to select the visible columns in the Files and Registry
  tables
- Add to Files table the columns: date (hidden), md5 (hidden), sha1 (hidden), sha256 (hidden)
- Add to Registry table the columns: date (hidden)
- Renamed Last Modified to Last modified in the Files table

* chore(changelog): add entry
  • Loading branch information
Desvelao authored Oct 24, 2024
1 parent 5fb561b commit 9157e9a
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 99 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ All notable changes to the Wazuh app project will be documented in this file.
- Support for Wazuh 4.10.0
- Added sample data for YARA [#6964](https://github.com/wazuh/wazuh-dashboard-plugins/issues/6964)
- Added a custom filter and visualization for vulnerability.under_evaluation field [#6968](https://github.com/wazuh/wazuh-dashboard-plugins/issues/6968) [#7044](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7044) [#7046](https://github.com/wazuh/wazuh-dashboard-plugins/issues/7046)
- Added ability to filter from File Integrity Monitoring registry inventory [#7119](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7119)
- Added new field columns and ability to select the visible fields in the File Integrity Monitoring Files and Registry tables [#7119](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7119)

### Changed

Expand All @@ -33,6 +35,7 @@ All notable changes to the Wazuh app project will be documented in this file.
- Fixed filter management to prevent hiding when adding multiple filters [#7077](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7077)
- Fixed vulnerabilities inventory table scroll [#7118](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7118)
- Fixed the filter are displayed cropped on screens of 575px to 767px in vulnerability detection module [#7047](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7047)
- Fixed ability to filter from files inventory details flyout of File Integrity Monitoring [#7119](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7119)

### Removed

Expand Down
55 changes: 6 additions & 49 deletions plugins/main/public/components/agents/fim/inventory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import { InventoryTable, RegistryTable } from './inventory/';
import { WzRequest } from '../../../react-services/wz-request';
import { getToasts } from '../../../kibana-services';
import { ICustomBadges } from '../../wz-search-bar/components';
import { filtersToObject } from '../../wz-search-bar';
import { UI_LOGGER_LEVELS } from '../../../../common/constants';
import {
UI_ERROR_SEVERITIES,
Expand All @@ -42,7 +41,6 @@ import { webDocumentationLink } from '../../../../common/services/web_documentat
export class Inventory extends Component {
_isMount = false;
state: {
filters: [];
selectedTabId: 'files' | 'registry';
totalItemsFile: number;
totalItemsRegistry: number;
Expand All @@ -57,7 +55,6 @@ export class Inventory extends Component {
constructor(props) {
super(props);
this.state = {
filters: [],
syscheck: [],
selectedTabId: 'files',
totalItemsFile: 0,
Expand All @@ -66,7 +63,6 @@ export class Inventory extends Component {
customBadges: [],
isConfigured: false,
};
this.onFiltersChange.bind(this);
}

async componentDidMount() {
Expand Down Expand Up @@ -135,56 +131,20 @@ export class Inventory extends Component {
return auxTabs;
}

getStoreFilters(props) {
const { section, selectView, agent } = props;
const filters = JSON.parse(
window.localStorage.getItem(
`wazuh-${section}-${selectView}-${
this.state?.selectedTabId || 'files'
}-${agent['id']}`,
) || '{}',
);
return filters;
}

setStoreFilters(filters) {
const { section, selectView, agent } = this.props;
window.localStorage.setItem(
`wazuh-${section}-${selectView}-${this.state?.selectedTabId || 'files'}-${
agent['id']
}`,
JSON.stringify(filters),
);
}

onFiltersChange = filters => {
this.setState({ filters });
};

onTotalItemsChange = (totalItems: number) => {
this.setState({ totalItemsFile: totalItems });
};

onSelectedTabChanged = id => {
this.setState({ selectedTabId: id });
};

buildFilter(type) {
const filters = filtersToObject(this.state.filters);
const filter = {
...filters,
limit: type === 'file' ? '15' : '1',
...(type === 'registry' ? { q: 'type=registry_key' } : { type }),
...(type === 'file' && { sort: '+file' }),
};
return filter;
}

async getItemNumber(type: 'file' | 'registry') {
try {
const agentID = this.props.agent.id;
const response = await WzRequest.apiReq('GET', `/syscheck/${agentID}`, {
params: this.buildFilter(type),
params: {
limit: 1, // reduce the size because only need the total items. 0 gives error
...(type === 'registry'
? { q: 'type=registry_key' }
: { q: 'type=file' }),
},
});
if (type === 'file') {
return {
Expand Down Expand Up @@ -257,16 +217,13 @@ export class Inventory extends Component {
filters={filters}
items={syscheck}
totalItems={totalItemsFile}
onFiltersChange={this.onFiltersChange}
onTotalItemsChange={this.onTotalItemsChange}
/>
)}
{selectedTabId === 'registry' && (
<RegistryTable
{...this.props}
filters={filters}
totalItems={totalItemsRegistry}
onFiltersChange={this.onFiltersChange}
/>
)}
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,13 +198,15 @@ export class FileDetails extends Component {
name: 'Last analysis',
grow: 2,
icon: 'clock',
link: true,
transformValue: formatUIDate,
},
{
field: 'mtime',
name: 'Last modified',
grow: 2,
icon: 'clock',
link: true,
transformValue: formatUIDate,
},
];
Expand Down Expand Up @@ -290,21 +292,19 @@ export class FileDetails extends Component {
}

addFilter(field, value) {
const { filters, onFiltersChange } = this.props;
const newBadge: ICustomBadges = { field: 'q', value: '' };
const { onFiltersChange } = this.props;
let filterUQL = '';
if (field === 'date' || field === 'mtime') {
const value_max = moment(value).add(1, 'day');
newBadge.value = `${field}>${moment(value).format(
filterUQL = `${field}>${moment(value).format(
'YYYY-MM-DD',
)} AND ${field}<${value_max.format('YYYY-MM-DD')}`;
)};${field}<${value_max.format('YYYY-MM-DD')}`;
} else {
newBadge.value = `${field}=${
filterUQL = `${field}=${
field === 'size' ? this.props.currentFile[field] : value
}`;
}
!filters.some(
item => item.field === newBadge.field && item.value === newBadge.value,
) && onFiltersChange([...filters, newBadge]);
onFiltersChange({ q: filterUQL });
this.props.closeFlyout();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,10 @@ import { withRouterSearch } from '../../../common/hocs';
import { Route, Switch } from '../../../router-search';
import NavigationService from '../../../../react-services/navigation-service';

const searchBarWQLOptions = {
implicitQuery: {
query: 'type=registry_key',
conjunction: ';',
},
};

const searchBarWQLFilters = { default: { q: 'type=registry_key' } };

export const RegistryTable = withRouterSearch(
class RegistryTable extends Component {
state: {
filters: {};
syscheck: [];
isFlyoutVisible: Boolean;
currentFile: {
Expand All @@ -51,7 +43,7 @@ export const RegistryTable = withRouterSearch(
super(props);

this.state = {
syscheck: [],
filters: {},
isFlyoutVisible: false,
currentFile: {
file: '',
Expand All @@ -73,12 +65,13 @@ export const RegistryTable = withRouterSearch(
name: 'Registry',
sortable: true,
searchable: true,
show: true,
},
{
field: 'mtime',
name: (
<span>
Last Modified{' '}
Last modified{' '}
<EuiIconTip
content='This is not searchable through a search term.'
size='s'
Expand All @@ -92,10 +85,35 @@ export const RegistryTable = withRouterSearch(
className: 'wz-white-space-nowrap',
render: formatUIDate,
searchable: false,
show: true,
},
{
field: 'date',
name: (
<span>
Last analysis{' '}
<EuiIconTip
content='This is not searchable through a search term.'
size='s'
color='subdued'
type='alert'
/>
</span>
),
sortable: true,
width: '100px',
render: formatUIDate,
searchable: false,
},
];
}

onFiltersChange = filters => {
this.setState({
filters,
});
};

renderRegistryTable() {
const getRowProps = item => {
const { file } = item;
Expand All @@ -111,18 +129,20 @@ export const RegistryTable = withRouterSearch(

const columns = this.columns();

const APIendpoint = `/syscheck/${this.props.agent.id}?type=registry_key`;

return (
<EuiFlexGroup>
<EuiFlexItem>
<TableWzAPI
title='Registry'
tableColumns={columns}
tableInitialSortingField='file'
endpoint={`/syscheck/${this.props.agent.id}`}
endpoint={APIendpoint}
searchBarWQL={{
options: searchBarWQLOptions,
suggestions: {
field: () => [
{ label: 'date', description: 'filter by analysis time' },
{ label: 'file', description: 'filter by file' },
{
label: 'mtime',
Expand All @@ -133,7 +153,7 @@ export const RegistryTable = withRouterSearch(
try {
const response = await WzRequest.apiReq(
'GET',
`/syscheck/${this.props.agent.id}`,
APIendpoint,
{
params: {
distinct: true,
Expand All @@ -142,12 +162,9 @@ export const RegistryTable = withRouterSearch(
sort: `+${field}`,
...(currentValue
? {
// Add the implicit query
q: `${searchBarWQLOptions.implicitQuery.query}${searchBarWQLOptions.implicitQuery.conjunction}${field}~${currentValue}`,
q: `${field}~${currentValue}`,
}
: {
q: `${searchBarWQLOptions.implicitQuery.query}`,
}),
: {}),
},
},
);
Expand All @@ -174,11 +191,16 @@ export const RegistryTable = withRouterSearch(
},
},
}}
filters={searchBarWQLFilters}
filters={this.state.filters}
showReload
downloadCsv={`fim-registry-${this.props.agent.id}`}
searchTable={true}
rowProps={getRowProps}
saveStateStorage={{
system: 'localStorage',
key: 'wz-fim-registry-key-table',
}}
showFieldSelector
/>
</EuiFlexItem>
</EuiFlexGroup>
Expand All @@ -201,6 +223,7 @@ export const RegistryTable = withRouterSearch(
view='inventory'
// showViewInEvents={true}
{...this.props}
onFiltersChange={this.onFiltersChange}
/>
)}
></Route>
Expand Down
Loading

0 comments on commit 9157e9a

Please sign in to comment.