diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f34027a08..43221f848b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,9 @@ 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 an "Agents management" menu and moved the sections: "Endpoint Groups" and "Endpoint Summary" which changed its name to "Summary".[#7112](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7112) +- 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 @@ -27,19 +30,23 @@ All notable changes to the Wazuh app project will be documented in this file. - Fixed read-only users could not access to Statistics application [#7001](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7001) - Fixed no-agent-alert spawn with selected agent in agent-welcome view [#7029](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7029) +- Fixed loading state of the agents status chart in the home overview [#7120](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7120) - Fixed security policy exception when it contained deprecated actions [#7042](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7042) +- Fixed border on cells in events that disappear when clicked [#7075](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7075) - Fixed export formatted csv data with special characters from tables [#7048](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7048) - Fixed column reordering feature [#7072](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7072) - Fixed filter management to prevent hiding when adding multiple filters [#7077](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7077) - Fixed agent view Mitre ATT&CK exception [#7116](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7116) - 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 - Removed agent RBAC filters from dashboard queries [#6945](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6945) - Removed GET /elastic/statistics API endpoint [#7001](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7001) - Removed VirusTotal application in favor of Malware Detection [#7038](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7038) +- Removed processes state column in macOS agents [#7122](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7122) ## Wazuh v4.9.1 - OpenSearch Dashboards 2.13.0 - Revision 04 diff --git a/plugins/main/public/components/agents/fim/inventory.tsx b/plugins/main/public/components/agents/fim/inventory.tsx index fbb5d41b22..6353589cb4 100644 --- a/plugins/main/public/components/agents/fim/inventory.tsx +++ b/plugins/main/public/components/agents/fim/inventory.tsx @@ -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, @@ -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; @@ -57,7 +55,6 @@ export class Inventory extends Component { constructor(props) { super(props); this.state = { - filters: [], syscheck: [], selectedTabId: 'files', totalItemsFile: 0, @@ -66,7 +63,6 @@ export class Inventory extends Component { customBadges: [], isConfigured: false, }; - this.onFiltersChange.bind(this); } async componentDidMount() { @@ -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 { @@ -257,8 +217,6 @@ export class Inventory extends Component { filters={filters} items={syscheck} totalItems={totalItemsFile} - onFiltersChange={this.onFiltersChange} - onTotalItemsChange={this.onTotalItemsChange} /> )} {selectedTabId === 'registry' && ( @@ -266,7 +224,6 @@ export class Inventory extends Component { {...this.props} filters={filters} totalItems={totalItemsRegistry} - onFiltersChange={this.onFiltersChange} /> )} diff --git a/plugins/main/public/components/agents/fim/inventory/fileDetail.tsx b/plugins/main/public/components/agents/fim/inventory/fileDetail.tsx index 0dff1a4698..ea2fe09158 100644 --- a/plugins/main/public/components/agents/fim/inventory/fileDetail.tsx +++ b/plugins/main/public/components/agents/fim/inventory/fileDetail.tsx @@ -198,6 +198,7 @@ export class FileDetails extends Component { name: 'Last analysis', grow: 2, icon: 'clock', + link: true, transformValue: formatUIDate, }, { @@ -205,6 +206,7 @@ export class FileDetails extends Component { name: 'Last modified', grow: 2, icon: 'clock', + link: true, transformValue: formatUIDate, }, ]; @@ -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(); } diff --git a/plugins/main/public/components/agents/fim/inventory/registry-table.tsx b/plugins/main/public/components/agents/fim/inventory/registry-table.tsx index ee96fff10c..6dfb410c46 100644 --- a/plugins/main/public/components/agents/fim/inventory/registry-table.tsx +++ b/plugins/main/public/components/agents/fim/inventory/registry-table.tsx @@ -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: { @@ -51,7 +43,7 @@ export const RegistryTable = withRouterSearch( super(props); this.state = { - syscheck: [], + filters: {}, isFlyoutVisible: false, currentFile: { file: '', @@ -73,12 +65,13 @@ export const RegistryTable = withRouterSearch( name: 'Registry', sortable: true, searchable: true, + show: true, }, { field: 'mtime', name: ( - Last Modified{' '} + Last modified{' '} + Last analysis{' '} + + + ), + sortable: true, + width: '100px', + render: formatUIDate, + searchable: false, }, ]; } + onFiltersChange = filters => { + this.setState({ + filters, + }); + }; + renderRegistryTable() { const getRowProps = item => { const { file } = item; @@ -111,6 +129,8 @@ export const RegistryTable = withRouterSearch( const columns = this.columns(); + const APIendpoint = `/syscheck/${this.props.agent.id}?type=registry_key`; + return ( @@ -118,11 +138,11 @@ export const RegistryTable = withRouterSearch( 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', @@ -133,7 +153,7 @@ export const RegistryTable = withRouterSearch( try { const response = await WzRequest.apiReq( 'GET', - `/syscheck/${this.props.agent.id}`, + APIendpoint, { params: { distinct: true, @@ -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}`, - }), + : {}), }, }, ); @@ -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 /> @@ -201,6 +223,7 @@ export const RegistryTable = withRouterSearch( view='inventory' // showViewInEvents={true} {...this.props} + onFiltersChange={this.onFiltersChange} /> )} > diff --git a/plugins/main/public/components/agents/fim/inventory/table.tsx b/plugins/main/public/components/agents/fim/inventory/table.tsx index f9021891db..80157ce30c 100644 --- a/plugins/main/public/components/agents/fim/inventory/table.tsx +++ b/plugins/main/public/components/agents/fim/inventory/table.tsx @@ -21,19 +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=file', - conjunction: ';', - }, -}; - -const searchBarWQLFilters = { default: { q: 'type=file' } }; - export const InventoryTable = withRouterSearch( class InventoryTable extends Component { state: { - syscheck: []; + filters: any; isFlyoutVisible: Boolean; currentFile: { file: string; @@ -46,14 +37,13 @@ export const InventoryTable = withRouterSearch( agent: any; items: []; totalItems: number; - onTotalItemsChange: Function; }; constructor(props) { super(props); this.state = { - syscheck: props.items, + filters: {}, isFlyoutVisible: false, currentFile: { file: '', @@ -80,12 +70,13 @@ export const InventoryTable = withRouterSearch( sortable: true, width: '250px', searchable: true, + show: true, }, { field: 'mtime', name: ( - Last Modified{' '} + Last modified{' '} + Last analysis{' '} + + + ), + sortable: true, + width: '100px', + render: formatUIDate, + searchable: false, + }, + { + field: 'md5', + name: 'MD5', + searchable: true, + sortable: true, + }, + { + field: 'sha1', + name: 'SHA1', + searchable: true, + sortable: true, + }, + { + field: 'sha256', + name: 'SHA256', + searchable: true, + sortable: true, }, ]; } + onFiltersChange = filters => { + this.setState({ + filters, + }); + }; + renderFilesTable() { const getRowProps = item => { const { file } = item; @@ -155,6 +194,8 @@ export const InventoryTable = withRouterSearch( }; const columns = this.columns(); + const APIendpoint = `/syscheck/${this.props.agent.id}?type=file`; + return ( @@ -162,18 +203,24 @@ export const InventoryTable = withRouterSearch( title='Files' tableColumns={columns} tableInitialSortingField='file' - endpoint={`/syscheck/${this.props.agent.id}`} + endpoint={APIendpoint} searchBarWQL={{ - options: searchBarWQLOptions, suggestions: { field: currentValue => [ + { label: 'date', description: 'filter by analysis time' }, { label: 'file', description: 'filter by file' }, { label: 'gid', description: 'filter by group id' }, { label: 'gname', description: 'filter by group name' }, + { label: 'md5', description: 'filter by MD5 checksum' }, { label: 'mtime', description: 'filter by modification time', }, + { label: 'sha1', description: 'filter by SHA1 checksum' }, + { + label: 'sha256', + description: 'filter by SHA256 checksum', + }, { label: 'size', description: 'filter by size' }, { label: 'uname', description: 'filter by user name' }, { label: 'uid', description: 'filter by user id' }, @@ -182,7 +229,7 @@ export const InventoryTable = withRouterSearch( try { const response = await WzRequest.apiReq( 'GET', - `/syscheck/${this.props.agent.id}`, + APIendpoint, { params: { distinct: true, @@ -191,12 +238,9 @@ export const InventoryTable = withRouterSearch( sort: `+${field}`, ...(currentValue ? { - // Add the implicit query - q: `${searchBarWQLOptions.implicitQuery.query}${searchBarWQLOptions.implicitQuery.conjunction}${field}~${currentValue}`, + q: `${field}~${currentValue}`, } - : { - q: `${searchBarWQLOptions.implicitQuery.query}`, - }), + : {}), }, }, ); @@ -223,11 +267,16 @@ export const InventoryTable = withRouterSearch( }, }, }} - filters={searchBarWQLFilters} + filters={this.state.filters} showReload downloadCsv={`fim-files-${this.props.agent.id}`} searchTable={true} rowProps={getRowProps} + saveStateStorage={{ + system: 'localStorage', + key: 'wz-fim-files-table', + }} + showFieldSelector /> @@ -251,6 +300,7 @@ export const InventoryTable = withRouterSearch( view='inventory' showViewInEvents={true} {...this.props} + onFiltersChange={this.onFiltersChange} /> )} > diff --git a/plugins/main/public/components/agents/syscollector/__snapshots__/inventory.test.tsx.snap b/plugins/main/public/components/agents/syscollector/__snapshots__/inventory.test.tsx.snap index d048bbcd49..92dad0b43e 100644 --- a/plugins/main/public/components/agents/syscollector/__snapshots__/inventory.test.tsx.snap +++ b/plugins/main/public/components/agents/syscollector/__snapshots__/inventory.test.tsx.snap @@ -2085,31 +2085,6 @@ exports[`Inventory component A Apple agent should be well rendered. 1`] = ` - - - @@ -2118,7 +2093,7 @@ exports[`Inventory component A Apple agent should be well rendered. 1`] = ` >
({ + ...rest, + field, + name: rest.name || KeyEquivalence[field] || field, +}); const windowsColumns = [ { field: 'name', searchable: true, sortable: true, width: '10%' }, @@ -8,7 +14,8 @@ const windowsColumns = [ { field: 'priority', searchable: true, sortable: true }, { field: 'nlwp', searchable: true, sortable: true }, { field: 'cmd', searchable: true, sortable: true, width: '30%' }, -].map(({field, ...rest}) => ({...rest, field, name: rest.name || KeyEquivalence[field] || field})); +].map(mapColumns); + const linuxColumns = [ { field: 'name', searchable: true, sortable: true, width: '10%' }, { field: 'euser', searchable: true, sortable: true }, @@ -22,7 +29,8 @@ const linuxColumns = [ { field: 'session', searchable: true, sortable: true }, { field: 'nice', searchable: true, sortable: true }, { field: 'state', searchable: true, sortable: true, width: '15%' }, -].map(({field, ...rest}) => ({...rest, field, name: rest.name || KeyEquivalence[field] || field})); +].map(mapColumns); + const macColumns = [ { field: 'name', searchable: true, sortable: true, width: '10%' }, { field: 'euser', searchable: true, sortable: true }, @@ -30,8 +38,7 @@ const macColumns = [ { field: 'ppid', searchable: true, sortable: true }, { field: 'vm_size', searchable: true, sortable: true }, { field: 'nice', searchable: true, sortable: true }, - { field: 'state', searchable: true, sortable: true, width: '15%' }, -].map(({field, ...rest}) => ({...rest, field, name: rest.name || KeyEquivalence[field] || field})); +].map(mapColumns); export const processColumns = { windows: windowsColumns, diff --git a/plugins/main/public/components/overview/overview.tsx b/plugins/main/public/components/overview/overview.tsx index de7a53e7de..91e9c97528 100644 --- a/plugins/main/public/components/overview/overview.tsx +++ b/plugins/main/public/components/overview/overview.tsx @@ -40,6 +40,7 @@ export const Overview: React.FC = withRouteResolvers({ savedSearch, })(() => { const [agentsCounts, setAgentsCounts] = useState({}); + const [isAgentsLoading, setIsAgentsLoading] = useState(true); const { tab = 'welcome', tabView = 'dashboard', agentId } = useRouterSearch(); const navigationService = NavigationService.getInstance(); const pinnedAgentManager = new PinnedAgentManager(); @@ -131,6 +132,7 @@ export const Overview: React.FC = withRouteResolvers({ }, } = await WzRequest.apiReq('GET', '/agents/summary/status', {}); setAgentsCounts(data); + setIsAgentsLoading(false); } catch (error) { return Promise.reject(error); } @@ -167,7 +169,7 @@ export const Overview: React.FC = withRouteResolvers({ - + diff --git a/plugins/main/public/controllers/overview/components/stats.js b/plugins/main/public/controllers/overview/components/stats.js index 97fbb7cfec..aec7fcbfba 100644 --- a/plugins/main/public/controllers/overview/components/stats.js +++ b/plugins/main/public/controllers/overview/components/stats.js @@ -79,20 +79,39 @@ export const Stats = withErrorBoundary( ); } + /** + * Calculate the size of the visualization evaluating if it renders the internal loading or the chart + * based on the viewport size + */ + getVisualizationSize() { + const normalLoadingSize = { width: 377, height: '150px' }; + const mobileLoadingSize = { + height: '150px', + }; + const loadingSize = + window.innerWidth < 768 ? mobileLoadingSize : normalLoadingSize; + const size = this.props.isAgentsLoading + ? loadingSize + : { width: '100%', height: '150px' }; + return size; + } + render() { + const { isAgentsLoading } = this.props; const hasResults = this.agentStatus.some( ({ status }) => this.props[status], ); + const showAgentsChart = isAgentsLoading || hasResults; return ( - {hasResults ? ( + {showAgentsChart ? ( ({ @@ -107,36 +126,33 @@ export const Stats = withErrorBoundary( )} /> ) : ( - !hasResults && - this.props !== undefined && ( - - This instance has no agents registered. -
- Please deploy agents to begin monitoring your endpoints. -

- } - actions={ - - Deploy new agent - - } - /> - ) + + This instance has no agents registered. +
+ Please deploy agents to begin monitoring your endpoints. +

+ } + actions={ + + Deploy new agent + + } + /> )}
diff --git a/plugins/main/public/styles/common.scss b/plugins/main/public/styles/common.scss index b9e4429542..31007c0175 100644 --- a/plugins/main/public/styles/common.scss +++ b/plugins/main/public/styles/common.scss @@ -324,12 +324,6 @@ input[type='search'].euiFieldSearch { box-shadow: none; } -:focus:not(.wz-button):not(.input-filter-box):not(.kuiLocalSearchInput):not( - .euiTextArea - ):not(.euiPanel.euiPopover__panel.euiPopover__panel-isOpen) { - box-shadow: none !important; -} - /* Custom colors styles */ .color-white { color: white; diff --git a/plugins/main/public/utils/applications.ts b/plugins/main/public/utils/applications.ts index 76ecbc060c..9b07810efd 100644 --- a/plugins/main/public/utils/applications.ts +++ b/plugins/main/public/utils/applications.ts @@ -24,8 +24,9 @@ Endpoint security: 200 Threat intelligence: 300 Security operations: 400 Cloud security: 500 -Server management: 600 -Dashboard management: 700 +Agents management: 600 +Server management: 700 +Dashboard management Indexer management (added to Wazuh dashboard default categories): 9000 */ @@ -54,53 +55,34 @@ export const overview = { }`, }; -export const fileIntegrityMonitoring = { +export const configurationAssessment = { category: 'wz-category-endpoint-security', - id: 'file-integrity-monitoring', - title: i18n.translate('wz-app-file-integrity-monitoring-title', { - defaultMessage: 'File Integrity Monitoring', + id: 'configuration-assessment', + title: i18n.translate('wz-app-configuration-assessment-title', { + defaultMessage: 'Configuration Assessment', }), breadcrumbLabel: i18n.translate( - 'wz-app-file-integrity-monitoring-breadcrumbLabel', + 'wz-app-configuration-assessment-breadcrumbLabel', { - defaultMessage: 'File Integrity Monitoring', + defaultMessage: 'Configuration Assessment', }, ), - description: i18n.translate('wz-app-file-integrity-monitoring-description', { + description: i18n.translate('wz-app-configuration-assessment-description', { defaultMessage: - 'Alerts related to file changes, including permissions, content, ownership, and attributes.', + 'Scan your assets as part of a configuration assessment audit.', }), - euiIconType: 'sqlApp', + order: 200, + euiIconType: 'managementApp', showInOverviewApp: true, showInAgentMenu: true, - order: 202, redirectTo: () => - `/overview/?tab=fim&tabView=dashboard${ + `/overview/?tab=sca&tabView=dashboard${ store.getState()?.appStateReducers?.currentAgentData?.id ? `&agentId=${store.getState()?.appStateReducers?.currentAgentData?.id}` : '' }`, }; -export const endpointSummary = { - category: 'wz-category-server-management', - id: 'endpoints-summary', - title: i18n.translate('wz-app-endpoints-summary-title', { - defaultMessage: 'Endpoints Summary', - }), - breadcrumbLabel: i18n.translate('wz-app-endpoints-summary-breadcrumbLabel', { - defaultMessage: 'Endpoints', - }), - description: i18n.translate('wz-app-endpoints-summary-description', { - defaultMessage: 'Summary of agents and their status.', - }), - euiIconType: 'spacesApp', - order: 600, - showInOverviewApp: false, - showInAgentMenu: false, - redirectTo: () => '/agents-preview/', -}; - export const malwareDetection = { category: 'wz-category-endpoint-security', id: 'malware-detection', @@ -126,28 +108,28 @@ export const malwareDetection = { }`, }; -export const configurationAssessment = { +export const fileIntegrityMonitoring = { category: 'wz-category-endpoint-security', - id: 'configuration-assessment', - title: i18n.translate('wz-app-configuration-assessment-title', { - defaultMessage: 'Configuration Assessment', + id: 'file-integrity-monitoring', + title: i18n.translate('wz-app-file-integrity-monitoring-title', { + defaultMessage: 'File Integrity Monitoring', }), breadcrumbLabel: i18n.translate( - 'wz-app-configuration-assessment-breadcrumbLabel', + 'wz-app-file-integrity-monitoring-breadcrumbLabel', { - defaultMessage: 'Configuration Assessment', + defaultMessage: 'File Integrity Monitoring', }, ), - description: i18n.translate('wz-app-configuration-assessment-description', { + description: i18n.translate('wz-app-file-integrity-monitoring-description', { defaultMessage: - 'Scan your assets as part of a configuration assessment audit.', + 'Alerts related to file changes, including permissions, content, ownership, and attributes.', }), - order: 200, - euiIconType: 'managementApp', + euiIconType: 'sqlApp', showInOverviewApp: true, showInAgentMenu: true, + order: 202, redirectTo: () => - `/overview/?tab=sca&tabView=dashboard${ + `/overview/?tab=fim&tabView=dashboard${ store.getState()?.appStateReducers?.currentAgentData?.id ? `&agentId=${store.getState()?.appStateReducers?.currentAgentData?.id}` : '' @@ -257,50 +239,50 @@ const pciDss = { }`, }; -const hipaa = { +const gdpr = { category: 'wz-category-security-operations', - id: 'hipaa', - title: i18n.translate('wz-app-hipaa-title', { - defaultMessage: 'HIPAA', + id: 'gdpr', + title: i18n.translate('wz-app-gdpr-title', { + defaultMessage: 'GDPR', }), - breadcrumbLabel: i18n.translate('wz-app-hipaa-breadcrumbLabel', { - defaultMessage: 'HIPAA', + breadcrumbLabel: i18n.translate('wz-app-gdpr-breadcrumbLabel', { + defaultMessage: 'GDPR', }), - description: i18n.translate('wz-app-hipaa-description', { + description: i18n.translate('wz-app-gdpr-description', { defaultMessage: - 'Health Insurance Portability and Accountability Act of 1996 (HIPAA) provides data privacy and security provisions for safeguarding medical information.', + 'General Data Protection Regulation (GDPR) sets guidelines for processing of personal data.', }), - euiIconType: 'monitoringApp', - order: 402, + euiIconType: 'visBarVertical', + order: 401, showInOverviewApp: true, showInAgentMenu: true, redirectTo: () => - `/overview/?tab=hipaa&tabView=dashboard${ + `/overview/?tab=gdpr&tabView=dashboard${ store.getState()?.appStateReducers?.currentAgentData?.id ? `&agentId=${store.getState()?.appStateReducers?.currentAgentData?.id}` : '' }`, }; -const gdpr = { +const hipaa = { category: 'wz-category-security-operations', - id: 'gdpr', - title: i18n.translate('wz-app-gdpr-title', { - defaultMessage: 'GDPR', + id: 'hipaa', + title: i18n.translate('wz-app-hipaa-title', { + defaultMessage: 'HIPAA', }), - breadcrumbLabel: i18n.translate('wz-app-gdpr-breadcrumbLabel', { - defaultMessage: 'GDPR', + breadcrumbLabel: i18n.translate('wz-app-hipaa-breadcrumbLabel', { + defaultMessage: 'HIPAA', }), - description: i18n.translate('wz-app-gdpr-description', { + description: i18n.translate('wz-app-hipaa-description', { defaultMessage: - 'General Data Protection Regulation (GDPR) sets guidelines for processing of personal data.', + 'Health Insurance Portability and Accountability Act of 1996 (HIPAA) provides data privacy and security provisions for safeguarding medical information.', }), - euiIconType: 'visBarVertical', - order: 401, + euiIconType: 'monitoringApp', + order: 402, showInOverviewApp: true, showInAgentMenu: true, redirectTo: () => - `/overview/?tab=gdpr&tabView=dashboard${ + `/overview/?tab=hipaa&tabView=dashboard${ store.getState()?.appStateReducers?.currentAgentData?.id ? `&agentId=${store.getState()?.appStateReducers?.currentAgentData?.id}` : '' @@ -357,6 +339,31 @@ const tsc = { }`, }; +export const docker = { + category: 'wz-category-cloud-security', + id: 'docker', + title: i18n.translate('wz-app-docker-title', { + defaultMessage: 'Docker', + }), + breadcrumbLabel: i18n.translate('wz-app-docker-breadcrumbLabel', { + defaultMessage: 'Docker', + }), + description: i18n.translate('wz-app-docker-description', { + defaultMessage: + 'Monitor and collect the activity from Docker containers such as creation, running, starting, stopping or pausing events.', + }), + euiIconType: LogoDocker, + order: 500, + showInOverviewApp: true, + showInAgentMenu: true, + redirectTo: () => + `/overview/?tab=docker&tabView=dashboard${ + store.getState()?.appStateReducers?.currentAgentData?.id + ? `&agentId=${store.getState()?.appStateReducers?.currentAgentData?.id}` + : '' + }`, +}; + export const amazonWebServices = { category: 'wz-category-cloud-security', id: 'amazon-web-services', @@ -374,7 +381,7 @@ export const amazonWebServices = { 'Security events related to your Amazon AWS services, collected directly via AWS API.', }), euiIconType: 'logoAWSMono', - order: 500, + order: 501, showInOverviewApp: true, showInAgentMenu: true, redirectTo: () => @@ -399,7 +406,7 @@ export const googleCloud = { 'Security events related to your Google Cloud Platform services, collected directly via GCP API.', }), euiIconType: LogoGoogleCloud, - order: 501, + order: 502, showInOverviewApp: true, showInAgentMenu: true, redirectTo: () => @@ -424,7 +431,7 @@ export const github = { 'Monitoring events from audit logs of your GitHub organizations.', }), euiIconType: LogoGitHub, - order: 502, + order: 503, showInOverviewApp: true, showInAgentMenu: true, redirectTo: () => @@ -448,7 +455,7 @@ export const office365 = { defaultMessage: 'Security events related to your Office 365 services.', }), euiIconType: LogoOffice365, - order: 503, + order: 504, showInOverviewApp: true, showInAgentMenu: true, redirectTo: () => @@ -459,29 +466,42 @@ export const office365 = { }`, }; -export const docker = { - category: 'wz-category-cloud-security', - id: 'docker', - title: i18n.translate('wz-app-docker-title', { - defaultMessage: 'Docker', +export const endpointSummary = { + category: 'wz-category-agents-management', + id: 'endpoints-summary', + title: i18n.translate('wz-app-endpoints-summary-title', { + defaultMessage: 'Summary', }), - breadcrumbLabel: i18n.translate('wz-app-docker-breadcrumbLabel', { - defaultMessage: 'Docker', + breadcrumbLabel: i18n.translate('wz-app-endpoints-summary-breadcrumbLabel', { + defaultMessage: 'Endpoints', }), - description: i18n.translate('wz-app-docker-description', { - defaultMessage: - 'Monitor and collect the activity from Docker containers such as creation, running, starting, stopping or pausing events.', + description: i18n.translate('wz-app-endpoints-summary-description', { + defaultMessage: 'Summary of agents and their status.', }), - euiIconType: LogoDocker, - order: 404, - showInOverviewApp: true, - showInAgentMenu: true, - redirectTo: () => - `/overview/?tab=docker&tabView=dashboard${ - store.getState()?.appStateReducers?.currentAgentData?.id - ? `&agentId=${store.getState()?.appStateReducers?.currentAgentData?.id}` - : '' - }`, + euiIconType: 'spacesApp', + order: 600, + showInOverviewApp: false, + showInAgentMenu: false, + redirectTo: () => '/agents-preview/', +}; + +export const endpointGroups = { + category: 'wz-category-agents-management', + id: 'endpoint-groups', + title: i18n.translate('wz-app-endpoint-groups-title', { + defaultMessage: 'Endpoint Groups', + }), + breadcrumbLabel: i18n.translate('wz-app-endpoint-groups-breadcrumbLabel', { + defaultMessage: 'Endpoint Groups', + }), + description: i18n.translate('wz-app-endpoint-groups-description', { + defaultMessage: 'Manage your agent groups.', + }), + euiIconType: 'usersRolesApp', + order: 601, + showInOverviewApp: false, + showInAgentMenu: false, + redirectTo: () => '/manager/?tab=groups', }; export const rules = { @@ -497,7 +517,7 @@ export const rules = { defaultMessage: 'Manage your cluster rules.', }), euiIconType: 'indexRollupApp', - order: 602, + order: 700, showInOverviewApp: false, showInAgentMenu: false, redirectTo: () => '/manager/?tab=ruleset', @@ -516,7 +536,7 @@ export const decoders = { defaultMessage: 'Manage your cluster decoders.', }), euiIconType: 'indexRollupApp', - order: 603, + order: 701, showInOverviewApp: false, showInAgentMenu: false, redirectTo: () => '/manager/?tab=decoders', @@ -535,31 +555,12 @@ export const cdbLists = { defaultMessage: 'Manage your cluster CDB list.', }), euiIconType: 'indexRollupApp', - order: 604, + order: 702, showInOverviewApp: false, showInAgentMenu: false, redirectTo: () => '/manager/?tab=lists', }; -export const endpointGroups = { - category: 'wz-category-server-management', - id: 'endpoint-groups', - title: i18n.translate('wz-app-endpoint-groups-title', { - defaultMessage: 'Endpoint Groups', - }), - breadcrumbLabel: i18n.translate('wz-app-endpoint-groups-breadcrumbLabel', { - defaultMessage: 'Endpoint Groups', - }), - description: i18n.translate('wz-app-endpoint-groups-description', { - defaultMessage: 'Manage your agent groups.', - }), - euiIconType: 'usersRolesApp', - order: 601, - showInOverviewApp: false, - showInAgentMenu: false, - redirectTo: () => '/manager/?tab=groups', -}; - export const serverStatus = { category: 'wz-category-server-management', id: 'server-status', @@ -573,7 +574,7 @@ export const serverStatus = { defaultMessage: 'Manage your cluster status.', }), euiIconType: 'indexRollupApp', - order: 605, + order: 703, showInOverviewApp: false, showInAgentMenu: false, redirectTo: () => '/manager/?tab=status', @@ -592,7 +593,7 @@ export const cluster = { defaultMessage: 'Manage your cluster.', }), euiIconType: 'indexRollupApp', - order: 606, + order: 704, showInOverviewApp: false, showInAgentMenu: false, redirectTo: () => '/manager/?tab=monitoring', @@ -611,7 +612,7 @@ export const statistics = { defaultMessage: 'Information about the enviroment.', }), euiIconType: 'indexRollupApp', - order: 607, + order: 705, showInOverviewApp: false, showInAgentMenu: false, redirectTo: () => '/manager/?tab=statistics', @@ -630,31 +631,12 @@ export const logs = { defaultMessage: 'Logs from your cluster.', }), euiIconType: 'indexRollupApp', - order: 608, + order: 706, showInOverviewApp: false, showInAgentMenu: false, redirectTo: () => '/manager/?tab=logs', }; -export const reporting = { - category: 'wz-category-dashboard-management', - id: 'reporting', - title: i18n.translate('wz-app-reporting-title', { - defaultMessage: 'Reporting', - }), - breadcrumbLabel: i18n.translate('wz-app-reporting-breadcrumbLabel', { - defaultMessage: 'Reporting', - }), - description: i18n.translate('wz-app-reporting-description', { - defaultMessage: 'Check your stored reports.', - }), - euiIconType: 'indexRollupApp', - order: 10002, - showInOverviewApp: false, - showInAgentMenu: false, - redirectTo: () => '/manager/?tab=reporting', -}; - export const settings = { category: 'wz-category-server-management', id: 'dashboards-settings', @@ -668,7 +650,7 @@ export const settings = { defaultMessage: 'Manage your cluster configuration.', }), euiIconType: 'indexRollupApp', - order: 609, + order: 707, showInOverviewApp: false, showInAgentMenu: false, redirectTo: () => '/manager/?tab=configuration', @@ -687,7 +669,7 @@ export const devTools = { defaultMessage: 'Test the API endpoints.', }), euiIconType: 'devToolsApp', - order: 610, + order: 708, showInOverviewApp: false, showInAgentMenu: false, redirectTo: () => '/wazuh-dev?tab=devTools', @@ -706,7 +688,7 @@ export const rulesetTest = { defaultMessage: 'Check your ruleset testing logs.', }), euiIconType: 'visualizeApp', - order: 611, + order: 709, showInOverviewApp: false, showInAgentMenu: false, redirectTo: () => '/wazuh-dev?tab=logtest', @@ -726,31 +708,12 @@ export const security = { 'Manage permissions to system resources based on the roles and policies.', }), euiIconType: 'securityAnalyticsApp', - order: 612, + order: 710, showInOverviewApp: false, showInAgentMenu: false, redirectTo: () => '/security?tab=users', }; -export const serverApis = { - category: 'wz-category-dashboard-management', - id: 'server-apis', - title: i18n.translate('wz-app-server-apis-title', { - defaultMessage: 'Server APIs', - }), - breadcrumbLabel: i18n.translate('wz-app-server-apis-breadcrumbLabel', { - defaultMessage: 'Server APIs', - }), - description: i18n.translate('wz-app-server-apis-description', { - defaultMessage: 'Manage and configure the API entries.', - }), - euiIconType: 'indexRollupApp', - order: 10003, - showInOverviewApp: false, - showInAgentMenu: false, - redirectTo: () => '/settings?tab=api', -}; - export const sampleData = { category: 'management', id: 'sample-data', @@ -770,6 +733,44 @@ export const sampleData = { redirectTo: () => '/settings?tab=sample_data', }; +export const reporting = { + category: 'wz-category-dashboard-management', + id: 'reporting', + title: i18n.translate('wz-app-reporting-title', { + defaultMessage: 'Reporting', + }), + breadcrumbLabel: i18n.translate('wz-app-reporting-breadcrumbLabel', { + defaultMessage: 'Reporting', + }), + description: i18n.translate('wz-app-reporting-description', { + defaultMessage: 'Check your stored reports.', + }), + euiIconType: 'indexRollupApp', + order: 10002, + showInOverviewApp: false, + showInAgentMenu: false, + redirectTo: () => '/manager/?tab=reporting', +}; + +export const serverApis = { + category: 'wz-category-dashboard-management', + id: 'server-apis', + title: i18n.translate('wz-app-server-apis-title', { + defaultMessage: 'Server APIs', + }), + breadcrumbLabel: i18n.translate('wz-app-server-apis-breadcrumbLabel', { + defaultMessage: 'Server APIs', + }), + description: i18n.translate('wz-app-server-apis-description', { + defaultMessage: 'Manage and configure the API entries.', + }), + euiIconType: 'indexRollupApp', + order: 10003, + showInOverviewApp: false, + showInAgentMenu: false, + redirectTo: () => '/settings?tab=api', +}; + export const appSettings = { category: 'wz-category-dashboard-management', id: 'app-settings', @@ -897,12 +898,20 @@ export const Categories = [ order: 500, euiIconType: 'watchesApp', }, + { + id: 'wz-category-agents-management', + label: i18n.translate('wz-app-category-agents-management', { + defaultMessage: 'Agents management', + }), + order: 600, + euiIconType: 'indexRollupApp', + }, { id: 'wz-category-server-management', label: i18n.translate('wz-app-category-server-management', { defaultMessage: 'Server management', }), - order: 600, + order: 700, euiIconType: 'indexRollupApp', }, { @@ -910,13 +919,13 @@ export const Categories = [ label: i18n.translate('wz-app-category-dashboard-management', { defaultMessage: 'Dashboard management', }), - order: 6e3, + order: 5e3, euiIconType: 'dashboardApp', }, { id: 'management', label: 'Indexer management', - order: 5e3, + order: 6e3, euiIconType: 'managementApp', }, ];