From 05c2f46b152ebeecb7c6c3b9e8bf6f2cdb5c5466 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chantal=20Bel=C3=A9n=20kelm?= <99441266+chantal-kelm@users.noreply.github.com> Date: Thu, 26 Sep 2024 13:41:53 -0300 Subject: [PATCH 01/41] Style breaks when unpinned an agent in safari (#7015) * fix style when unnpinned an agent in endpoint summary section * update changelog --- CHANGELOG.md | 1 + plugins/main/public/components/endpoints-summary/agent/index.tsx | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cca05a7231..06029a01ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ All notable changes to the Wazuh app project will be documented in this file. - Fixed missing options depending on agent operating system in the agent configuration report [#6983](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6983) - Fixed an style that affected the Discover plugin [#6989](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6989) - Fixed a problem updating the API host registry in the GET /api/check-stored-api [#6995](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6995) +- Fixed style when unnpinned an agent in endpoint summary section [#7015](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7015) ### Changed diff --git a/plugins/main/public/components/endpoints-summary/agent/index.tsx b/plugins/main/public/components/endpoints-summary/agent/index.tsx index d30b618052..7a4f7be0c2 100644 --- a/plugins/main/public/components/endpoints-summary/agent/index.tsx +++ b/plugins/main/public/components/endpoints-summary/agent/index.tsx @@ -46,6 +46,7 @@ export const AgentView = compose( You need to select an agent or return to From a2ab3ee5767c1c26692b7d24f05a2d4635fb9798 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chantal=20Bel=C3=A9n=20kelm?= <99441266+chantal-kelm@users.noreply.github.com> Date: Thu, 26 Sep 2024 15:20:45 -0300 Subject: [PATCH 02/41] Fix when generating a PDF report, the open report button in safari does not work (#7019) * Fix when generating a PDF report, the open report button in safari does not work * update changelog * New solution for pdf report problem * update changelog * update changelog --- CHANGELOG.md | 1 + .../reporting/utils/columns-main.js | 20 +++++++------------ .../main/public/react-services/reporting.js | 15 +++++--------- 3 files changed, 13 insertions(+), 23 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 06029a01ca..a70afc2679 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ All notable changes to the Wazuh app project will be documented in this file. - Fixed missing options depending on agent operating system in the agent configuration report [#6983](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6983) - Fixed an style that affected the Discover plugin [#6989](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6989) - Fixed a problem updating the API host registry in the GET /api/check-stored-api [#6995](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6995) +- Fixed the `Open report` button of the toast and the `Download report` icon of the reporting table in Safari [#7019](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7019) - Fixed style when unnpinned an agent in endpoint summary section [#7015](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7015) ### Changed diff --git a/plugins/main/public/controllers/management/components/management/reporting/utils/columns-main.js b/plugins/main/public/controllers/management/components/management/reporting/utils/columns-main.js index b9c288ce1f..24679102a7 100644 --- a/plugins/main/public/controllers/management/components/management/reporting/utils/columns-main.js +++ b/plugins/main/public/controllers/management/components/management/reporting/utils/columns-main.js @@ -1,8 +1,7 @@ import React from 'react'; -import { EuiToolTip, EuiButtonIcon } from '@elastic/eui'; +import { EuiToolTip, EuiButtonEmpty } from '@elastic/eui'; import ReportingHandler from './reporting-handler'; import moment from 'moment-timezone'; -import { WzButton } from '../../../../../../components/common/buttons'; import { getHttp, getUiSettings } from '../../../../../../kibana-services'; import { formatUIDate } from '../../../../../../react-services/time-service'; export default class ReportingColums { @@ -41,15 +40,17 @@ export default class ReportingColums { return (
- this.goReport(item.name)} + href={getHttp().basePath.prepend(`/reports/${item.name}`)} + target='_blank' color='primary' + contentProps={{ className: 'wz-no-padding' }} /> -
); @@ -70,14 +72,6 @@ export default class ReportingColums { this.buildColumns(); } - /** - * Downloads the report - * @param {*} name The name of the report - */ - goReport(name) { - window.open(getHttp().basePath.prepend(`/reports/${name}`), '_blank'); - } - /** * Returns given date adding the timezone offset * @param {string} date Date diff --git a/plugins/main/public/react-services/reporting.js b/plugins/main/public/react-services/reporting.js index a5436236a5..e198b461cf 100644 --- a/plugins/main/public/react-services/reporting.js +++ b/plugins/main/public/react-services/reporting.js @@ -22,7 +22,7 @@ import store from '../redux/store'; import domtoimage from '../utils/dom-to-image-more'; import dateMath from '@elastic/datemath'; import React from 'react'; -import { EuiFlexGroup, EuiFlexItem, EuiButton, EuiLink } from '@elastic/eui'; +import { EuiFlexGroup, EuiFlexItem, EuiLink } from '@elastic/eui'; import { reporting } from '../utils/applications'; import { RedirectAppLinks } from '../../../../src/plugins/opensearch_dashboards_react/public'; import { @@ -93,17 +93,12 @@ export class ReportingService { - - window.open( - getHttp().basePath.prepend(`/reports/${filename}`), - '_blank', - ) - } - size='s' + Open report - +
, From 930e5d57ebacb77d511c8387b2598926eb0dcc34 Mon Sep 17 00:00:00 2001 From: Antonio <34042064+Desvelao@users.noreply.github.com> Date: Fri, 27 Sep 2024 11:19:33 +0200 Subject: [PATCH 03/41] Add visualization of vulnerabilities evaluation status count (#6968) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: rename use-data-grid.ts file * fix: use the field formatter to render the fields in the WzDataGrid * feat: add the wazuh.vulnerability.under_evaluation field to the vulnerabilities sample data tool * feat(vulnerabilities): add visualization related to evaluation status to the dashboard * changelog: add entry * fix(changelog): rephrase * Change visualization to only pending * Add post fixed filter place to render components * Add under evaluation filter component * Apply under evaluation filter in vuls tabs * Add style to button group in filter * Apply prettier * Apply prettier * Fix style in dark and light theme * Added changelog --------- Co-authored-by: Chantal Belén kelm <99441266+chantal-kelm@users.noreply.github.com> Co-authored-by: Federico Rodriguez Co-authored-by: Maximiliano Ibarra --- CHANGELOG.md | 3 +- .../{use-data-grid.ts => use-data-grid.tsx} | 14 ++- .../pattern-data-source-filter-manager.ts | 2 +- .../common/search-bar/search-bar.tsx | 9 ++ .../components/vuls-evaluation-filter.tsx | 104 ++++++++++++++++ .../dashboards/inventory/inventory.tsx | 60 +++++++-- .../dashboards/overview/dashboard.tsx | 50 +++++++- .../overview/dashboard_panels_kpis.ts | 117 ++++++++++++++++-- plugins/main/public/styles/common.scss | 23 ++++ .../public/styles/theme/dark/index.dark.scss | 9 ++ .../DIS_Template.json | 9 +- .../dataInjectScript.py | 1 + 12 files changed, 376 insertions(+), 25 deletions(-) rename plugins/main/public/components/common/data-grid/{use-data-grid.ts => use-data-grid.tsx} (90%) create mode 100644 plugins/main/public/components/overview/vulnerabilities/common/components/vuls-evaluation-filter.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index b9a02263b5..94d0cc4413 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,11 +8,12 @@ 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) ### Changed - Update malware detection group values in data sources [#6963](https://github.com/wazuh/wazuh-dashboard-plugins/issues/6963) -- Changed the registration id of the Settings application for compatibility with Opensearch Dashboard 2.16.0 [#6938](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6938) +- Changed the registration id of the Settings application for compatibility with OpenSearch Dashboard 2.16.0 [#6938](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6938) - Changed Malware detection dashboard visualizations [#6964](https://github.com/wazuh/wazuh-dashboard-plugins/issues/6964) ### Fixed diff --git a/plugins/main/public/components/common/data-grid/use-data-grid.ts b/plugins/main/public/components/common/data-grid/use-data-grid.tsx similarity index 90% rename from plugins/main/public/components/common/data-grid/use-data-grid.ts rename to plugins/main/public/components/common/data-grid/use-data-grid.tsx index a330fc5ad1..d85d5898ea 100644 --- a/plugins/main/public/components/common/data-grid/use-data-grid.ts +++ b/plugins/main/public/components/common/data-grid/use-data-grid.tsx @@ -17,6 +17,7 @@ import { IndexPattern, } from '../../../../../../src/plugins/data/common'; import { EuiDataGridPaginationProps } from '@opensearch-project/oui'; +import dompurify from 'dompurify'; export interface PaginationOptions extends Pick< @@ -163,7 +164,18 @@ export const useDataGrid = (props: tDataGridProps): EuiDataGridProps => { ); } - return fieldFormatted; + // Format the value using the field formatter + // https://github.com/opensearch-project/OpenSearch-Dashboards/blob/2.16.0/src/plugins/discover/public/application/components/data_grid/data_grid_table_cell_value.tsx#L80-L89 + const formattedValue = indexPattern.formatField(rows[rowIndex], columnId); + if (typeof formattedValue === 'undefined') { + return -; + } else { + const sanitizedCellValue = dompurify.sanitize(formattedValue); + return ( + // eslint-disable-next-line react/no-danger + + ); + } } return null; }; diff --git a/plugins/main/public/components/common/data-source/pattern/pattern-data-source-filter-manager.ts b/plugins/main/public/components/common/data-source/pattern/pattern-data-source-filter-manager.ts index f26282ad85..8e4781c360 100644 --- a/plugins/main/public/components/common/data-source/pattern/pattern-data-source-filter-manager.ts +++ b/plugins/main/public/components/common/data-source/pattern/pattern-data-source-filter-manager.ts @@ -325,7 +325,7 @@ export class PatternDataSourceFilterManager static createFilter( type: FILTER_OPERATOR, key: string, - value: string | string[], + value: string | string[] | any, indexPatternId: string, controlledBy?: string, ) { diff --git a/plugins/main/public/components/common/search-bar/search-bar.tsx b/plugins/main/public/components/common/search-bar/search-bar.tsx index 4dd1a6c8d4..8c7b57144a 100644 --- a/plugins/main/public/components/common/search-bar/search-bar.tsx +++ b/plugins/main/public/components/common/search-bar/search-bar.tsx @@ -12,11 +12,13 @@ export interface WzSearchBarProps extends SearchBarProps { userFilters?: Filter[]; preQueryBar?: React.ReactElement; postFilters?: React.ReactElement; + postFixedFilters?: () => React.ReactElement[]; hideFixedFilters?: boolean; } export const WzSearchBar = ({ fixedFilters = [], + postFixedFilters, preQueryBar, hideFixedFilters, postFilters, @@ -73,6 +75,13 @@ export const WzSearchBar = ({ ))} + {postFixedFilters + ? postFixedFilters.map((Filter, idx) => ( + + + + )) + : null} )} diff --git a/plugins/main/public/components/overview/vulnerabilities/common/components/vuls-evaluation-filter.tsx b/plugins/main/public/components/overview/vulnerabilities/common/components/vuls-evaluation-filter.tsx new file mode 100644 index 0000000000..590b251faa --- /dev/null +++ b/plugins/main/public/components/overview/vulnerabilities/common/components/vuls-evaluation-filter.tsx @@ -0,0 +1,104 @@ +import React, { useState, useEffect } from 'react'; +import { EuiButtonGroup } from '@elastic/eui'; +import { + FILTER_OPERATOR, + PatternDataSourceFilterManager, +} from '../../../../common/data-source'; +import { Filter } from '../../../../../../../../src/plugins/data/common'; + +type VulsEvaluatedFilterProps = { + setValue: (underEvaluation: boolean | null) => void; + value: boolean | null; +}; + +const UNDER_EVALUATION_FIELD = 'wazuh.vulnerability.under_evaluation'; + +export const getUnderEvaluationFilterValue = ( + filters: Filter[], +): boolean | null => { + const underEvaluationFilter = filters.find( + f => f.meta?.key === UNDER_EVALUATION_FIELD, + ); + if (underEvaluationFilter) { + return underEvaluationFilter.meta?.params.query as boolean; + } + return null; +}; + +export const excludeUnderEvaluationFilter = (filters: Filter[]): Filter[] => { + return filters.filter(f => f.meta?.key !== UNDER_EVALUATION_FIELD); +}; + +export const createUnderEvaluationFilter = ( + underEvaluation: boolean, + indexPatternId: string, +): Filter => { + return PatternDataSourceFilterManager.createFilter( + FILTER_OPERATOR.IS, + UNDER_EVALUATION_FIELD, + underEvaluation, + indexPatternId, + ); +}; + +const VulsEvaluationFilter = ({ + setValue, + value, +}: VulsEvaluatedFilterProps) => { + const toggleButtons = [ + { + id: 'evaluated', + label: 'Evaluated', + }, + { + id: 'underEvaluation', + label: 'Under evaluation', + }, + ]; + + const getDefaultValue = () => { + if (value === true) { + return { underEvaluation: true, evaluated: false }; + } else if (value === false) { + return { underEvaluation: false, evaluated: true }; + } else { + return {}; + } + }; + + const [toggleIdToSelectedMap, setToggleIdToSelectedMap] = useState( + getDefaultValue(), + ); + + useEffect(() => { + setToggleIdToSelectedMap(getDefaultValue()); + }, [value]); + + const handleChange = (optionId: string) => { + let newToggleIdToSelectedMap = {}; + if (!toggleIdToSelectedMap[optionId]) { + newToggleIdToSelectedMap = { [optionId]: true }; + } + setToggleIdToSelectedMap(newToggleIdToSelectedMap); + if (optionId === 'underEvaluation' && newToggleIdToSelectedMap[optionId]) { + setValue(true); + } else if (optionId === 'evaluated' && newToggleIdToSelectedMap[optionId]) { + setValue(false); + } else { + setValue(null); + } + }; + + return ( + handleChange(id)} + buttonSize='compressed' + /> + ); +}; + +export default VulsEvaluationFilter; diff --git a/plugins/main/public/components/overview/vulnerabilities/dashboards/inventory/inventory.tsx b/plugins/main/public/components/overview/vulnerabilities/dashboards/inventory/inventory.tsx index ecef54dd3a..4786bf71a1 100644 --- a/plugins/main/public/components/overview/vulnerabilities/dashboards/inventory/inventory.tsx +++ b/plugins/main/public/components/overview/vulnerabilities/dashboards/inventory/inventory.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useMemo, useState } from 'react'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; import { IntlProvider } from 'react-intl'; import { EuiDataGrid, @@ -34,7 +34,6 @@ import { LoadingSearchbarProgress } from '../../../../../../public/components/co // common components/hooks import useSearchBar from '../../../../common/search-bar/use-search-bar'; import { useDataGrid } from '../../../../common/data-grid/use-data-grid'; -import { useDocViewer } from '../../../../common/doc-viewer/use-doc-viewer'; import { withErrorBoundary } from '../../../../common/hocs'; import { exportSearchToCSV } from '../../../../common/data-grid/data-grid-service'; import { compose } from 'redux'; @@ -51,6 +50,11 @@ import { IndexPattern } from '../../../../../../../../src/plugins/data/public'; import { wzDiscoverRenderColumns } from '../../../../common/wazuh-discover/render-columns'; import { DocumentViewTableAndJson } from '../../../../common/wazuh-discover/components/document-view-table-and-json'; import { WzSearchBar } from '../../../../common/search-bar'; +import VulsEvaluationFilter, { + createUnderEvaluationFilter, + excludeUnderEvaluationFilter, + getUnderEvaluationFilterValue, +} from '../../common/components/vuls-evaluation-filter'; const InventoryVulsComponent = () => { const { @@ -104,6 +108,11 @@ const InventoryVulsComponent = () => { ); }; + const getUnderEvaluation = useCallback(getUnderEvaluationFilterValue, [ + JSON.stringify(filters), + isDataSourceLoading, + ]); + const dataGridProps = useDataGrid({ ariaLabelledBy: 'Vulnerabilities Inventory Table', defaultColumns: inventoryTableDefaultColumns, @@ -117,11 +126,6 @@ const InventoryVulsComponent = () => { const { pagination, sorting, columnVisibility } = dataGridProps; - const docViewerProps = useDocViewer({ - doc: inspectedHit, - indexPattern: indexPattern as IndexPattern, - }); - const onClickExportResults = async () => { const params = { indexPattern: indexPattern as IndexPattern, @@ -152,6 +156,7 @@ const InventoryVulsComponent = () => { if (isDataSourceLoading) { return; } + setUnderEvaluation(getUnderEvaluation(filters || [])); setIndexPattern(dataSource?.indexPattern); fetchData({ query, pagination, sorting }) .then(results => { @@ -171,6 +176,32 @@ const InventoryVulsComponent = () => { JSON.stringify(sorting), ]); + /** + * When the user changes the filter value, this function is called to update the filters + * If the value is null, the filter is removed + * If the filter already exists, it is remove and the new filter is added + * @param underEvaluation + * @returns + */ + const handleFilterChange = (underEvaluation: boolean | null) => { + const newFilters = excludeUnderEvaluationFilter(filters || []); + if (underEvaluation === null) { + setFilters(newFilters); + return; + } + newFilters.push( + createUnderEvaluationFilter( + underEvaluation, + dataSource?.id || indexPattern?.id, + ), + ); + setFilters(newFilters); + }; + + const [underEvaluation, setUnderEvaluation] = useState( + getUnderEvaluation(filters || []), + ); + return ( <> @@ -190,7 +221,16 @@ const InventoryVulsComponent = () => { ( + + ), + ]} showDatePicker={false} showQueryInput={true} showQueryBar={true} @@ -222,9 +262,11 @@ const InventoryVulsComponent = () => { results?.hits?.total > MAX_ENTRIES_PER_QUERY ? { ariaLabel: 'Warning', - content: `The query results exceeded the limit of ${formatNumWithCommas( + content: `The query results has exceeded the limit of ${formatNumWithCommas( + MAX_ENTRIES_PER_QUERY, + )} hits. To provide a better experience the table only shows the first ${formatNumWithCommas( MAX_ENTRIES_PER_QUERY, - )} hits. Please refine your search.`, + )} hits.`, iconType: 'alert', position: 'top', } diff --git a/plugins/main/public/components/overview/vulnerabilities/dashboards/overview/dashboard.tsx b/plugins/main/public/components/overview/vulnerabilities/dashboards/overview/dashboard.tsx index 2ea3d9846f..7398da1bb4 100644 --- a/plugins/main/public/components/overview/vulnerabilities/dashboards/overview/dashboard.tsx +++ b/plugins/main/public/components/overview/vulnerabilities/dashboards/overview/dashboard.tsx @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useMemo } from 'react'; +import React, { useState, useEffect, useCallback } from 'react'; import { SearchResponse } from '../../../../../../../../src/core/server'; import { getPlugins } from '../../../../../kibana-services'; import { ViewMode } from '../../../../../../../../src/plugins/embeddable/public'; @@ -25,10 +25,17 @@ import { VulnerabilitiesDataSource, PatternDataSource, tParsedIndexPattern, + PatternDataSourceFilterManager, + FILTER_OPERATOR, } from '../../../../common/data-source'; import { useDataSource } from '../../../../common/data-source/hooks'; import { IndexPattern } from '../../../../../../../../src/plugins/data/public'; import { WzSearchBar } from '../../../../common/search-bar'; +import VulsEvaluationFilter, { + createUnderEvaluationFilter, + excludeUnderEvaluationFilter, + getUnderEvaluationFilterValue, +} from '../../common/components/vuls-evaluation-filter'; const plugins = getPlugins(); const DashboardByRenderer = plugins.dashboard.DashboardContainerByValueRenderer; @@ -70,6 +77,7 @@ const DashboardVulsComponent: React.FC = ({ if (isDataSourceLoading) { return; } + setUnderEvaluation(getUnderEvaluation(filters || [])); fetchData({ query }) .then(results => { setResults(results); @@ -83,6 +91,37 @@ const DashboardVulsComponent: React.FC = ({ }); }, [JSON.stringify(fetchFilters), JSON.stringify(query)]); + /** + * When the user changes the filter value, this function is called to update the filters + * If the value is null, the filter is removed + * If the filter already exists, it is remove and the new filter is added + * @param underEvaluation + * @returns + */ + const handleFilterChange = (underEvaluation: boolean | null) => { + const newFilters = excludeUnderEvaluationFilter(filters || []); + if (underEvaluation === null) { + setFilters(newFilters); + return; + } + newFilters.push( + createUnderEvaluationFilter( + underEvaluation, + dataSource?.id || indexPattern?.id, + ), + ); + setFilters(newFilters); + }; + + const getUnderEvaluation = useCallback(getUnderEvaluationFilterValue, [ + JSON.stringify(filters), + isDataSourceLoading, + ]); + + const [underEvaluation, setUnderEvaluation] = useState( + getUnderEvaluation(filters || []), + ); + return ( <> @@ -94,7 +133,16 @@ const DashboardVulsComponent: React.FC = ({ ( + + ), + ]} showDatePicker={false} showQueryInput={true} showQueryBar={true} diff --git a/plugins/main/public/components/overview/vulnerabilities/dashboards/overview/dashboard_panels_kpis.ts b/plugins/main/public/components/overview/vulnerabilities/dashboards/overview/dashboard_panels_kpis.ts index c2d213b401..06e49f7fcc 100644 --- a/plugins/main/public/components/overview/vulnerabilities/dashboards/overview/dashboard_panels_kpis.ts +++ b/plugins/main/public/components/overview/vulnerabilities/dashboards/overview/dashboard_panels_kpis.ts @@ -34,7 +34,7 @@ const getVisStateSeverityCritical = (indexPatternId: string) => { bgColor: false, labelColor: false, subText: '', - fontSize: 50, + fontSize: 40, }, }, }, @@ -119,7 +119,7 @@ const getVisStateSeverityHigh = (indexPatternId: string) => { bgColor: false, labelColor: false, subText: '', - fontSize: 50, + fontSize: 40, }, }, }, @@ -204,7 +204,7 @@ const getVisStateSeverityMedium = (indexPatternId: string) => { bgColor: false, labelColor: false, subText: '', - fontSize: 50, + fontSize: 40, }, }, }, @@ -289,7 +289,7 @@ const getVisStateSeverityLow = (indexPatternId: string) => { bgColor: false, labelColor: false, subText: '', - fontSize: 50, + fontSize: 40, }, }, }, @@ -341,6 +341,87 @@ const getVisStateSeverityLow = (indexPatternId: string) => { }; }; +const getVisStateEvaluatedEvaluationPending = (indexPatternId: string) => { + return { + id: 'vulnerabilities_evaluation_count', + title: 'Evaluation', + type: 'metric', + params: { + addLegend: false, + addTooltip: true, + metric: { + colorSchema: 'Green to Red', + colorsRange: [ + { + from: 0, + to: 10000, + }, + ], + invertColors: false, + labels: { + show: true, + }, + metricColorMode: 'None', + percentageMode: false, + style: { + bgColor: false, + bgFill: '#000', + fontSize: 40, + labelColor: false, + subText: '', + }, + useRanges: false, + }, + type: 'metric', + }, + data: { + searchSource: { + query: { + language: 'kuery', + query: '', + }, + filter: [], + index: indexPatternId, + }, + references: [ + { + name: 'kibanaSavedObjectMeta.searchSourceJSON.index', + type: 'index-pattern', + id: indexPatternId, + }, + ], + aggs: [ + { + id: '1', + enabled: true, + type: 'count', + params: { + customLabel: 'Evaluation', + }, + schema: 'metric', + }, + { + id: '2', + enabled: true, + type: 'filters', + params: { + filters: [ + { + input: { + language: 'kuery', + query: 'wazuh.vulnerability.under_evaluation:true', + }, + label: 'Pending', + }, + ], + }, + schema: 'group', + }, + ], + }, + }; +}; + export const getKPIsPanel = ( indexPatternId: string, ): { @@ -351,7 +432,7 @@ export const getKPIsPanel = ( return { '1': { gridData: { - w: 12, + w: 9, h: 6, x: 0, y: 0, @@ -365,9 +446,9 @@ export const getKPIsPanel = ( }, '2': { gridData: { - w: 12, + w: 9, h: 6, - x: 12, + x: 9, y: 0, i: '2', }, @@ -379,9 +460,9 @@ export const getKPIsPanel = ( }, '3': { gridData: { - w: 12, + w: 9, h: 6, - x: 24, + x: 18, y: 0, i: '3', }, @@ -393,9 +474,9 @@ export const getKPIsPanel = ( }, '4': { gridData: { - w: 12, + w: 9, h: 6, - x: 36, + x: 27, y: 0, i: '4', }, @@ -405,5 +486,19 @@ export const getKPIsPanel = ( savedVis: getVisStateSeverityLow(indexPatternId), }, }, + '5': { + gridData: { + w: 12, + h: 6, + x: 36, + y: 0, + i: '5', + }, + type: 'visualization', + explicitInput: { + id: '5', + savedVis: getVisStateEvaluatedEvaluationPending(indexPatternId), + }, + }, }; }; diff --git a/plugins/main/public/styles/common.scss b/plugins/main/public/styles/common.scss index 69f2be672e..a6fbe6be15 100644 --- a/plugins/main/public/styles/common.scss +++ b/plugins/main/public/styles/common.scss @@ -1833,3 +1833,26 @@ iframe.width-changed { fill: #000000bb; } } + +/* Vulnerabilities under evaluation filter */ +.button-group-filter { + border-radius: 2px; + + .euiButton__content, + .euiButton__text { + font-size: 12px; + font-weight: 500; + } + + .euiButtonGroup__buttons { + height: 30px; + border-radius: 2px; + box-shadow: 0 1px 1px -1px rgba(152, 162, 179, 0.2), + 0 3px 2px -2px rgba(152, 162, 179, 0.2), inset 0 0 0 1px #bcc3ce !important; + border: none !important; + + .euiButtonGroupButton { + line-height: 28px; + } + } +} diff --git a/plugins/main/public/styles/theme/dark/index.dark.scss b/plugins/main/public/styles/theme/dark/index.dark.scss index 4e2b58481b..421d51f17f 100644 --- a/plugins/main/public/styles/theme/dark/index.dark.scss +++ b/plugins/main/public/styles/theme/dark/index.dark.scss @@ -217,6 +217,7 @@ table thead > tr { .wzMultipleSelector select { border-color: #343741; } + .wzMultipleSelectorSelect { color: #dfe5ef; } @@ -456,3 +457,11 @@ svg .legend text { fill: #dfe5ef; } } + +/* Vulnerabilities under evaluation filter */ +.button-group-filter { + .euiButtonGroup__buttons { + box-shadow: 0 1px 1px -1px rgba(0, 0, 0, 0.2), + 0 3px 2px -2px rgba(0, 0, 0, 0.2), inset 0 0 0 1px #424752 !important; + } +} diff --git a/scripts/vulnerabilities-events-injector/DIS_Template.json b/scripts/vulnerabilities-events-injector/DIS_Template.json index 14d6167f1d..75a723b057 100644 --- a/scripts/vulnerabilities-events-injector/DIS_Template.json +++ b/scripts/vulnerabilities-events-injector/DIS_Template.json @@ -257,6 +257,13 @@ "type": "keyword" } } + }, + "vulnerability": { + "properties": { + "under_evaluation": { + "type": "boolean" + } + } } } } @@ -273,4 +280,4 @@ "refresh_interval": "2s" } } -} \ No newline at end of file +} diff --git a/scripts/vulnerabilities-events-injector/dataInjectScript.py b/scripts/vulnerabilities-events-injector/dataInjectScript.py index 00136432f5..f9e6dfbaca 100644 --- a/scripts/vulnerabilities-events-injector/dataInjectScript.py +++ b/scripts/vulnerabilities-events-injector/dataInjectScript.py @@ -130,6 +130,7 @@ def generateRandomVulnerability(): def generateRandomWazuh(): wazuh = {} wazuh['cluster'] = {'name':random.choice(['wazuh.manager', 'wazuh']), 'node':random.choice(['master','worker-01','worker-02','worker-03'])} + wazuh['vulnerability'] = {'under_evaluation': random.choice([True, False])} return(wazuh) def generateRandomData(number): From 6ef14dc8fbdbe35cca03b7ffff7de43662379db8 Mon Sep 17 00:00:00 2001 From: Federico Rodriguez Date: Fri, 27 Sep 2024 11:38:00 +0200 Subject: [PATCH 04/41] Update PDF report year (#7022) * Update PDF report year * Add changelog --- CHANGELOG.md | 1 + plugins/wazuh-core/common/constants.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a70afc2679..ce2cdbb1fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ All notable changes to the Wazuh app project will be documented in this file. - Upgraded Event-tab column selector showing first the picked columns [#6984](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6984) - Changed vulnerabilities.reference to links in Vulnerability Detection > Inventory columns [#6960](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6960) - Upgraded the `follow-redirects` dependency to `1.15.6` [#6982](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6982) +- Changed PDF report footer year [#7022](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7022) - Changed many loading spinners in some views to loading search progress [#6956](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6956) ### Removed diff --git a/plugins/wazuh-core/common/constants.ts b/plugins/wazuh-core/common/constants.ts index e4ad9aa1ab..6d87b6d55f 100644 --- a/plugins/wazuh-core/common/constants.ts +++ b/plugins/wazuh-core/common/constants.ts @@ -274,7 +274,7 @@ export const ASSETS_PUBLIC_URL = '/plugins/wazuh/public/assets/'; export const REPORTS_LOGO_IMAGE_ASSETS_RELATIVE_PATH = 'images/logo_reports.png'; export const REPORTS_PRIMARY_COLOR = '#256BD1'; -export const REPORTS_PAGE_FOOTER_TEXT = 'Copyright © 2023 Wazuh, Inc.'; +export const REPORTS_PAGE_FOOTER_TEXT = 'Copyright © 2024 Wazuh, Inc.'; export const REPORTS_PAGE_HEADER_TEXT = 'info@wazuh.com\nhttps://wazuh.com'; // Plugin platform From a2ed51dd2f30693d47fd76c192f51c119214967d Mon Sep 17 00:00:00 2001 From: Guido Modarelli <38738725+guidomodarelli@users.noreply.github.com> Date: Fri, 27 Sep 2024 08:22:30 -0300 Subject: [PATCH 05/41] Filter expands outside the viewport and cannot be removed (#7021) * Update search bar layout in WzSearchBar component * Update single quotes to double quotes in search-bar component * Fix overflow hidden * Add changelog * Fix post filter flexgroup --------- Co-authored-by: Federico Rodriguez --- CHANGELOG.md | 1 + .../main/public/components/common/search-bar/search-bar.tsx | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce2cdbb1fe..5f536fe91a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ All notable changes to the Wazuh app project will be documented in this file. - Fixed a problem updating the API host registry in the GET /api/check-stored-api [#6995](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6995) - Fixed the `Open report` button of the toast and the `Download report` icon of the reporting table in Safari [#7019](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7019) - Fixed style when unnpinned an agent in endpoint summary section [#7015](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7015) +- Fixed overflow style on a long value filter [#7021](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7021) ### Changed diff --git a/plugins/main/public/components/common/search-bar/search-bar.tsx b/plugins/main/public/components/common/search-bar/search-bar.tsx index 4dd1a6c8d4..3d713958af 100644 --- a/plugins/main/public/components/common/search-bar/search-bar.tsx +++ b/plugins/main/public/components/common/search-bar/search-bar.tsx @@ -76,14 +76,14 @@ export const WzSearchBar = ({ )} - + - + Date: Fri, 27 Sep 2024 13:35:26 +0200 Subject: [PATCH 06/41] Remove PDF report footer year (#7023) * Remove pdf report footer year * Add changelog --- CHANGELOG.md | 2 +- plugins/main/common/constants.ts | 2 +- plugins/wazuh-core/common/constants.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5f536fe91a..d1173a7bbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,11 +33,11 @@ All notable changes to the Wazuh app project will be documented in this file. - Upgraded Event-tab column selector showing first the picked columns [#6984](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6984) - Changed vulnerabilities.reference to links in Vulnerability Detection > Inventory columns [#6960](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6960) - Upgraded the `follow-redirects` dependency to `1.15.6` [#6982](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6982) -- Changed PDF report footer year [#7022](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7022) - Changed many loading spinners in some views to loading search progress [#6956](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6956) ### Removed +- Removed the PDF report footer year [#7023](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7023) - Removed the XML autoformat function group configuration due to performance [#6999](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6999) ## Wazuh v4.9.0 - OpenSearch Dashboards 2.13.0 - Revision 07 diff --git a/plugins/main/common/constants.ts b/plugins/main/common/constants.ts index 26fc95c5c4..62eb2fc7ec 100644 --- a/plugins/main/common/constants.ts +++ b/plugins/main/common/constants.ts @@ -302,7 +302,7 @@ export const ASSETS_PUBLIC_URL = '/plugins/wazuh/public/assets/'; export const REPORTS_LOGO_IMAGE_ASSETS_RELATIVE_PATH = 'images/logo_reports.png'; export const REPORTS_PRIMARY_COLOR = '#256BD1'; -export const REPORTS_PAGE_FOOTER_TEXT = 'Copyright © 2024 Wazuh, Inc.'; +export const REPORTS_PAGE_FOOTER_TEXT = 'Copyright © Wazuh, Inc.'; export const REPORTS_PAGE_HEADER_TEXT = 'info@wazuh.com\nhttps://wazuh.com'; // Plugin platform diff --git a/plugins/wazuh-core/common/constants.ts b/plugins/wazuh-core/common/constants.ts index 6d87b6d55f..6075cc9619 100644 --- a/plugins/wazuh-core/common/constants.ts +++ b/plugins/wazuh-core/common/constants.ts @@ -274,7 +274,7 @@ export const ASSETS_PUBLIC_URL = '/plugins/wazuh/public/assets/'; export const REPORTS_LOGO_IMAGE_ASSETS_RELATIVE_PATH = 'images/logo_reports.png'; export const REPORTS_PRIMARY_COLOR = '#256BD1'; -export const REPORTS_PAGE_FOOTER_TEXT = 'Copyright © 2024 Wazuh, Inc.'; +export const REPORTS_PAGE_FOOTER_TEXT = 'Copyright © Wazuh, Inc.'; export const REPORTS_PAGE_HEADER_TEXT = 'info@wazuh.com\nhttps://wazuh.com'; // Plugin platform From d6ba1051f28dd6507be27a0c0f2c28e9a0835cca Mon Sep 17 00:00:00 2001 From: Federico Rodriguez Date: Fri, 27 Sep 2024 13:53:06 +0200 Subject: [PATCH 07/41] Bump revision 4.9.1 02 (#7025) Bump revision to 02 --- CHANGELOG.md | 2 +- plugins/main/opensearch_dashboards.json | 2 +- plugins/main/package.json | 2 +- plugins/wazuh-check-updates/opensearch_dashboards.json | 2 +- plugins/wazuh-check-updates/package.json | 2 +- plugins/wazuh-core/opensearch_dashboards.json | 2 +- plugins/wazuh-core/package.json | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1173a7bbf..fcb5dead49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to the Wazuh app project will be documented in this file. -## Wazuh v4.9.1 - OpenSearch Dashboards 2.13.0 - Revision 01 +## Wazuh v4.9.1 - OpenSearch Dashboards 2.13.0 - Revision 02 ### Added diff --git a/plugins/main/opensearch_dashboards.json b/plugins/main/opensearch_dashboards.json index c8f011eb27..384752eac2 100644 --- a/plugins/main/opensearch_dashboards.json +++ b/plugins/main/opensearch_dashboards.json @@ -1,6 +1,6 @@ { "id": "wazuh", - "version": "4.9.1-01", + "version": "4.9.1-02", "opensearchDashboardsVersion": "opensearchDashboards", "configPath": ["wazuh"], "requiredPlugins": [ diff --git a/plugins/main/package.json b/plugins/main/package.json index ce6123a678..e7dcecce67 100644 --- a/plugins/main/package.json +++ b/plugins/main/package.json @@ -1,7 +1,7 @@ { "name": "wazuh", "version": "4.9.1", - "revision": "01", + "revision": "02", "pluginPlatform": { "version": "2.13.0" }, diff --git a/plugins/wazuh-check-updates/opensearch_dashboards.json b/plugins/wazuh-check-updates/opensearch_dashboards.json index b52eca1246..cfd6e912d1 100644 --- a/plugins/wazuh-check-updates/opensearch_dashboards.json +++ b/plugins/wazuh-check-updates/opensearch_dashboards.json @@ -1,6 +1,6 @@ { "id": "wazuhCheckUpdates", - "version": "4.9.1-01", + "version": "4.9.1-02", "opensearchDashboardsVersion": "opensearchDashboards", "server": true, "ui": true, diff --git a/plugins/wazuh-check-updates/package.json b/plugins/wazuh-check-updates/package.json index fa69efe528..550c9e5f2e 100644 --- a/plugins/wazuh-check-updates/package.json +++ b/plugins/wazuh-check-updates/package.json @@ -1,7 +1,7 @@ { "name": "wazuh-check-updates", "version": "4.9.1", - "revision": "01", + "revision": "02", "pluginPlatform": { "version": "2.13.0" }, diff --git a/plugins/wazuh-core/opensearch_dashboards.json b/plugins/wazuh-core/opensearch_dashboards.json index b714fbf461..a1f22c9a27 100644 --- a/plugins/wazuh-core/opensearch_dashboards.json +++ b/plugins/wazuh-core/opensearch_dashboards.json @@ -1,6 +1,6 @@ { "id": "wazuhCore", - "version": "4.9.1-01", + "version": "4.9.1-02", "opensearchDashboardsVersion": "opensearchDashboards", "server": true, "ui": true, diff --git a/plugins/wazuh-core/package.json b/plugins/wazuh-core/package.json index 19c0425494..f43bc9b13f 100644 --- a/plugins/wazuh-core/package.json +++ b/plugins/wazuh-core/package.json @@ -1,7 +1,7 @@ { "name": "wazuh-core", "version": "4.9.1", - "revision": "01", + "revision": "02", "pluginPlatform": { "version": "2.13.0" }, From 05ebac51257876555836b9ef2052caabe41b7edf Mon Sep 17 00:00:00 2001 From: JuanGarriuz Date: Mon, 30 Sep 2024 12:06:22 +0200 Subject: [PATCH 08/41] Fixed no agent alert spawn with selected agent in agent welcome (#7029) * Fixed no-agent spawn * Added Changelog --------- Co-authored-by: Federico Rodriguez --- CHANGELOG.md | 1 + .../components/common/hocs/withAgentSync.tsx | 26 +++++++++++++++++++ .../endpoints-summary/agent/index.tsx | 2 ++ 3 files changed, 29 insertions(+) create mode 100644 plugins/main/public/components/common/hocs/withAgentSync.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index 94d0cc4413..0a25674f56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ All notable changes to the Wazuh app project will be documented in this file. ### Fixed - 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) ### Removed diff --git a/plugins/main/public/components/common/hocs/withAgentSync.tsx b/plugins/main/public/components/common/hocs/withAgentSync.tsx new file mode 100644 index 0000000000..b1be76b99a --- /dev/null +++ b/plugins/main/public/components/common/hocs/withAgentSync.tsx @@ -0,0 +1,26 @@ +/* + * Wazuh app - React HOCs handles rendering errors + * Copyright (C) 2015-2022 Wazuh, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Find more information about this on the LICENSE file. + */ + +import React, { useState, useEffect } from 'react'; +import { PinnedAgentManager } from '../../wz-agent-selector/wz-agent-selector-service'; +import { withGuardAsync } from './withGuard'; + +export const withAgentSync = WrappedComponent => props => { + const [loading, setLoading] = useState(true); + useEffect(() => { + const pinnedAgentManager = new PinnedAgentManager(); + pinnedAgentManager.syncPinnedAgentSources().finally(() => { + setLoading(false); + }); + }, []); + return loading ? null : ; +}; diff --git a/plugins/main/public/components/endpoints-summary/agent/index.tsx b/plugins/main/public/components/endpoints-summary/agent/index.tsx index d30b618052..00201ca0bc 100644 --- a/plugins/main/public/components/endpoints-summary/agent/index.tsx +++ b/plugins/main/public/components/endpoints-summary/agent/index.tsx @@ -27,6 +27,7 @@ import { PromptNoSelectedAgent } from '../../agents/prompts'; import { RedirectAppLinks } from '../../../../../../src/plugins/opensearch_dashboards_react/public'; import { getCore } from '../../../kibana-services'; import { endpointSummary } from '../../../utils/applications'; +import { withAgentSync } from '../../common/hocs/withAgentSync'; const mapStateToProps = state => ({ agent: state.appStateReducers?.currentAgentData, @@ -36,6 +37,7 @@ export const AgentView = compose( withErrorBoundary, withRouteResolvers({ enableMenu, ip, nestedResolve, savedSearch }), connect(mapStateToProps), + withAgentSync, withGuard( props => !(props.agent && props.agent.id), () => ( From 663fc9e6b02e2acdbc5024b4dd765e7a8e98af22 Mon Sep 17 00:00:00 2001 From: Guido Modarelli <38738725+guidomodarelli@users.noreply.github.com> Date: Tue, 1 Oct 2024 08:35:33 -0300 Subject: [PATCH 09/41] Update malware feature description (#7036) * Update malware detection description in Wazuh modules * Update malware feature description * Update md5 value for a specific test case --- CHANGELOG.md | 1 + plugins/main/common/wazuh-modules.ts | 2 +- plugins/main/public/utils/applications.ts | 2 +- plugins/main/server/routes/wazuh-reporting.test.ts | 4 +--- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a25674f56..aa376214f9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ All notable changes to the Wazuh app project will be documented in this file. - Update malware detection group values in data sources [#6963](https://github.com/wazuh/wazuh-dashboard-plugins/issues/6963) - Changed the registration id of the Settings application for compatibility with OpenSearch Dashboard 2.16.0 [#6938](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6938) - Changed Malware detection dashboard visualizations [#6964](https://github.com/wazuh/wazuh-dashboard-plugins/issues/6964) +- Changed malware feature description [#7036](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7036) ### Fixed diff --git a/plugins/main/common/wazuh-modules.ts b/plugins/main/common/wazuh-modules.ts index 341300f65d..7b779b2ec1 100644 --- a/plugins/main/common/wazuh-modules.ts +++ b/plugins/main/common/wazuh-modules.ts @@ -26,7 +26,7 @@ export const WAZUH_MODULES = { title: 'Malware detection', appId: 'malware-detection', description: - 'Verify that your systems are configured according to your security policies baseline.', + 'Check indicators of compromise triggered by malware infections or cyberattacks.', }, vuls: { title: 'Vulnerability detection', diff --git a/plugins/main/public/utils/applications.ts b/plugins/main/public/utils/applications.ts index 2333823b68..3c14fad9a1 100644 --- a/plugins/main/public/utils/applications.ts +++ b/plugins/main/public/utils/applications.ts @@ -112,7 +112,7 @@ export const malwareDetection = { }), description: i18n.translate('wz-app-malware-detection-description', { defaultMessage: - 'Verify that your systems are configured according to your security policies baseline.', + 'Check indicators of compromise triggered by malware infections or cyberattacks.', }), euiIconType: 'indexRollupApp', order: 201, diff --git a/plugins/main/server/routes/wazuh-reporting.test.ts b/plugins/main/server/routes/wazuh-reporting.test.ts index c5ef7494d0..21760bafe5 100644 --- a/plugins/main/server/routes/wazuh-reporting.test.ts +++ b/plugins/main/server/routes/wazuh-reporting.test.ts @@ -229,7 +229,7 @@ describe('[endpoint] PUT /utils/configuration', () => { // If any of the parameters is changed this variable should be updated with the new md5 it.each` footer | header | responseStatusCode | expectedMD5 | tab - ${null} | ${null} | ${200} | ${'2a8dfb6e1fa377ce6a235bd5b4b701b5'} | ${'pm'} + ${null} | ${null} | ${200} | ${'dc7edb68490376cdb70535f420ba82d3'} | ${'pm'} ${'Custom\nFooter'} | ${'info@company.com\nFake Avenue 123'} | ${200} | ${'9003caabb5a3ef69b4b7e56e8c549011'} | ${'general'} ${''} | ${''} | ${200} | ${'66bd70790000b5016f42775653a0f169'} | ${'fim'} ${'Custom Footer'} | ${null} | ${200} | ${'ed1b880b6141fde5c9109178ea112646'} | ${'aws'} @@ -327,8 +327,6 @@ describe('[endpoint] PUT /utils/configuration', () => { .send(reportBody); // .expect(200); - console.log({ responseReport }); - const fileName = responseReport.body?.message.match(/([A-Z-0-9]*\.pdf)/gi)[0]; const userPath = md5(USER_NAME); From 0a402f1ef517839504b0cca061948532faa34f51 Mon Sep 17 00:00:00 2001 From: Guido Modarelli <38738725+guidomodarelli@users.noreply.github.com> Date: Tue, 1 Oct 2024 11:48:55 -0300 Subject: [PATCH 10/41] Increase the font size of the kpi subtitles and the features descriptions (#7033) * Remove font-size property from welcome.scss * Refactor LastAlertsStat component for readability * Fix Merge Conflict * Refactor LastAlertsStat component and severities object * Update font size for KPI subtitles and feature descriptions * Update text size to 's' in LastAlertsStat component * Update class size to "small" in Stats component snapshot --- CHANGELOG.md | 1 + .../components/common/welcome/welcome.scss | 1 - .../__snapshots__/stats.test.tsx.snap | 8 +- .../last-alerts-stat/last-alerts-stat.tsx | 105 ++++++++++-------- 4 files changed, 61 insertions(+), 54 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aa376214f9..a94d836602 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ 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://github.com/wazuh/wazuh-dashboard-plugins/pull/6938) - Changed Malware detection dashboard visualizations [#6964](https://github.com/wazuh/wazuh-dashboard-plugins/issues/6964) - Changed malware feature description [#7036](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7036) +- Changed the font size of the kpi subtitles and the features descriptions [#7033](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7033) ### Fixed diff --git a/plugins/main/public/components/common/welcome/welcome.scss b/plugins/main/public/components/common/welcome/welcome.scss index 9058ab441c..0ce9e18dda 100644 --- a/plugins/main/public/components/common/welcome/welcome.scss +++ b/plugins/main/public/components/common/welcome/welcome.scss @@ -6,7 +6,6 @@ .wz-welcome-page .euiCard .euiText, .wz-module-body .euiCard .euiText { - font-size: 12px; font-family: sans-serif; } diff --git a/plugins/main/public/controllers/overview/components/__snapshots__/stats.test.tsx.snap b/plugins/main/public/controllers/overview/components/__snapshots__/stats.test.tsx.snap index 29b8d3d0da..4b0953aba0 100644 --- a/plugins/main/public/controllers/overview/components/__snapshots__/stats.test.tsx.snap +++ b/plugins/main/public/controllers/overview/components/__snapshots__/stats.test.tsx.snap @@ -139,7 +139,7 @@ exports[`Stats component renders correctly to match the snapshot 1`] = `

Rule level 15 or higher @@ -184,7 +184,7 @@ exports[`Stats component renders correctly to match the snapshot 1`] = `

Rule level 12 to 14 @@ -229,7 +229,7 @@ exports[`Stats component renders correctly to match the snapshot 1`] = `

Rule level 7 to 11 @@ -274,7 +274,7 @@ exports[`Stats component renders correctly to match the snapshot 1`] = `

Rule level 0 to 6 diff --git a/plugins/main/public/controllers/overview/components/last-alerts-stat/last-alerts-stat.tsx b/plugins/main/public/controllers/overview/components/last-alerts-stat/last-alerts-stat.tsx index e1113790d5..4f51cf8600 100644 --- a/plugins/main/public/controllers/overview/components/last-alerts-stat/last-alerts-stat.tsx +++ b/plugins/main/public/controllers/overview/components/last-alerts-stat/last-alerts-stat.tsx @@ -20,48 +20,59 @@ import { PatternDataSourceFilterManager, } from '../../../../components/common/data-source/pattern/pattern-data-source-filter-manager'; -export function LastAlertsStat({ severity }: { severity: string }) { - const [countLastAlerts, setCountLastAlerts] = useState(null); - const [discoverLocation, setDiscoverLocation] = useState(''); - const severityLabel = { - low: { - label: 'Low', - color: UI_COLOR_STATUS.success, - ruleLevelRange: { - minRuleLevel: 0, - maxRuleLevel: 6, - }, +type SeverityKey = 'low' | 'medium' | 'high' | 'critical'; + +const severities = { + low: { + label: 'Low', + color: UI_COLOR_STATUS.success, + ruleLevelRange: { + minRuleLevel: 0, + maxRuleLevel: 6, }, - medium: { - label: 'Medium', - color: UI_COLOR_STATUS.info, - ruleLevelRange: { - minRuleLevel: 7, - maxRuleLevel: 11, - }, + }, + medium: { + label: 'Medium', + color: UI_COLOR_STATUS.info, + ruleLevelRange: { + minRuleLevel: 7, + maxRuleLevel: 11, }, - high: { - label: 'High', - color: UI_COLOR_STATUS.warning, - ruleLevelRange: { - minRuleLevel: 12, - maxRuleLevel: 14, - }, + }, + high: { + label: 'High', + color: UI_COLOR_STATUS.warning, + ruleLevelRange: { + minRuleLevel: 12, + maxRuleLevel: 14, }, - critical: { - label: 'Critical', - color: UI_COLOR_STATUS.danger, - ruleLevelRange: { - minRuleLevel: 15, - }, + }, + critical: { + label: 'Critical', + color: UI_COLOR_STATUS.danger, + ruleLevelRange: { + minRuleLevel: 15, + maxRuleLevel: undefined, }, - }; + }, +} as const; + +export function LastAlertsStat({ + severity: severityKey, +}: { + severity: SeverityKey; +}) { + const [countLastAlerts, setCountLastAlerts] = useState(null); + const [discoverLocation, setDiscoverLocation] = useState(''); + + const severity = severities[severityKey]; + const ruleLevelRange = severity.ruleLevelRange; useEffect(() => { const getCountLastAlerts = async () => { try { const { indexPatternId, cluster, count } = await getLast24HoursAlerts( - severityLabel[severity].ruleLevelRange, + ruleLevelRange, ); setCountLastAlerts(count); const core = getCore(); @@ -82,10 +93,7 @@ export function LastAlertsStat({ severity }: { severity: string }) { PatternDataSourceFilterManager.createFilter( FILTER_OPERATOR.IS_BETWEEN, 'rule.level', - [ - severityLabel[severity].ruleLevelRange.minRuleLevel, - severityLabel[severity].ruleLevelRange.maxRuleLevel, - ], + [ruleLevelRange.minRuleLevel, ruleLevelRange.maxRuleLevel], indexPatternId, ); const predefinedFilters = @@ -117,20 +125,19 @@ export function LastAlertsStat({ severity }: { severity: string }) { @@ -138,16 +145,16 @@ export function LastAlertsStat({ severity }: { severity: string }) { } - description={`${severityLabel[severity].label} severity`} + description={`${severity.label} severity`} descriptionElement='h3' - titleColor={severityLabel[severity].color} + titleColor={severity.color} textAlign='center' /> - + {'Rule level ' + - severityLabel[severity].ruleLevelRange.minRuleLevel + - (severityLabel[severity].ruleLevelRange.maxRuleLevel - ? ' to ' + severityLabel[severity].ruleLevelRange.maxRuleLevel + ruleLevelRange.minRuleLevel + + (ruleLevelRange.maxRuleLevel + ? ' to ' + ruleLevelRange.maxRuleLevel : ' or higher')} From 23c8dc583808ef4aab7486b5bdc08a3d85632bbd Mon Sep 17 00:00:00 2001 From: Federico Rodriguez Date: Tue, 1 Oct 2024 17:23:28 +0200 Subject: [PATCH 11/41] Filter deprecated actions (#7042) * Filter deprecated actions * Add changelog * Update plugins/main/public/components/security/policies/edit-policy.tsx Co-authored-by: Guido Modarelli <38738725+guidomodarelli@users.noreply.github.com> --------- Co-authored-by: Guido Modarelli <38738725+guidomodarelli@users.noreply.github.com> --- CHANGELOG.md | 3 ++- .../components/security/policies/edit-policy.tsx | 14 ++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a94d836602..c144e2ddeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,7 +21,8 @@ All notable changes to the Wazuh app project will be documented in this file. ### Fixed - 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 no-agent-alert spawn with selected agent in agent-welcome view [#7029](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7029) +- Fixed security policy exception when it contained deprecated actions [#7042](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7042) ### Removed diff --git a/plugins/main/public/components/security/policies/edit-policy.tsx b/plugins/main/public/components/security/policies/edit-policy.tsx index 17485f96d3..ba8e95fbef 100644 --- a/plugins/main/public/components/security/policies/edit-policy.tsx +++ b/plugins/main/public/components/security/policies/edit-policy.tsx @@ -130,16 +130,18 @@ export const EditPolicyFlyout = ({ policy, closeFlyout }) => { ), }; }) - .sort((a, b) => a.value.localeCompare(b.value)); + .sort((a, b) => a.value?.localeCompare(b.value)); setActions(actions); } const loadResources = () => { let allResources = []; - addedActions.forEach(x => { - const res = (availableActions[x.action] || {})['resources']; - allResources = allResources.concat(res); - }); + addedActions + .filter(x => !!availableActions?.[x.action]) // Remove configured actions no longer available on the API + .forEach(x => { + const res = availableActions[x.action]?.['resources']; + allResources = allResources.concat(res); + }); const allResourcesSet = new Set(allResources); const resources = Array.from(allResourcesSet) .map((x, idx) => { @@ -159,7 +161,7 @@ export const EditPolicyFlyout = ({ policy, closeFlyout }) => { ), }; }) - .sort((a, b) => a.value.localeCompare(b.value)); + .sort((a, b) => a.value?.localeCompare(b.value)); setResources(resources); }; From 628f6549d19c5f5779413fff03b7227401631cf4 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Mon, 30 Sep 2024 09:00:48 -0300 Subject: [PATCH 12/41] Add padding to welcome page and stats component --- plugins/main/public/components/common/welcome/welcome.scss | 4 ++++ plugins/main/public/controllers/overview/components/stats.js | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/main/public/components/common/welcome/welcome.scss b/plugins/main/public/components/common/welcome/welcome.scss index 0ce9e18dda..e2756c0b80 100644 --- a/plugins/main/public/components/common/welcome/welcome.scss +++ b/plugins/main/public/components/common/welcome/welcome.scss @@ -48,3 +48,7 @@ span.statWithLink:hover { display: flex; flex-grow: 1; } + +.wz-welcome-page { + padding-bottom: 24px; +} \ No newline at end of file diff --git a/plugins/main/public/controllers/overview/components/stats.js b/plugins/main/public/controllers/overview/components/stats.js index 782e7c9638..685a68aee1 100644 --- a/plugins/main/public/controllers/overview/components/stats.js +++ b/plugins/main/public/controllers/overview/components/stats.js @@ -82,7 +82,7 @@ export const Stats = withErrorBoundary( ({ status }) => this.props[status], ); return ( - + From 43f52c435dbdea986be8b72389e0b8cd13af2b71 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Mon, 30 Sep 2024 09:01:56 -0300 Subject: [PATCH 13/41] Update stats page styling with welcome stats class --- plugins/main/public/controllers/overview/components/stats.js | 2 +- .../main/public/controllers/overview/components/stats.scss | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/main/public/controllers/overview/components/stats.js b/plugins/main/public/controllers/overview/components/stats.js index 685a68aee1..35b8bc09f3 100644 --- a/plugins/main/public/controllers/overview/components/stats.js +++ b/plugins/main/public/controllers/overview/components/stats.js @@ -82,7 +82,7 @@ export const Stats = withErrorBoundary( ({ status }) => this.props[status], ); return ( - + diff --git a/plugins/main/public/controllers/overview/components/stats.scss b/plugins/main/public/controllers/overview/components/stats.scss index 8e8bfcf937..6bec32a9fa 100644 --- a/plugins/main/public/controllers/overview/components/stats.scss +++ b/plugins/main/public/controllers/overview/components/stats.scss @@ -1,3 +1,8 @@ .vulnerabilites-summary-card { padding-top: 2vh; } + +.wz-welcome-stats { + padding-top: 24px; + padding-bottom: 8px; +} \ No newline at end of file From ba28cc12fd6005a6053f79231f70a7907cb7df28 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Mon, 30 Sep 2024 09:02:24 -0300 Subject: [PATCH 14/41] Update imports and component structure in stats.js --- .../controllers/overview/components/stats.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/plugins/main/public/controllers/overview/components/stats.js b/plugins/main/public/controllers/overview/components/stats.js index 35b8bc09f3..ab06446131 100644 --- a/plugins/main/public/controllers/overview/components/stats.js +++ b/plugins/main/public/controllers/overview/components/stats.js @@ -10,25 +10,25 @@ * * Find more information about this on the LICENSE file. */ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; import { EuiCard, - EuiFlexItem, EuiFlexGroup, + EuiFlexItem, EuiPage, EuiToolTip, } from '@elastic/eui'; -import { withErrorBoundary } from '../../../components/common/hocs'; +import PropTypes from 'prop-types'; +import { Component } from 'react'; import { API_NAME_AGENT_STATUS } from '../../../../common/constants'; import { - agentStatusLabelByAgentStatus, agentStatusColorByAgentStatus, + agentStatusLabelByAgentStatus, } from '../../../../common/services/wz_agent_status'; -import { endpointSummary } from '../../../utils/applications'; -import { LastAlertsStat } from './last-alerts-stat'; import { VisualizationBasic } from '../../../components/common/charts/visualizations/basic'; +import { withErrorBoundary } from '../../../components/common/hocs'; import NavigationService from '../../../react-services/navigation-service'; +import { endpointSummary } from '../../../utils/applications'; +import { LastAlertsStat } from './last-alerts-stat'; import './stats.scss'; export const Stats = withErrorBoundary( class Stats extends Component { From f817ef931f2ae20edc4b159cb38bc8a336c9a4cc Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Mon, 30 Sep 2024 09:37:21 -0300 Subject: [PATCH 15/41] Adjust padding in welcome and stats components --- plugins/main/public/components/common/welcome/welcome.scss | 2 +- plugins/main/public/controllers/overview/components/stats.scss | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/main/public/components/common/welcome/welcome.scss b/plugins/main/public/components/common/welcome/welcome.scss index e2756c0b80..5754123f55 100644 --- a/plugins/main/public/components/common/welcome/welcome.scss +++ b/plugins/main/public/components/common/welcome/welcome.scss @@ -51,4 +51,4 @@ span.statWithLink:hover { .wz-welcome-page { padding-bottom: 24px; -} \ No newline at end of file +} diff --git a/plugins/main/public/controllers/overview/components/stats.scss b/plugins/main/public/controllers/overview/components/stats.scss index 6bec32a9fa..6d18137c71 100644 --- a/plugins/main/public/controllers/overview/components/stats.scss +++ b/plugins/main/public/controllers/overview/components/stats.scss @@ -5,4 +5,4 @@ .wz-welcome-stats { padding-top: 24px; padding-bottom: 8px; -} \ No newline at end of file +} From 4626373e6563cd82ec1b063907a3e22e468c7f76 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Mon, 30 Sep 2024 10:25:23 -0300 Subject: [PATCH 16/41] Update stats component imports and class definition --- .../components/__snapshots__/stats.test.tsx.snap | 2 +- .../controllers/overview/components/stats.js | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/main/public/controllers/overview/components/__snapshots__/stats.test.tsx.snap b/plugins/main/public/controllers/overview/components/__snapshots__/stats.test.tsx.snap index 4b0953aba0..4fe01ec984 100644 --- a/plugins/main/public/controllers/overview/components/__snapshots__/stats.test.tsx.snap +++ b/plugins/main/public/controllers/overview/components/__snapshots__/stats.test.tsx.snap @@ -3,7 +3,7 @@ exports[`Stats component renders correctly to match the snapshot 1`] = `
Date: Mon, 30 Sep 2024 10:31:39 -0300 Subject: [PATCH 17/41] Update feature container margins for consistent design --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c144e2ddeb..29ba34f4c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ All notable changes to the Wazuh app project will be documented in this file. - Changed Malware detection dashboard visualizations [#6964](https://github.com/wazuh/wazuh-dashboard-plugins/issues/6964) - Changed malware feature description [#7036](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7036) - Changed the font size of the kpi subtitles and the features descriptions [#7033](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7033) +- Changed feature container margins to ensure consistent separation and uniform design. [#7034](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7034) ### Fixed From 1ae35d8191b3859effdfb1688223be25ec2decbe Mon Sep 17 00:00:00 2001 From: Federico Rodriguez Date: Wed, 2 Oct 2024 12:04:56 +0200 Subject: [PATCH 18/41] Rename vulnerability.under_evaluation field (#7046) * Rename vulnerability.under_evaluation field * Add changelog * Prettier --- CHANGELOG.md | 2 +- .../common/components/vuls-evaluation-filter.tsx | 2 +- .../dashboards/overview/dashboard_panels_kpis.ts | 2 +- .../vulnerabilities-events-injector/DIS_Template.json | 10 +++------- .../dataInjectScript.py | 2 +- 5 files changed, 7 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c144e2ddeb..19b7e1c07d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ 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) +- Added a custom filter and visualization for vulnerability.under_evaluation field [#6968](https://github.com/wazuh/wazuh-dashboard-plugins/issues/6968) [#7046](https://github.com/wazuh/wazuh-dashboard-plugins/issues/7046) ### Changed diff --git a/plugins/main/public/components/overview/vulnerabilities/common/components/vuls-evaluation-filter.tsx b/plugins/main/public/components/overview/vulnerabilities/common/components/vuls-evaluation-filter.tsx index 590b251faa..9dd34fa203 100644 --- a/plugins/main/public/components/overview/vulnerabilities/common/components/vuls-evaluation-filter.tsx +++ b/plugins/main/public/components/overview/vulnerabilities/common/components/vuls-evaluation-filter.tsx @@ -11,7 +11,7 @@ type VulsEvaluatedFilterProps = { value: boolean | null; }; -const UNDER_EVALUATION_FIELD = 'wazuh.vulnerability.under_evaluation'; +const UNDER_EVALUATION_FIELD = 'vulnerability.under_evaluation'; export const getUnderEvaluationFilterValue = ( filters: Filter[], diff --git a/plugins/main/public/components/overview/vulnerabilities/dashboards/overview/dashboard_panels_kpis.ts b/plugins/main/public/components/overview/vulnerabilities/dashboards/overview/dashboard_panels_kpis.ts index 06e49f7fcc..0fc588a169 100644 --- a/plugins/main/public/components/overview/vulnerabilities/dashboards/overview/dashboard_panels_kpis.ts +++ b/plugins/main/public/components/overview/vulnerabilities/dashboards/overview/dashboard_panels_kpis.ts @@ -409,7 +409,7 @@ const getVisStateEvaluatedEvaluationPending = (indexPatternId: string) => { { input: { language: 'kuery', - query: 'wazuh.vulnerability.under_evaluation:true', + query: 'vulnerability.under_evaluation:true', }, label: 'Pending', }, diff --git a/scripts/vulnerabilities-events-injector/DIS_Template.json b/scripts/vulnerabilities-events-injector/DIS_Template.json index 75a723b057..33fb6040c2 100644 --- a/scripts/vulnerabilities-events-injector/DIS_Template.json +++ b/scripts/vulnerabilities-events-injector/DIS_Template.json @@ -229,6 +229,9 @@ "severity": { "ignore_above": 1024, "type": "keyword" + }, + "under_evaluation": { + "type": "boolean" } } }, @@ -257,13 +260,6 @@ "type": "keyword" } } - }, - "vulnerability": { - "properties": { - "under_evaluation": { - "type": "boolean" - } - } } } } diff --git a/scripts/vulnerabilities-events-injector/dataInjectScript.py b/scripts/vulnerabilities-events-injector/dataInjectScript.py index f9e6dfbaca..447bdb257c 100644 --- a/scripts/vulnerabilities-events-injector/dataInjectScript.py +++ b/scripts/vulnerabilities-events-injector/dataInjectScript.py @@ -125,12 +125,12 @@ def generateRandomVulnerability(): vulnerability['severity'] = random.choice(['Low','Medium','High','Critical']) vulnerability['published_at'] = generateRandomDate(2000) vulnerability['detected_at'] = generateRandomDate(180) + vulnerability['under_evaluation'] = random.choice([True, False]) return(vulnerability) def generateRandomWazuh(): wazuh = {} wazuh['cluster'] = {'name':random.choice(['wazuh.manager', 'wazuh']), 'node':random.choice(['master','worker-01','worker-02','worker-03'])} - wazuh['vulnerability'] = {'under_evaluation': random.choice([True, False])} return(wazuh) def generateRandomData(number): From 58fd2278e440191ea4df682686e66f4f10d1acb3 Mon Sep 17 00:00:00 2001 From: Federico Rodriguez Date: Wed, 2 Oct 2024 12:33:55 +0200 Subject: [PATCH 19/41] Fix data grid pagination with relative index per page (#7044) * Fix data grid pagination with relative row index * Add changelog --- CHANGELOG.md | 2 +- .../public/components/common/data-grid/use-data-grid.tsx | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 19b7e1c07d..7b104e2868 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ 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) [#7046](https://github.com/wazuh/wazuh-dashboard-plugins/issues/7046) +- 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) ### Changed diff --git a/plugins/main/public/components/common/data-grid/use-data-grid.tsx b/plugins/main/public/components/common/data-grid/use-data-grid.tsx index d85d5898ea..ebc58594da 100644 --- a/plugins/main/public/components/common/data-grid/use-data-grid.tsx +++ b/plugins/main/public/components/common/data-grid/use-data-grid.tsx @@ -166,7 +166,10 @@ export const useDataGrid = (props: tDataGridProps): EuiDataGridProps => { // Format the value using the field formatter // https://github.com/opensearch-project/OpenSearch-Dashboards/blob/2.16.0/src/plugins/discover/public/application/components/data_grid/data_grid_table_cell_value.tsx#L80-L89 - const formattedValue = indexPattern.formatField(rows[rowIndex], columnId); + const formattedValue = indexPattern.formatField( + rows[relativeRowIndex], + columnId, + ); if (typeof formattedValue === 'undefined') { return -; } else { From 7bf3e985146617c8441e4770771f01a7e1e270ec Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Wed, 2 Oct 2024 07:38:11 -0300 Subject: [PATCH 20/41] Refactor overview components layout and structure --- .../common/welcome/overview-welcome.js | 106 ++++++++---------- .../public/components/overview/overview.tsx | 15 ++- .../controllers/overview/components/stats.js | 84 ++++++-------- 3 files changed, 97 insertions(+), 108 deletions(-) diff --git a/plugins/main/public/components/common/welcome/overview-welcome.js b/plugins/main/public/components/common/welcome/overview-welcome.js index 868136ddc9..1ba09d2153 100644 --- a/plugins/main/public/components/common/welcome/overview-welcome.js +++ b/plugins/main/public/components/common/welcome/overview-welcome.js @@ -21,7 +21,6 @@ import { EuiSpacer, EuiFlexGrid, EuiCallOut, - EuiPage, } from '@elastic/eui'; import './welcome.scss'; import { withErrorBoundary, withGlobalBreadcrumb } from '../hocs'; @@ -111,63 +110,56 @@ export const OverviewWelcome = compose( render() { return ( - - - - - {this.props.agentsCountTotal === 0 && this.addAgent()} - - - {appCategories.map(({ label, apps }) => ( - - category.id === label) - ?.label - } - > - - - {apps.map(app => ( - - - - } - className='homSynopsis__card' - title={app.title} - href={NavigationService.getInstance().getUrlForApp( - app.id, - )} - data-test-subj={`overviewWelcome${this.strtools.capitalize( - app.id, - )}`} - description={app.description} - /> - - - ))} - - - - ))} - - - + + + {this.props.agentsCountTotal === 0 && this.addAgent()} + + + {appCategories.map(({ label, apps }) => ( + + category.id === label) + ?.label + } + > + + + {apps.map(app => ( + + + + } + className='homSynopsis__card' + title={app.title} + href={NavigationService.getInstance().getUrlForApp( + app.id, + )} + data-test-subj={`overviewWelcome${this.strtools.capitalize( + app.id, + )}`} + description={app.description} + /> + + + ))} + + + + ))} + - - + + ); } }, diff --git a/plugins/main/public/components/overview/overview.tsx b/plugins/main/public/components/overview/overview.tsx index 12476ad0a7..56afe727c8 100644 --- a/plugins/main/public/components/overview/overview.tsx +++ b/plugins/main/public/components/overview/overview.tsx @@ -1,4 +1,5 @@ import React, { useEffect, useState } from 'react'; +import { EuiPage, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; import { getDataPlugin, getUiSettings } from '../../kibana-services'; import { Stats } from '../../controllers/overview/components/stats'; import { AppState, WzRequest } from '../../react-services'; @@ -158,10 +159,16 @@ export const Overview: React.FC = withRouteResolvers({ )} {tab === 'welcome' && ( - <> - - - + + + + + + + + + + )} ); diff --git a/plugins/main/public/controllers/overview/components/stats.js b/plugins/main/public/controllers/overview/components/stats.js index 35b8bc09f3..46b9125f04 100644 --- a/plugins/main/public/controllers/overview/components/stats.js +++ b/plugins/main/public/controllers/overview/components/stats.js @@ -12,13 +12,7 @@ */ import React, { Component } from 'react'; import PropTypes from 'prop-types'; -import { - EuiCard, - EuiFlexItem, - EuiFlexGroup, - EuiPage, - EuiToolTip, -} from '@elastic/eui'; +import { EuiCard, EuiFlexItem, EuiFlexGroup, EuiToolTip } from '@elastic/eui'; import { withErrorBoundary } from '../../../components/common/hocs'; import { API_NAME_AGENT_STATUS } from '../../../../common/constants'; import { @@ -82,46 +76,42 @@ export const Stats = withErrorBoundary( ({ status }) => this.props[status], ); return ( - - - - - ({ - onClick, - label, - value: - typeof this.props[status] !== 'undefined' - ? this.props[status] - : 0, - color, - }), - ) - } - noDataTitle='No results' - noDataMessage='No results were found.' - /> - - - - - - - - - - - - - - + + + + ({ + onClick, + label, + value: + typeof this.props[status] !== 'undefined' + ? this.props[status] + : 0, + color, + })) + } + noDataTitle='No results' + noDataMessage='No results were found.' + /> + + + + + + + + + + + + + ); } }, From b6cca953da38d76228a8fc4185c73ed5d53b4f5d Mon Sep 17 00:00:00 2001 From: JuanGarriuz Date: Wed, 2 Oct 2024 17:46:37 +0200 Subject: [PATCH 21/41] Change agents summary no results (#7041) * Change agent summary render * Added Changelog * updated snaps * solve styles bug * Update Snaps * Move redirect url to a const * Change deploy text * Solve test faillure --------- Co-authored-by: Federico Rodriguez --- CHANGELOG.md | 1 + .../__snapshots__/stats.test.tsx.snap | 71 ++++++++++--------- .../controllers/overview/components/stats.js | 59 +++++++++++---- .../overview/components/stats.test.tsx | 31 ++++++++ 4 files changed, 116 insertions(+), 46 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b104e2868..6c95580692 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ All notable changes to the Wazuh app project will be documented in this file. - Update malware detection group values in data sources [#6963](https://github.com/wazuh/wazuh-dashboard-plugins/issues/6963) - Changed the registration id of the Settings application for compatibility with OpenSearch Dashboard 2.16.0 [#6938](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6938) - Changed Malware detection dashboard visualizations [#6964](https://github.com/wazuh/wazuh-dashboard-plugins/issues/6964) +- Changed the agents summary in overview with no results to an agent deployment help message. [#7041](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7041) - Changed malware feature description [#7036](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7036) - Changed the font size of the kpi subtitles and the features descriptions [#7033](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7033) diff --git a/plugins/main/public/controllers/overview/components/__snapshots__/stats.test.tsx.snap b/plugins/main/public/controllers/overview/components/__snapshots__/stats.test.tsx.snap index 4b0953aba0..1f7b3597f0 100644 --- a/plugins/main/public/controllers/overview/components/__snapshots__/stats.test.tsx.snap +++ b/plugins/main/public/controllers/overview/components/__snapshots__/stats.test.tsx.snap @@ -25,47 +25,52 @@ exports[`Stats component renders correctly to match the snapshot 1`] = ` class="euiCard__children" >
-
-
-

- No results -

+

+ This instance has no agents registered. +
+ Please deploy agents to begin monitoring your endpoints. +

+
+ +
+
diff --git a/plugins/main/public/controllers/overview/components/stats.js b/plugins/main/public/controllers/overview/components/stats.js index 782e7c9638..60d1c790bf 100644 --- a/plugins/main/public/controllers/overview/components/stats.js +++ b/plugins/main/public/controllers/overview/components/stats.js @@ -18,6 +18,7 @@ import { EuiFlexGroup, EuiPage, EuiToolTip, + EuiEmptyPrompt, } from '@elastic/eui'; import { withErrorBoundary } from '../../../components/common/hocs'; import { API_NAME_AGENT_STATUS } from '../../../../common/constants'; @@ -30,6 +31,8 @@ import { LastAlertsStat } from './last-alerts-stat'; import { VisualizationBasic } from '../../../components/common/charts/visualizations/basic'; import NavigationService from '../../../react-services/navigation-service'; import './stats.scss'; +import { WzButtonPermissions } from '../../../components/common/permissions/button'; + export const Stats = withErrorBoundary( class Stats extends Component { constructor(props) { @@ -81,19 +84,19 @@ export const Stats = withErrorBoundary( const hasResults = this.agentStatus.some( ({ status }) => this.props[status], ); + return ( - ({ onClick, label, @@ -103,11 +106,41 @@ export const Stats = withErrorBoundary( : 0, color, }), - ) - } - noDataTitle='No results' - noDataMessage='No results were found.' - /> + )} + /> + ) : ( + !hasResults && + this.props !== undefined && ( + + This instance has no agents registered. +
+ Please deploy agents to begin monitoring your + endpoints. +

+ } + actions={ + + Deploy new agent + + } + /> + ) + )}
diff --git a/plugins/main/public/controllers/overview/components/stats.test.tsx b/plugins/main/public/controllers/overview/components/stats.test.tsx index 0e03c26535..574fb4ac79 100644 --- a/plugins/main/public/controllers/overview/components/stats.test.tsx +++ b/plugins/main/public/controllers/overview/components/stats.test.tsx @@ -16,6 +16,37 @@ import React from 'react'; import { render, act } from '@testing-library/react'; import '@testing-library/jest-dom'; import { Stats } from './stats'; +import jsonBeautifier from '../../../utils/json-beautifier'; + +jest.mock('../../../react-services/navigation-service', () => { + return { + getInstance() { + return { + getUrlForApp() { + return ''; + }, + }; + }, + }; +}); + +jest.mock('../../../components/common/hooks/use-user-is-admin', () => { + return { + useUserPermissionsIsAdminRequirements() { + console.log('UserPermisionsIsAdmin'); + return ['', []]; + }, + }; +}); + +jest.mock('../../../components/common/hooks/useUserPermissions', () => { + return { + useUserPermissionsRequirements() { + console.log('UserPermisions'); + return [false, []]; + }, + }; +}); jest.mock( '../../../../../../node_modules/@elastic/eui/lib/services/accessibility/html_id_generator', From 4431ff6ec8893be241df224a9cb35a4bd1c742aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chantal=20Bel=C3=A9n=20kelm?= <99441266+chantal-kelm@users.noreply.github.com> Date: Wed, 2 Oct 2024 13:21:57 -0300 Subject: [PATCH 22/41] Fix the filter are displayed cropped on screens of 575px to 767px (#7047) * fix the filter are displayed cropped on screens of 575px to 767px * update changelog * update changelog --------- Co-authored-by: Federico Rodriguez --- CHANGELOG.md | 4 + .../common/search-bar/search-bar.tsx | 5 +- plugins/main/public/styles/media-queries.scss | 140 +++++++++++------- 3 files changed, 96 insertions(+), 53 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c95580692..e327d5cc21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ All notable changes to the Wazuh app project will be documented in this file. ## Wazuh v4.10.0 - OpenSearch Dashboards 2.16.0 - Revision 01 +## Fixed + +- 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) + ### Added - Support for Wazuh 4.10.0 diff --git a/plugins/main/public/components/common/search-bar/search-bar.tsx b/plugins/main/public/components/common/search-bar/search-bar.tsx index 8c7b57144a..c6cc9a4bf9 100644 --- a/plugins/main/public/components/common/search-bar/search-bar.tsx +++ b/plugins/main/public/components/common/search-bar/search-bar.tsx @@ -6,6 +6,7 @@ import { SearchBarProps, Filter, } from '../../../../../../src/plugins/data/public'; +import '../../../../public/styles/media-queries.scss'; export interface WzSearchBarProps extends SearchBarProps { fixedFilters?: Filter[]; @@ -85,14 +86,14 @@ export const WzSearchBar = ({
)} - + - + .euiFlexItem { + margin-bottom: 0 !important; + } + } + + @media only screen and (min-width: 575px) and (max-width: 767px) { + .globalFilterGroup__wrapper-isVisible { + .euiFlexItem.euiFlexItem--flexGrowZero { + margin-bottom: 0px; + } + } + } + + @media only screen and (min-width: 575px) and (max-width: 767px) { + .euiFlexGroup--responsive { + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + margin-left: 0; + margin-right: 0; + margin-bottom: 6px; + margin-top: 10px; } + } } From d3f1dd5d9507aad46adefbdb53e0d0873237db13 Mon Sep 17 00:00:00 2001 From: JuanGarriuz Date: Wed, 2 Oct 2024 18:45:23 +0200 Subject: [PATCH 23/41] Changed Mitre overview description (#7032) * Changed description * Update Changelog * change description in wazuh-modules * Fixed a typo --------- Co-authored-by: Federico Rodriguez --- CHANGELOG.md | 1 + plugins/main/README.md | 2 +- plugins/main/common/wazuh-modules.ts | 2 +- plugins/main/public/utils/applications.ts | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e327d5cc21..f1cac93806 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ All notable changes to the Wazuh app project will be documented in this file. - Update malware detection group values in data sources [#6963](https://github.com/wazuh/wazuh-dashboard-plugins/issues/6963) - Changed the registration id of the Settings application for compatibility with OpenSearch Dashboard 2.16.0 [#6938](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6938) - Changed Malware detection dashboard visualizations [#6964](https://github.com/wazuh/wazuh-dashboard-plugins/issues/6964) +- Changed MITRE ATT&CK overview description [#7032](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7032) - Changed the agents summary in overview with no results to an agent deployment help message. [#7041](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7041) - Changed malware feature description [#7036](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7036) - Changed the font size of the kpi subtitles and the features descriptions [#7033](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7033) diff --git a/plugins/main/README.md b/plugins/main/README.md index 0d48293988..0d60d6fd32 100644 --- a/plugins/main/README.md +++ b/plugins/main/README.md @@ -25,7 +25,7 @@ the Wazuh Indexer. The plugin provides the following capabilities: - CIS-CAT: Configuration assessment using Center of Internet Security scanner and SCAP checks. - Threat Detection and Response - Vulnerabilities: Discover what applications in your environment are affected by well-known vulnerabilities. - - MITRE ATT&CK: Security events from the knowledge base of adversary tactics and techniques based on real-world observations. + - MITRE ATT&CK: Explore security alerts mapped to adversary tactics and techniques for better threat understanding. - VirusTotal: Alerts resulting from VirusTotal analysis of suspicious files via an integration with their API. - Osquery: Osquery can be used to expose an operating system as a high-performance relational database. - Docker listener: Monitor and collect the activity from Docker containers such as creation, running, starting, stopping or pausing events. diff --git a/plugins/main/common/wazuh-modules.ts b/plugins/main/common/wazuh-modules.ts index 7b779b2ec1..82eb87c3bf 100644 --- a/plugins/main/common/wazuh-modules.ts +++ b/plugins/main/common/wazuh-modules.ts @@ -109,7 +109,7 @@ export const WAZUH_MODULES = { title: 'MITRE ATT&CK', appId: 'mitre-attack', description: - 'Security events from the knowledge base of adversary tactics and techniques based on real-world observations', + 'Explore security alerts mapped to adversary tactics and techniques for better threat understanding.', }, syscollector: { title: 'Inventory data', diff --git a/plugins/main/public/utils/applications.ts b/plugins/main/public/utils/applications.ts index 3c14fad9a1..4db8e2d751 100644 --- a/plugins/main/public/utils/applications.ts +++ b/plugins/main/public/utils/applications.ts @@ -218,7 +218,7 @@ export const mitreAttack = { }), description: i18n.translate('wz-app-mitre-attack-description', { defaultMessage: - 'Security events from the knowledge base of adversary tactics and techniques based on real-world observations.', + 'Explore security alerts mapped to adversary tactics and techniques for better threat understanding.', }), euiIconType: 'grokApp', order: 302, From d14e2f6c5f67bc97832a6da4eb3cf3afbd1db480 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Wed, 2 Oct 2024 13:45:49 -0300 Subject: [PATCH 24/41] Update stats test snapshot for component changes --- .../__snapshots__/stats.test.tsx.snap | 402 +++++++++--------- 1 file changed, 199 insertions(+), 203 deletions(-) diff --git a/plugins/main/public/controllers/overview/components/__snapshots__/stats.test.tsx.snap b/plugins/main/public/controllers/overview/components/__snapshots__/stats.test.tsx.snap index 4fe01ec984..d0b8785bbf 100644 --- a/plugins/main/public/controllers/overview/components/__snapshots__/stats.test.tsx.snap +++ b/plugins/main/public/controllers/overview/components/__snapshots__/stats.test.tsx.snap @@ -3,299 +3,295 @@ exports[`Stats component renders correctly to match the snapshot 1`] = `
+
-
+
+

+ No results +

+ -
-

- No results -

- -
-
- No results were found. -
- -
+ No results were found. +
+
+
+ - - Agents summary - + Agents summary -
+
+
+
+
-
+
+ Rule level 15 or higher
+
+
+
+ Rule level 12 to 14
+
+
+
+ Rule level 7 to 11
+
+
+
+ Rule level 0 to 6
+
+ - - Last 24 hours alerts - + Last 24 hours alerts -
+
From 8b18817635fb3e2ea862317aa27bd396adcee568 Mon Sep 17 00:00:00 2001 From: Maximiliano Ibarra <6089438+Machi3mfl@users.noreply.github.com> Date: Wed, 2 Oct 2024 14:09:47 -0300 Subject: [PATCH 25/41] Fix export formatted csv data with special characters from tables (#7048) * Scape doublequotes on export * Add sanitize to the new line character * Update CHANGELOG * Apply prettier * Apply prettier * Scape linebreak --------- Co-authored-by: Federico Rodriguez --- CHANGELOG.md | 1 + .../components/common/data-grid/data-grid-service.ts | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1cac93806..c8f3be31da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ 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 security policy exception when it contained deprecated actions [#7042](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7042) +- Fix export formatted csv data with special characters from tables [#7048](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7048) ### Removed diff --git a/plugins/main/public/components/common/data-grid/data-grid-service.ts b/plugins/main/public/components/common/data-grid/data-grid-service.ts index 35151a2f2d..bdd6cace7e 100644 --- a/plugins/main/public/components/common/data-grid/data-grid-service.ts +++ b/plugins/main/public/components/common/data-grid/data-grid-service.ts @@ -170,7 +170,12 @@ export const exportSearchToCSV = async ( if (typeof value === 'object') { return JSON.stringify(value); } - return `"${value}"`; + // Escape double quotes and handle line breaks to prevent column misalignment + return `"${value + .toString() + .replaceAll(/"/g, '""') + .replaceAll(/\r\n/g, '\\r\\n') + .replaceAll(/\n/g, '\\n')}"`; }); return parsedRow?.join(','); }) From b7f040cdab2ebe829b216e3f8ce145d68f41e138 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Wed, 2 Oct 2024 15:51:01 -0300 Subject: [PATCH 26/41] Add grow property to EuiFlexItem and adjust card styling --- .../common/welcome/overview-welcome.js | 7 ++++--- .../components/common/welcome/welcome.scss | 20 ++----------------- 2 files changed, 6 insertions(+), 21 deletions(-) diff --git a/plugins/main/public/components/common/welcome/overview-welcome.js b/plugins/main/public/components/common/welcome/overview-welcome.js index 1ba09d2153..70af0d608b 100644 --- a/plugins/main/public/components/common/welcome/overview-welcome.js +++ b/plugins/main/public/components/common/welcome/overview-welcome.js @@ -128,9 +128,9 @@ export const OverviewWelcome = compose( {apps.map(app => ( - + } - className='homSynopsis__card' + className='wz-module-card-title h-100' title={app.title} + titleSize='xs' href={NavigationService.getInstance().getUrlForApp( app.id, )} diff --git a/plugins/main/public/components/common/welcome/welcome.scss b/plugins/main/public/components/common/welcome/welcome.scss index 5754123f55..ab06214b0d 100644 --- a/plugins/main/public/components/common/welcome/welcome.scss +++ b/plugins/main/public/components/common/welcome/welcome.scss @@ -1,14 +1,3 @@ -.wz-welcome-page .euiCard .euiTitle, -.wz-module-body .euiCard .euiTitle { - font-size: 16px; - font-weight: 400; -} - -.wz-welcome-page .euiCard .euiText, -.wz-module-body .euiCard .euiText { - font-family: sans-serif; -} - .wz-module-header-agent:not(.wz-module-header-agent-main) { background: white; border-bottom: 1px solid #d3dae6; @@ -44,11 +33,6 @@ span.statWithLink:hover { text-decoration: underline; } -.wz-welcome-page .flex-redirect-app-links { - display: flex; - flex-grow: 1; -} - -.wz-welcome-page { - padding-bottom: 24px; +.wz-module-card-title .euiCard__content .euiTitle { + font-weight: 400; } From c5823e1682a6e9e5277c5db264cc54d941d5fc1e Mon Sep 17 00:00:00 2001 From: Nicolas Agustin Guevara Pihen <42900763+Tostti@users.noreply.github.com> Date: Thu, 3 Oct 2024 07:39:53 -0300 Subject: [PATCH 27/41] Fix permissions for group edit buttons (#7056) * Add permissions validation to buttons * Update changelog * Minor fixes to agents table * Fix typo * Prettier * Update snapshots --- CHANGELOG.md | 1 + .../__snapshots__/agent-status.test.tsx.snap | 9 ++++++--- .../public/components/agents/agent-status.tsx | 2 +- .../management/groups/actions-buttons-agents.js | 15 ++++++++++++--- .../management/groups/actions-buttons-files.js | 3 ++- .../management/groups/group-agents-table.js | 3 ++- .../management/groups/groups-overview.js | 6 +++++- .../management/groups/utils/columns-files.js | 3 ++- 8 files changed, 31 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fcb5dead49..92d0769bf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ All notable changes to the Wazuh app project will be documented in this file. - Fixed the `Open report` button of the toast and the `Download report` icon of the reporting table in Safari [#7019](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7019) - Fixed style when unnpinned an agent in endpoint summary section [#7015](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7015) - Fixed overflow style on a long value filter [#7021](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7021) +- Fixed buttons enabled for a readonly user in `Endpoint groups` section [#7056](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7056) ### Changed diff --git a/plugins/main/public/components/agents/__snapshots__/agent-status.test.tsx.snap b/plugins/main/public/components/agents/__snapshots__/agent-status.test.tsx.snap index e4b3c3708c..281620631e 100644 --- a/plugins/main/public/components/agents/__snapshots__/agent-status.test.tsx.snap +++ b/plugins/main/public/components/agents/__snapshots__/agent-status.test.tsx.snap @@ -126,7 +126,8 @@ exports[`AgentStatus component Renders status indicator with the its color and t xmlns="http://www.w3.org/2000/svg" > @@ -193,7 +194,8 @@ exports[`AgentStatus component Renders status indicator with the its color and t xmlns="http://www.w3.org/2000/svg" > @@ -260,7 +262,8 @@ exports[`AgentStatus component Renders status indicator with the its color and t xmlns="http://www.w3.org/2000/svg" > diff --git a/plugins/main/public/components/agents/agent-status.tsx b/plugins/main/public/components/agents/agent-status.tsx index 146646f637..a7967a0d92 100644 --- a/plugins/main/public/components/agents/agent-status.tsx +++ b/plugins/main/public/components/agents/agent-status.tsx @@ -26,7 +26,7 @@ export const AgentStatus = ({ status, children = null, style = {}, agent }) => { anchorClassName='wz-margin-left-10' aria-label='Description' size='m' - type='questionInCircle' + type='iInCircle' color='primary' content={statusCodeAgent?.STATUS_DESCRIPTION ?? 'Without information'} /> diff --git a/plugins/main/public/controllers/management/components/management/groups/actions-buttons-agents.js b/plugins/main/public/controllers/management/components/management/groups/actions-buttons-agents.js index 4f3d377178..4b74367ccc 100644 --- a/plugins/main/public/controllers/management/components/management/groups/actions-buttons-agents.js +++ b/plugins/main/public/controllers/management/components/management/groups/actions-buttons-agents.js @@ -11,7 +11,7 @@ */ import React, { Component, Fragment } from 'react'; // Eui components -import { EuiFlexItem, EuiButtonEmpty } from '@elastic/eui'; +import { EuiFlexItem } from '@elastic/eui'; import { connect } from 'react-redux'; @@ -20,6 +20,7 @@ import { updateShowAddAgents } from '../../../../../redux/actions/groupsActions' import GroupsHandler from './utils/groups-handler'; import { ExportConfiguration } from '../../../../../components/agents/export-configuration'; import { ReportingService } from '../../../../../react-services/reporting'; +import { WzButtonPermissions } from '../../../../../components/common/permissions/button'; class WzGroupsActionButtonsAgents extends Component { _isMounted = false; @@ -38,13 +39,21 @@ class WzGroupsActionButtonsAgents extends Component { render() { // Add new group button const manageAgentsButton = ( - this.showManageAgents()} > Manage agents - + ); // Export PDF button diff --git a/plugins/main/public/controllers/management/components/management/groups/actions-buttons-files.js b/plugins/main/public/controllers/management/components/management/groups/actions-buttons-files.js index 13fc7d36de..8601dfa2a6 100644 --- a/plugins/main/public/controllers/management/components/management/groups/actions-buttons-files.js +++ b/plugins/main/public/controllers/management/components/management/groups/actions-buttons-files.js @@ -59,9 +59,10 @@ class WzGroupsActionButtonsFiles extends Component { buttonType='empty' permissions={[ { - action: 'group:read', + action: 'group:update_config', resource: `group:id:${this.props.state.itemDetail.name}`, }, + { action: 'cluster:status', resource: '*:*:*' }, ]} iconSide='left' iconType='documentEdit' diff --git a/plugins/main/public/controllers/management/components/management/groups/group-agents-table.js b/plugins/main/public/controllers/management/components/management/groups/group-agents-table.js index fe99cf8751..c417c105a5 100644 --- a/plugins/main/public/controllers/management/components/management/groups/group-agents-table.js +++ b/plugins/main/public/controllers/management/components/management/groups/group-agents-table.js @@ -90,9 +90,10 @@ class WzGroupAgentsTable extends Component { align: 'left', searchable: true, sortable: true, - render: status => ( + render: (status, agent) => ( ), diff --git a/plugins/main/public/controllers/management/components/management/groups/groups-overview.js b/plugins/main/public/controllers/management/components/management/groups/groups-overview.js index 3e1bc7f471..0112173bfc 100644 --- a/plugins/main/public/controllers/management/components/management/groups/groups-overview.js +++ b/plugins/main/public/controllers/management/components/management/groups/groups-overview.js @@ -95,7 +95,11 @@ export class WzGroupsOverview extends Component { Date: Fri, 4 Oct 2024 10:46:08 +0200 Subject: [PATCH 28/41] Bump Wazuh 4.9.1 revision to 03 (#7067) Bump revision to 03 --- CHANGELOG.md | 2 +- plugins/main/opensearch_dashboards.json | 2 +- plugins/main/package.json | 2 +- plugins/wazuh-check-updates/opensearch_dashboards.json | 2 +- plugins/wazuh-check-updates/package.json | 2 +- plugins/wazuh-core/opensearch_dashboards.json | 2 +- plugins/wazuh-core/package.json | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 92d0769bf3..856c417d71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to the Wazuh app project will be documented in this file. -## Wazuh v4.9.1 - OpenSearch Dashboards 2.13.0 - Revision 02 +## Wazuh v4.9.1 - OpenSearch Dashboards 2.13.0 - Revision 03 ### Added diff --git a/plugins/main/opensearch_dashboards.json b/plugins/main/opensearch_dashboards.json index 384752eac2..63bfa6d3cc 100644 --- a/plugins/main/opensearch_dashboards.json +++ b/plugins/main/opensearch_dashboards.json @@ -1,6 +1,6 @@ { "id": "wazuh", - "version": "4.9.1-02", + "version": "4.9.1-03", "opensearchDashboardsVersion": "opensearchDashboards", "configPath": ["wazuh"], "requiredPlugins": [ diff --git a/plugins/main/package.json b/plugins/main/package.json index e7dcecce67..ba9e31a4d0 100644 --- a/plugins/main/package.json +++ b/plugins/main/package.json @@ -1,7 +1,7 @@ { "name": "wazuh", "version": "4.9.1", - "revision": "02", + "revision": "03", "pluginPlatform": { "version": "2.13.0" }, diff --git a/plugins/wazuh-check-updates/opensearch_dashboards.json b/plugins/wazuh-check-updates/opensearch_dashboards.json index cfd6e912d1..70c8cc9e56 100644 --- a/plugins/wazuh-check-updates/opensearch_dashboards.json +++ b/plugins/wazuh-check-updates/opensearch_dashboards.json @@ -1,6 +1,6 @@ { "id": "wazuhCheckUpdates", - "version": "4.9.1-02", + "version": "4.9.1-03", "opensearchDashboardsVersion": "opensearchDashboards", "server": true, "ui": true, diff --git a/plugins/wazuh-check-updates/package.json b/plugins/wazuh-check-updates/package.json index 550c9e5f2e..71d2419a06 100644 --- a/plugins/wazuh-check-updates/package.json +++ b/plugins/wazuh-check-updates/package.json @@ -1,7 +1,7 @@ { "name": "wazuh-check-updates", "version": "4.9.1", - "revision": "02", + "revision": "03", "pluginPlatform": { "version": "2.13.0" }, diff --git a/plugins/wazuh-core/opensearch_dashboards.json b/plugins/wazuh-core/opensearch_dashboards.json index a1f22c9a27..0fe0d96e0d 100644 --- a/plugins/wazuh-core/opensearch_dashboards.json +++ b/plugins/wazuh-core/opensearch_dashboards.json @@ -1,6 +1,6 @@ { "id": "wazuhCore", - "version": "4.9.1-02", + "version": "4.9.1-03", "opensearchDashboardsVersion": "opensearchDashboards", "server": true, "ui": true, diff --git a/plugins/wazuh-core/package.json b/plugins/wazuh-core/package.json index f43bc9b13f..2357b581d1 100644 --- a/plugins/wazuh-core/package.json +++ b/plugins/wazuh-core/package.json @@ -1,7 +1,7 @@ { "name": "wazuh-core", "version": "4.9.1", - "revision": "02", + "revision": "03", "pluginPlatform": { "version": "2.13.0" }, From e47c317e942600a711887ba301591823b2f638c0 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Fri, 4 Oct 2024 12:21:02 -0300 Subject: [PATCH 29/41] Refactor column visibility logic in useDataGrid hook --- .../common/data-grid/use-data-grid.tsx | 80 ++++++++----------- 1 file changed, 34 insertions(+), 46 deletions(-) diff --git a/plugins/main/public/components/common/data-grid/use-data-grid.tsx b/plugins/main/public/components/common/data-grid/use-data-grid.tsx index ebc58594da..b7104851f9 100644 --- a/plugins/main/public/components/common/data-grid/use-data-grid.tsx +++ b/plugins/main/public/components/common/data-grid/use-data-grid.tsx @@ -65,15 +65,15 @@ export const useDataGrid = (props: tDataGridProps): EuiDataGridProps => { indexPattern, DocViewInspectButton, results, - defaultColumns: columns, + defaultColumns, renderColumns, useDefaultPagination = false, pagination: paginationProps = {}, filters = [], setFilters = () => {}, } = props; - const [columnVisibility, setVisibility] = useState(() => - columns.map(({ id }) => id), + const [visibleColumns, setVisibleColumns] = useState(() => + defaultColumns.map(({ id }) => id), ); /** Rows */ const [rows, setRows] = useState([]); @@ -81,7 +81,7 @@ export const useDataGrid = (props: tDataGridProps): EuiDataGridProps => { /** Sorting **/ // get default sorting from default columns const getDefaultSorting = () => { - const defaultSort = columns.find( + const defaultSort = defaultColumns.find( column => column.isSortable || column.defaultSortDirection, ); return defaultSort @@ -110,6 +110,31 @@ export const useDataGrid = (props: tDataGridProps): EuiDataGridProps => { }, ); + const filterColumns = () => { + const allColumns = parseColumns( + indexPattern?.fields || [], + defaultColumns, + indexPattern, + rows, + pagination.pageSize, + filters, + setFilters, + ); + const columnNonMatch = allColumns.filter( + item => !visibleColumns.includes(item.name), + ); + + return [...defaultColumns, ...columnNonMatch]; + }; + + const [columns, setColumns] = useState([]); + + useEffect(() => { + if (indexPattern !== undefined) { + setColumns(filterColumns()); + } + }, [indexPattern]); + const onChangeItemsPerPage = useMemo( () => (pageSize: number) => setPagination(pagination => ({ @@ -149,7 +174,7 @@ export const useDataGrid = (props: tDataGridProps): EuiDataGridProps => { rowsParsed, ); // check if column have render method initialized - const column = columns.find(column => column.id === columnId); + const column = defaultColumns.find(column => column.id === columnId); if (column && column.render) { return column.render(fieldFormatted, rowsParsed[relativeRowIndex]); } @@ -198,53 +223,16 @@ export const useDataGrid = (props: tDataGridProps): EuiDataGridProps => { ]; }, [results]); - const filterColumns = () => { - const allColumns = parseColumns( - indexPattern?.fields || [], - columns, - indexPattern, - rows, - pagination.pageSize, - filters, - setFilters, - ); - const columnMatch = []; - const columnNonMatch = []; - - for (const item of allColumns) { - if (columnVisibility.includes(item.name)) { - columnMatch.push(item); - } else { - columnNonMatch.push(item); - } - } - - return [...columnMatch, ...columnNonMatch]; - }; - - const defaultColumnsPosition = (columnsVisibility, defaultColumns) => { - const defaults = defaultColumns - .map(item => item.id) - .filter(id => columnsVisibility.includes(id)); - - const nonDefaults = columnsVisibility.filter( - item => !defaultColumns.map(item => item.id).includes(item), - ); - - return [...defaults, ...nonDefaults]; - }; - return { 'aria-labelledby': props.ariaLabelledBy, - columns: filterColumns(), + columns, columnVisibility: { - visibleColumns: defaultColumnsPosition(columnVisibility, columns), - setVisibleColumns: setVisibility, + visibleColumns, + setVisibleColumns, }, renderCellValue: renderCellValue, leadingControlColumns: leadingControlColumns, - rowCount: - rowCount < MAX_ENTRIES_PER_QUERY ? rowCount : MAX_ENTRIES_PER_QUERY, + rowCount: Math.min(rowCount, MAX_ENTRIES_PER_QUERY), sorting: { columns: sortingColumns, onSort }, pagination: { ...pagination, From 84bac39dc42f729ff770a7a1e17f276a8716b6dc Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Fri, 4 Oct 2024 13:24:30 -0300 Subject: [PATCH 30/41] Fix column reordering feature in data grid functionality --- CHANGELOG.md | 3 +- .../common/data-grid/use-data-grid.tsx | 46 +++++++++++++++---- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8f3be31da..4f360b164a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,7 +29,8 @@ 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 security policy exception when it contained deprecated actions [#7042](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7042) -- Fix export formatted csv data with special characters from tables [#7048](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7048) +- 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) ### Removed diff --git a/plugins/main/public/components/common/data-grid/use-data-grid.tsx b/plugins/main/public/components/common/data-grid/use-data-grid.tsx index b7104851f9..9792b9f365 100644 --- a/plugins/main/public/components/common/data-grid/use-data-grid.tsx +++ b/plugins/main/public/components/common/data-grid/use-data-grid.tsx @@ -110,8 +110,33 @@ export const useDataGrid = (props: tDataGridProps): EuiDataGridProps => { }, ); - const filterColumns = () => { - const allColumns = parseColumns( + const reOrderFirstMatchedColumns = ( + columns: tDataGridColumn[], + visibleColumnsOrdered: string[], + ) => { + const firstMatchedColumns = []; + const nonMatchedColumns = []; + + for (let i = 0; i < columns.length; i++) { + const column = columns[i]; + if (visibleColumnsOrdered.includes(column.id)) { + firstMatchedColumns.push(column); + } else { + nonMatchedColumns.push(column); + } + } + + firstMatchedColumns.sort( + (a, b) => + visibleColumnsOrdered.indexOf(a.id) - + visibleColumnsOrdered.indexOf(b.id), + ); + + return [...firstMatchedColumns, ...nonMatchedColumns]; + }; + + const getColumns = () => { + return parseColumns( indexPattern?.fields || [], defaultColumns, indexPattern, @@ -120,18 +145,18 @@ export const useDataGrid = (props: tDataGridProps): EuiDataGridProps => { filters, setFilters, ); - const columnNonMatch = allColumns.filter( - item => !visibleColumns.includes(item.name), - ); - - return [...defaultColumns, ...columnNonMatch]; }; const [columns, setColumns] = useState([]); useEffect(() => { if (indexPattern !== undefined) { - setColumns(filterColumns()); + setColumns( + reOrderFirstMatchedColumns( + getColumns(), + defaultColumns.map(col => col.id), + ), + ); } }, [indexPattern]); @@ -228,7 +253,10 @@ export const useDataGrid = (props: tDataGridProps): EuiDataGridProps => { columns, columnVisibility: { visibleColumns, - setVisibleColumns, + setVisibleColumns: colsId => { + setVisibleColumns(colsId); + setColumns(reOrderFirstMatchedColumns(columns, colsId)); + }, }, renderCellValue: renderCellValue, leadingControlColumns: leadingControlColumns, From 4b5169fa9852cf81568c983f834129f5f9be2dc1 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Fri, 4 Oct 2024 17:58:08 -0300 Subject: [PATCH 31/41] Refactor sorting and ordering of columns logic --- .../common/data-grid/use-data-grid.tsx | 49 ++++++++++++------- 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/plugins/main/public/components/common/data-grid/use-data-grid.tsx b/plugins/main/public/components/common/data-grid/use-data-grid.tsx index 9792b9f365..a60b9cd9f7 100644 --- a/plugins/main/public/components/common/data-grid/use-data-grid.tsx +++ b/plugins/main/public/components/common/data-grid/use-data-grid.tsx @@ -110,32 +110,42 @@ export const useDataGrid = (props: tDataGridProps): EuiDataGridProps => { }, ); - const reOrderFirstMatchedColumns = ( + const sortFirstMatchedColumns = ( + firstMatchedColumns: tDataGridColumn[], + visibleColumnsOrdered: string[], + ) => { + firstMatchedColumns.sort( + (a, b) => + visibleColumnsOrdered.indexOf(a.id) - + visibleColumnsOrdered.indexOf(b.id), + ); + return firstMatchedColumns; + }; + + const orderFirstMatchedColumns = ( columns: tDataGridColumn[], visibleColumnsOrdered: string[], ) => { - const firstMatchedColumns = []; - const nonMatchedColumns = []; + const firstMatchedColumns: tDataGridColumn[] = []; + const nonMatchedColumns: tDataGridColumn[] = []; + const visibleColumnsSet = new Set(visibleColumnsOrdered); for (let i = 0; i < columns.length; i++) { const column = columns[i]; - if (visibleColumnsOrdered.includes(column.id)) { + if (visibleColumnsSet.has(column.id)) { firstMatchedColumns.push(column); } else { nonMatchedColumns.push(column); } } - firstMatchedColumns.sort( - (a, b) => - visibleColumnsOrdered.indexOf(a.id) - - visibleColumnsOrdered.indexOf(b.id), - ); - - return [...firstMatchedColumns, ...nonMatchedColumns]; + return [ + ...sortFirstMatchedColumns(firstMatchedColumns, visibleColumnsOrdered), + ...nonMatchedColumns, + ]; }; - const getColumns = () => { + const getColumns = useMemo(() => { return parseColumns( indexPattern?.fields || [], defaultColumns, @@ -145,15 +155,15 @@ export const useDataGrid = (props: tDataGridProps): EuiDataGridProps => { filters, setFilters, ); - }; + }, [indexPattern, rows, pagination.pageSize, filters, setFilters]); const [columns, setColumns] = useState([]); useEffect(() => { if (indexPattern !== undefined) { setColumns( - reOrderFirstMatchedColumns( - getColumns(), + orderFirstMatchedColumns( + getColumns, defaultColumns.map(col => col.id), ), ); @@ -248,15 +258,16 @@ export const useDataGrid = (props: tDataGridProps): EuiDataGridProps => { ]; }, [results]); + useEffect(() => { + setColumns(orderFirstMatchedColumns(columns, visibleColumns)); + }, [visibleColumns]); + return { 'aria-labelledby': props.ariaLabelledBy, columns, columnVisibility: { visibleColumns, - setVisibleColumns: colsId => { - setVisibleColumns(colsId); - setColumns(reOrderFirstMatchedColumns(columns, colsId)); - }, + setVisibleColumns, }, renderCellValue: renderCellValue, leadingControlColumns: leadingControlColumns, From c4d14790c97a25db168236a24fc789027b928b24 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Mon, 7 Oct 2024 09:51:55 -0300 Subject: [PATCH 32/41] Refactor setting columns in useDataGrid hook --- .../common/data-grid/use-data-grid.tsx | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/plugins/main/public/components/common/data-grid/use-data-grid.tsx b/plugins/main/public/components/common/data-grid/use-data-grid.tsx index a60b9cd9f7..babf9cb790 100644 --- a/plugins/main/public/components/common/data-grid/use-data-grid.tsx +++ b/plugins/main/public/components/common/data-grid/use-data-grid.tsx @@ -157,19 +157,6 @@ export const useDataGrid = (props: tDataGridProps): EuiDataGridProps => { ); }, [indexPattern, rows, pagination.pageSize, filters, setFilters]); - const [columns, setColumns] = useState([]); - - useEffect(() => { - if (indexPattern !== undefined) { - setColumns( - orderFirstMatchedColumns( - getColumns, - defaultColumns.map(col => col.id), - ), - ); - } - }, [indexPattern]); - const onChangeItemsPerPage = useMemo( () => (pageSize: number) => setPagination(pagination => ({ @@ -258,13 +245,9 @@ export const useDataGrid = (props: tDataGridProps): EuiDataGridProps => { ]; }, [results]); - useEffect(() => { - setColumns(orderFirstMatchedColumns(columns, visibleColumns)); - }, [visibleColumns]); - return { 'aria-labelledby': props.ariaLabelledBy, - columns, + columns: orderFirstMatchedColumns(getColumns, visibleColumns), columnVisibility: { visibleColumns, setVisibleColumns, From 586140c0692d0bde6b27c4c43425b039af0b444b Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Tue, 8 Oct 2024 08:11:57 -0300 Subject: [PATCH 33/41] Remove welcome stats styles from overview component --- .../main/public/controllers/overview/components/stats.scss | 5 ----- 1 file changed, 5 deletions(-) diff --git a/plugins/main/public/controllers/overview/components/stats.scss b/plugins/main/public/controllers/overview/components/stats.scss index 6d18137c71..8e8bfcf937 100644 --- a/plugins/main/public/controllers/overview/components/stats.scss +++ b/plugins/main/public/controllers/overview/components/stats.scss @@ -1,8 +1,3 @@ .vulnerabilites-summary-card { padding-top: 2vh; } - -.wz-welcome-stats { - padding-top: 24px; - padding-bottom: 8px; -} From f2d432ccc7ef57edb8f54cefc2e39aa5dae07be3 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Thu, 10 Oct 2024 10:04:58 -0300 Subject: [PATCH 34/41] Resolve prettier issues --- CHANGELOG.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f07ca6bba..72defdb4a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,6 @@ All notable changes to the Wazuh app project will be documented in this file. - ## Wazuh v4.10.0 - OpenSearch Dashboards 2.16.0 - Revision 01 ## Fixed @@ -39,7 +38,6 @@ All notable changes to the Wazuh app project will be documented in this file. ## Wazuh v4.9.1 - OpenSearch Dashboards 2.13.0 - Revision 03 - ### Added - Support for Wazuh 4.9.1 From f9784c891ebf3849d814213bc5f6476b9a181ef7 Mon Sep 17 00:00:00 2001 From: Federico Rodriguez Date: Thu, 10 Oct 2024 17:29:43 +0200 Subject: [PATCH 35/41] Support 4.10.0 alpha2 (#7096) --- CHANGELOG.md | 2 +- .../common/api-info/security-actions.json | 20 +++++++++---------- plugins/main/opensearch_dashboards.json | 2 +- plugins/main/package.json | 2 +- .../opensearch_dashboards.json | 2 +- plugins/wazuh-check-updates/package.json | 2 +- plugins/wazuh-core/opensearch_dashboards.json | 2 +- plugins/wazuh-core/package.json | 2 +- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 72defdb4a3..d1b27fe8de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to the Wazuh app project will be documented in this file. -## Wazuh v4.10.0 - OpenSearch Dashboards 2.16.0 - Revision 01 +## Wazuh v4.10.0 - OpenSearch Dashboards 2.16.0 - Revision 02 ## Fixed diff --git a/plugins/main/common/api-info/security-actions.json b/plugins/main/common/api-info/security-actions.json index d766d2a62d..3bc1e1b9c9 100644 --- a/plugins/main/common/api-info/security-actions.json +++ b/plugins/main/common/api-info/security-actions.json @@ -551,6 +551,16 @@ "DELETE /decoders/files/{filename}" ] }, + "event:ingest": { + "description": "Ingest events", + "resources": ["*:*"], + "example": { + "actions": ["event:ingest"], + "resources": ["*:*:*"], + "effect": "allow" + }, + "related_endpoints": ["POST /events"] + }, "syscollector:read": { "description": "Access agents syscollector information", "resources": ["agent:id", "agent:group"], @@ -694,15 +704,5 @@ "effect": "deny" }, "related_endpoints": ["GET /tasks/status"] - }, - "event:ingest": { - "description": "Ingest events", - "resources": ["*:*"], - "example": { - "actions": ["event:ingest"], - "resources": ["*:*:*"], - "effect": "allow" - }, - "related_endpoints": ["POST /events"] } } diff --git a/plugins/main/opensearch_dashboards.json b/plugins/main/opensearch_dashboards.json index fbc491a254..cd0d8939c2 100644 --- a/plugins/main/opensearch_dashboards.json +++ b/plugins/main/opensearch_dashboards.json @@ -1,6 +1,6 @@ { "id": "wazuh", - "version": "4.10.0-01", + "version": "4.10.0-02", "opensearchDashboardsVersion": "opensearchDashboards", "configPath": ["wazuh"], "requiredPlugins": [ diff --git a/plugins/main/package.json b/plugins/main/package.json index e8a7216885..128da3d9df 100644 --- a/plugins/main/package.json +++ b/plugins/main/package.json @@ -1,7 +1,7 @@ { "name": "wazuh", "version": "4.10.0", - "revision": "01", + "revision": "02", "pluginPlatform": { "version": "2.16.0" }, diff --git a/plugins/wazuh-check-updates/opensearch_dashboards.json b/plugins/wazuh-check-updates/opensearch_dashboards.json index 90f2a93909..c30aa25ad9 100644 --- a/plugins/wazuh-check-updates/opensearch_dashboards.json +++ b/plugins/wazuh-check-updates/opensearch_dashboards.json @@ -1,6 +1,6 @@ { "id": "wazuhCheckUpdates", - "version": "4.10.0-01", + "version": "4.10.0-02", "opensearchDashboardsVersion": "opensearchDashboards", "server": true, "ui": true, diff --git a/plugins/wazuh-check-updates/package.json b/plugins/wazuh-check-updates/package.json index 9725d153e4..022bd7e506 100644 --- a/plugins/wazuh-check-updates/package.json +++ b/plugins/wazuh-check-updates/package.json @@ -1,7 +1,7 @@ { "name": "wazuh-check-updates", "version": "4.10.0", - "revision": "01", + "revision": "02", "pluginPlatform": { "version": "2.16.0" }, diff --git a/plugins/wazuh-core/opensearch_dashboards.json b/plugins/wazuh-core/opensearch_dashboards.json index cd9d8e5fef..c7d6b0ae39 100644 --- a/plugins/wazuh-core/opensearch_dashboards.json +++ b/plugins/wazuh-core/opensearch_dashboards.json @@ -1,6 +1,6 @@ { "id": "wazuhCore", - "version": "4.10.0-01", + "version": "4.10.0-02", "opensearchDashboardsVersion": "opensearchDashboards", "server": true, "ui": true, diff --git a/plugins/wazuh-core/package.json b/plugins/wazuh-core/package.json index 897ff7150a..83ebc5f414 100644 --- a/plugins/wazuh-core/package.json +++ b/plugins/wazuh-core/package.json @@ -1,7 +1,7 @@ { "name": "wazuh-core", "version": "4.10.0", - "revision": "01", + "revision": "02", "pluginPlatform": { "version": "2.16.0" }, From c3559defa2c1d39075e478dd2f95b465359ba3b1 Mon Sep 17 00:00:00 2001 From: Federico Rodriguez Date: Fri, 11 Oct 2024 11:57:46 +0200 Subject: [PATCH 36/41] Remove event tables from dashboards (#7086) * Remove data grid from Threat hunting dashboard * Remove data grid from GitHub and Office365 drill down views * Add changelog --- CHANGELOG.md | 1 + .../github/panel/config/drilldown-action.tsx | 35 +--- .../github/panel/config/drilldown-actor.tsx | 53 +----- .../panel/config/drilldown-data-grid.tsx | 79 --------- .../panel/config/drilldown-organization.tsx | 54 +----- .../panel/config/drilldown-repository.tsx | 51 +----- .../panel/config/drilldown-ip-config.tsx | 44 +---- .../config/drilldown-operations-config.tsx | 43 +---- .../panel/config/drilldown-rules-config.tsx | 48 +----- .../panel/config/drilldown-user-config.tsx | 47 +---- .../threat-hunting/dashboard/dashboard.tsx | 162 +----------------- 11 files changed, 17 insertions(+), 600 deletions(-) delete mode 100644 plugins/main/public/components/overview/github/panel/config/drilldown-data-grid.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index 856c417d71..6e4db2d778 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,6 +40,7 @@ All notable changes to the Wazuh app project will be documented in this file. - Removed the PDF report footer year [#7023](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7023) - Removed the XML autoformat function group configuration due to performance [#6999](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6999) +- Removed data grid tables from Threat hunting dashboard, GitHub panel and Office365 panel [#7086](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7086) ## Wazuh v4.9.0 - OpenSearch Dashboards 2.13.0 - Revision 07 diff --git a/plugins/main/public/components/overview/github/panel/config/drilldown-action.tsx b/plugins/main/public/components/overview/github/panel/config/drilldown-action.tsx index 37fc626b55..e711a36fc6 100644 --- a/plugins/main/public/components/overview/github/panel/config/drilldown-action.tsx +++ b/plugins/main/public/components/overview/github/panel/config/drilldown-action.tsx @@ -12,7 +12,7 @@ import React from 'react'; import { ViewMode } from '../../../../../../../../src/plugins/embeddable/public'; -import { getPlugins, getCore } from '../../../../../kibana-services'; +import { getPlugins } from '../../../../../kibana-services'; import { DashboardPanelState } from '../../../../../../../../src/plugins/dashboard/public/application'; import { EmbeddableInput } from '../../../../../../../../src/plugins/embeddable/public'; import { @@ -23,7 +23,6 @@ import { getVisStateTopRepositories, } from './visualizations'; import { ModuleConfigProps } from './module-config'; -import DrillDownDataGrid from './drilldown-data-grid'; const DashboardByRenderer = getPlugins().dashboard.DashboardContainerByValueRenderer; @@ -148,38 +147,6 @@ export const DrilldownConfigAction = (drilldownProps: ModuleConfigProps) => { }, ], }, - { - columns: [ - { - width: 100, - component: () => { - const defaultTableColumns = [ - { - id: 'timestamp', - isSortable: true, - defaultSortDirection: 'desc', - }, - { id: 'rule.description' }, - { id: 'data.github.org', displayAsText: 'Organization' }, - { id: 'data.github.repo', displayAsText: 'Repository' }, - { id: 'data.github.actor', displayAsText: 'Actor' }, - { id: 'rule.level' }, - { id: 'rule.id' }, - ]; - - return ( - - ); - }, - }, - ], - }, ], }; }; diff --git a/plugins/main/public/components/overview/github/panel/config/drilldown-actor.tsx b/plugins/main/public/components/overview/github/panel/config/drilldown-actor.tsx index bcc3eb720c..6bcede34dc 100644 --- a/plugins/main/public/components/overview/github/panel/config/drilldown-actor.tsx +++ b/plugins/main/public/components/overview/github/panel/config/drilldown-actor.tsx @@ -10,18 +10,9 @@ * Find more information about this on the LICENSE file. */ -import React, { useState, useMemo, useEffect } from 'react'; -import { - EuiFlexItem, - EuiPanel, - EuiToolTip, - EuiButtonIcon, - EuiDataGridCellValueElementProps, - EuiDataGrid, - EuiLink, -} from '@elastic/eui'; +import React from 'react'; import { ViewMode } from '../../../../../../../../src/plugins/embeddable/public'; -import { getPlugins, getCore } from '../../../../../kibana-services'; +import { getPlugins } from '../../../../../kibana-services'; import { DashboardPanelState } from '../../../../../../../../src/plugins/dashboard/public/application'; import { EmbeddableInput } from '../../../../../../../../src/plugins/embeddable/public'; import { @@ -32,14 +23,6 @@ import { getVisStateTopRepositories, } from './visualizations'; import { ModuleConfigProps } from './module-config'; -import { - ErrorFactory, - HttpError, - ErrorHandler, -} from '../../../../../react-services/error-management'; -import DrillDownDataGrid from './drilldown-data-grid'; -import { rules } from '../../../../../utils/applications'; -import { RedirectAppLinks } from '../../../../../../../../src/plugins/opensearch_dashboards_react/public'; const DashboardByRenderer = getPlugins().dashboard.DashboardContainerByValueRenderer; @@ -164,38 +147,6 @@ export const DrilldownConfigActor = (drilldownProps: ModuleConfigProps) => { }, ], }, - { - columns: [ - { - width: 100, - component: () => { - const defaultTableColumns = [ - { - id: 'timestamp', - isSortable: true, - defaultSortDirection: 'desc', - }, - { id: 'rule.description' }, - { id: 'data.github.org', displayAsText: 'Organization' }, - { id: 'data.github.repo', displayAsText: 'Repository' }, - { id: 'data.github.action', displayAsText: 'Action' }, - { id: 'rule.level' }, - { id: 'rule.id' }, - ]; - - return ( - - ); - }, - }, - ], - }, ], }; }; diff --git a/plugins/main/public/components/overview/github/panel/config/drilldown-data-grid.tsx b/plugins/main/public/components/overview/github/panel/config/drilldown-data-grid.tsx deleted file mode 100644 index 0a5c8aa15d..0000000000 --- a/plugins/main/public/components/overview/github/panel/config/drilldown-data-grid.tsx +++ /dev/null @@ -1,79 +0,0 @@ -import React, { useState, useEffect } from 'react'; -import { EuiFlexItem } from '@elastic/eui'; -import { ModuleConfigProps } from './module-config'; -import { - ErrorFactory, - HttpError, - ErrorHandler, -} from '../../../../../react-services/error-management'; -import WazuhDataGrid from '../../../../common/wazuh-data-grid/wz-data-grid'; -import { tDataGridColumn } from '../../../../common/data-grid'; - -type tDrillDownDataGridProps = { - defaultTableColumns: tDataGridColumn[]; -} & ModuleConfigProps; - -export default function DrillDownDataGrid(props: tDrillDownDataGridProps) { - const [results, setResults] = useState([]); - const [pagination, setPagination] = useState({ - pageIndex: 0, - pageSize: 15, - pageSizeOptions: [15, 25, 50, 100], - }); - const [sorting, setSorting] = useState([]); - - const { - fetchData, - searchBarProps, - indexPattern, - fetchFilters, - defaultTableColumns, - } = props; - - useEffect(() => { - if (!indexPattern) { - return; - } - fetchData({ - query: searchBarProps.query, - filters: fetchFilters, - pagination, - sorting, - dateRange: searchBarProps.absoluteDateRange, - }) - .then(results => { - setResults(results); - }) - .catch(error => { - const searchError = ErrorFactory.create(HttpError, { - error, - message: 'Error fetching data', - }); - ErrorHandler.handleError(searchError); - }); - }, [ - JSON.stringify(fetchFilters), - JSON.stringify(searchBarProps.query), - JSON.stringify(pagination), - JSON.stringify(sorting), - JSON.stringify(searchBarProps.absoluteDateRange), - ]); - - return ( - - setPagination(pagination)} - onChangeSorting={sorting => { - setSorting(sorting); - }} - dateRange={searchBarProps?.absoluteDateRange} - /> - - ); -} diff --git a/plugins/main/public/components/overview/github/panel/config/drilldown-organization.tsx b/plugins/main/public/components/overview/github/panel/config/drilldown-organization.tsx index 37b5427ae2..6cdac16307 100644 --- a/plugins/main/public/components/overview/github/panel/config/drilldown-organization.tsx +++ b/plugins/main/public/components/overview/github/panel/config/drilldown-organization.tsx @@ -10,19 +10,9 @@ * Find more information about this on the LICENSE file. */ -import React, { useState, useMemo, useEffect } from 'react'; -import { - EuiFlexItem, - EuiPanel, - EuiToolTip, - EuiButtonIcon, - EuiDataGridCellValueElementProps, - EuiDataGrid, - EuiLink, -} from '@elastic/eui'; -import { SecurityAlerts } from '../../../../visualize/components'; +import React from 'react'; import { ViewMode } from '../../../../../../../../src/plugins/embeddable/public'; -import { getPlugins, getCore } from '../../../../../kibana-services'; +import { getPlugins } from '../../../../../kibana-services'; import { DashboardPanelState } from '../../../../../../../../src/plugins/dashboard/public/application'; import { EmbeddableInput } from '../../../../../../../../src/plugins/embeddable/public'; import { @@ -33,14 +23,6 @@ import { getVisStateTopActions, } from './visualizations'; import { ModuleConfigProps } from './module-config'; -import { - ErrorFactory, - HttpError, - ErrorHandler, -} from '../../../../../react-services/error-management'; -import DrillDownDataGrid from './drilldown-data-grid'; -import { rules } from '../../../../../utils/applications'; -import { RedirectAppLinks } from '../../../../../../../../src/plugins/opensearch_dashboards_react/public'; const DashboardByRenderer = getPlugins().dashboard.DashboardContainerByValueRenderer; @@ -167,38 +149,6 @@ export const DrilldownConfigOrganization = ( }, ], }, - { - columns: [ - { - width: 100, - component: () => { - const defaultTableColumns = [ - { - id: 'timestamp', - isSortable: true, - defaultSortDirection: 'desc', - }, - { id: 'rule.description' }, - { id: 'data.github.repo', displayAsText: 'Repository' }, - { id: 'data.github.actor', displayAsText: 'Actor' }, - { id: 'data.github.action', displayAsText: 'Action' }, - { id: 'rule.level' }, - { id: 'rule.id' }, - ]; - - return ( - - ); - }, - }, - ], - }, ], }; }; diff --git a/plugins/main/public/components/overview/github/panel/config/drilldown-repository.tsx b/plugins/main/public/components/overview/github/panel/config/drilldown-repository.tsx index 83639b34fb..c2a5e01a92 100644 --- a/plugins/main/public/components/overview/github/panel/config/drilldown-repository.tsx +++ b/plugins/main/public/components/overview/github/panel/config/drilldown-repository.tsx @@ -11,9 +11,8 @@ */ import React from 'react'; -import { EuiLink } from '@elastic/eui'; import { ViewMode } from '../../../../../../../../src/plugins/embeddable/public'; -import { getPlugins, getCore } from '../../../../../kibana-services'; +import { getPlugins } from '../../../../../kibana-services'; import { DashboardPanelState } from '../../../../../../../../src/plugins/dashboard/public/application'; import { EmbeddableInput } from '../../../../../../../../src/plugins/embeddable/public'; import { @@ -24,13 +23,6 @@ import { getVisStateTopOrganizations, } from './visualizations'; import { ModuleConfigProps } from './module-config'; -import { - ErrorFactory, - HttpError, - ErrorHandler, -} from '../../../../../react-services/error-management'; -import DrillDownDataGrid from './drilldown-data-grid'; -import { rules } from '../../../../../utils/applications'; const DashboardByRenderer = getPlugins().dashboard.DashboardContainerByValueRenderer; @@ -157,47 +149,6 @@ export const DrilldownConfigRepository = ( }, ], }, - { - columns: [ - { - width: 100, - component: () => { - const defaultTableColumns = [ - { - id: 'timestamp', - isSortable: true, - defaultSortDirection: 'desc', - }, - { id: 'rule.description' }, - { id: 'data.github.org', displayAsText: 'Organization' }, - { id: 'data.github.actor', displayAsText: 'Actor' }, - { id: 'data.github.action', displayAsText: 'Action' }, - { id: 'rule.level' }, - { - id: 'rule.id', - render: value => ( - - {value} - - ), - }, - ]; - - return ( - - ); - }, - }, - ], - }, ], }; }; diff --git a/plugins/main/public/components/overview/office/panel/config/drilldown-ip-config.tsx b/plugins/main/public/components/overview/office/panel/config/drilldown-ip-config.tsx index c0946559b7..837f6cd0b0 100644 --- a/plugins/main/public/components/overview/office/panel/config/drilldown-ip-config.tsx +++ b/plugins/main/public/components/overview/office/panel/config/drilldown-ip-config.tsx @@ -13,9 +13,8 @@ */ import React from 'react'; -import { EuiFlexItem, EuiLink } from '@elastic/eui'; import { ViewMode } from '../../../../../../../../src/plugins/embeddable/public'; -import { getPlugins, getCore } from '../../../../../kibana-services'; +import { getPlugins } from '../../../../../kibana-services'; import { DashboardPanelState } from '../../../../../../../../src/plugins/dashboard/public/application'; import { EmbeddableInput } from '../../../../../../../../src/plugins/embeddable/public'; import { @@ -24,9 +23,6 @@ import { getVisStateOfficeUserOperationLevel, getVisStateOfficeAlertsEvolutionByUser, } from './visualizations'; -import DrillDownDataGrid from '../../../github/panel/config/drilldown-data-grid'; -import { rules } from '../../../../../utils/applications'; -import { RedirectAppLinks } from '../../../../../../../../src/plugins/opensearch_dashboards_react/public'; const DashboardByRenderer = getPlugins().dashboard.DashboardContainerByValueRenderer; @@ -99,7 +95,7 @@ const getDashboardPanels = ( }; export const drilldownIPConfig = props => { - const { fetchData, fetchFilters, searchBarProps, indexPattern } = props; + const { fetchFilters, searchBarProps, indexPattern } = props; return { rows: [ @@ -108,33 +104,6 @@ export const drilldownIPConfig = props => { { width: 100, component: props => { - const defaultTableColumns = [ - { - id: 'timestamp', - isSortable: true, - defaultSortDirection: 'desc', - }, - { id: 'rule.description', displayAsText: 'Description' }, - { id: 'data.office365.UserId', displayAsText: 'User ID' }, - { - id: 'data.office365.Operation', - displayAsText: 'Operation', - }, - { id: 'rule.level', displayAsText: 'Level' }, - { - id: 'rule.id', - render: value => ( - - - {value} - - - ), - }, - ]; - return (
{ }} onInputUpdated={() => {}} /> - - -
); }, diff --git a/plugins/main/public/components/overview/office/panel/config/drilldown-operations-config.tsx b/plugins/main/public/components/overview/office/panel/config/drilldown-operations-config.tsx index 4a700d8b28..f12d4c42bb 100644 --- a/plugins/main/public/components/overview/office/panel/config/drilldown-operations-config.tsx +++ b/plugins/main/public/components/overview/office/panel/config/drilldown-operations-config.tsx @@ -12,9 +12,8 @@ */ import React from 'react'; -import { EuiFlexItem, EuiLink } from '@elastic/eui'; import { ViewMode } from '../../../../../../../../src/plugins/embeddable/public'; -import { getPlugins, getCore } from '../../../../../kibana-services'; +import { getPlugins } from '../../../../../kibana-services'; import { DashboardPanelState } from '../../../../../../../../src/plugins/dashboard/public/application'; import { EmbeddableInput } from '../../../../../../../../src/plugins/embeddable/public'; import { @@ -22,9 +21,6 @@ import { getVisStateOfficeCountryTagCloud, getVisStateOfficeAlertsEvolutionByUserID, } from './visualizations'; -import DrillDownDataGrid from '../../../github/panel/config/drilldown-data-grid'; -import { rules } from '../../../../../utils/applications'; -import { RedirectAppLinks } from '../../../../../../../../src/plugins/opensearch_dashboards_react/public'; const DashboardByRenderer = getPlugins().dashboard.DashboardContainerByValueRenderer; @@ -83,7 +79,7 @@ const getDashboardPanels = ( }; export const drilldownOperationsConfig = props => { - const { fetchData, fetchFilters, searchBarProps, indexPattern } = props; + const { fetchFilters, searchBarProps, indexPattern } = props; return { rows: [ @@ -92,32 +88,6 @@ export const drilldownOperationsConfig = props => { { width: 100, component: props => { - const defaultTableColumns = [ - { - id: 'timestamp', - isSortable: true, - defaultSortDirection: 'desc', - }, - { id: 'rule.description', displayAsText: 'Description' }, - { id: 'data.office365.UserId', displayAsText: 'User ID' }, - { - id: 'data.office365.ClientIP', - displayAsText: 'Client IP address', - }, - { id: 'rule.level', displayAsText: 'Level' }, - { - id: 'rule.id', - render: value => ( - - - {value} - - - ), - }, - ]; return (
{ }} onInputUpdated={() => {}} /> - - -
); }, diff --git a/plugins/main/public/components/overview/office/panel/config/drilldown-rules-config.tsx b/plugins/main/public/components/overview/office/panel/config/drilldown-rules-config.tsx index 04fba33db7..7990b1a64c 100644 --- a/plugins/main/public/components/overview/office/panel/config/drilldown-rules-config.tsx +++ b/plugins/main/public/components/overview/office/panel/config/drilldown-rules-config.tsx @@ -12,9 +12,8 @@ */ import React from 'react'; -import { EuiFlexItem, EuiLink } from '@elastic/eui'; import { ViewMode } from '../../../../../../../../src/plugins/embeddable/public'; -import { getPlugins, getCore } from '../../../../../kibana-services'; +import { getPlugins } from '../../../../../kibana-services'; import { DashboardPanelState } from '../../../../../../../../src/plugins/dashboard/public/application'; import { EmbeddableInput } from '../../../../../../../../src/plugins/embeddable/public'; import { @@ -23,9 +22,6 @@ import { getVisStateOfficeCountryTagCloud, getVisStateOfficeAlertsEvolutionByUserID, } from './visualizations'; -import DrillDownDataGrid from '../../../github/panel/config/drilldown-data-grid'; -import { rules } from '../../../../../utils/applications'; -import { RedirectAppLinks } from '../../../../../../../../src/plugins/opensearch_dashboards_react/public'; const DashboardByRenderer = getPlugins().dashboard.DashboardContainerByValueRenderer; @@ -98,7 +94,7 @@ const getDashboardPanels = ( }; export const drilldownRulesConfig = props => { - const { fetchData, fetchFilters, searchBarProps, indexPattern } = props; + const { fetchFilters, searchBarProps, indexPattern } = props; return { rows: [ @@ -107,37 +103,6 @@ export const drilldownRulesConfig = props => { { width: 100, component: props => { - const defaultTableColumns = [ - { - id: 'timestamp', - isSortable: true, - defaultSortDirection: 'desc', - }, - { id: 'rule.description', displayAsText: 'Description' }, - { id: 'data.office365.UserId', displayAsText: 'User ID' }, - { - id: 'data.office365.ClientIP', - displayAsText: 'Client IP address', - }, - { - id: 'data.office365.Operation', - displayAsText: 'Operation', - }, - { id: 'rule.level', displayAsText: 'Level' }, - { - id: 'rule.id', - render: value => ( - - - {value} - - - ), - }, - ]; - return (
{ }} onInputUpdated={() => {}} /> - - -
); }, diff --git a/plugins/main/public/components/overview/office/panel/config/drilldown-user-config.tsx b/plugins/main/public/components/overview/office/panel/config/drilldown-user-config.tsx index 6e7ec543c8..4e91891993 100644 --- a/plugins/main/public/components/overview/office/panel/config/drilldown-user-config.tsx +++ b/plugins/main/public/components/overview/office/panel/config/drilldown-user-config.tsx @@ -13,9 +13,8 @@ */ import React from 'react'; -import { EuiFlexItem, EuiLink } from '@elastic/eui'; import { ViewMode } from '../../../../../../../../src/plugins/embeddable/public'; -import { getPlugins, getCore } from '../../../../../kibana-services'; +import { getPlugins } from '../../../../../kibana-services'; import { DashboardPanelState } from '../../../../../../../../src/plugins/dashboard/public/application'; import { EmbeddableInput } from '../../../../../../../../src/plugins/embeddable/public'; import { @@ -24,9 +23,6 @@ import { getVisStateOfficeTopsEventsPie, getVisStateOfficeMetricStats, } from './visualizations'; -import DrillDownDataGrid from '../../../github/panel/config/drilldown-data-grid'; -import { rules } from '../../../../../utils/applications'; -import { RedirectAppLinks } from '../../../../../../../../src/plugins/opensearch_dashboards_react/public'; const DashboardByRenderer = getPlugins().dashboard.DashboardContainerByValueRenderer; @@ -99,7 +95,7 @@ const getDashboardPanels = ( }; export const drilldownUserConfig = props => { - const { fetchData, fetchFilters, searchBarProps, indexPattern } = props; + const { fetchFilters, searchBarProps, indexPattern } = props; return { rows: [ @@ -108,36 +104,6 @@ export const drilldownUserConfig = props => { { width: 100, component: props => { - const defaultTableColumns = [ - { - id: 'timestamp', - isSortable: true, - defaultSortDirection: 'desc', - }, - { id: 'rule.description', displayAsText: 'Description' }, - { - id: 'data.office365.ClientIP', - displayAsText: 'Client IP address', - }, - { - id: 'data.office365.Operation', - displayAsText: 'Operation', - }, - { id: 'rule.level', displayAsText: 'Level' }, - { - id: 'rule.id', - render: value => ( - - - {value} - - - ), - }, - ]; - return (
{ }} onInputUpdated={() => {}} /> - - -
); }, diff --git a/plugins/main/public/components/overview/threat-hunting/dashboard/dashboard.tsx b/plugins/main/public/components/overview/threat-hunting/dashboard/dashboard.tsx index ba380ff059..bad298ebfa 100644 --- a/plugins/main/public/components/overview/threat-hunting/dashboard/dashboard.tsx +++ b/plugins/main/public/components/overview/threat-hunting/dashboard/dashboard.tsx @@ -1,5 +1,5 @@ -import React, { useState, useEffect, useMemo } from 'react'; -import { getPlugins, getWazuhCorePlugin } from '../../../../kibana-services'; +import React, { useState, useEffect } from 'react'; +import { getPlugins } from '../../../../kibana-services'; import { ViewMode } from '../../../../../../../src/plugins/embeddable/public'; import { SearchResponse } from '../../../../../../../src/core/server'; import { IndexPattern } from '../../../../../../../src/plugins/data/common'; @@ -7,39 +7,14 @@ import { getDashboardPanels } from './dashboard_panels'; import { I18nProvider } from '@osd/i18n/react'; import useSearchBar from '../../../common/search-bar/use-search-bar'; import { getKPIsPanel } from './dashboard_panels_kpis'; -import { - EuiFlexGroup, - EuiFlexItem, - EuiButtonIcon, - EuiDataGrid, - EuiToolTip, - EuiDataGridCellValueElementProps, - EuiFlyout, - EuiFlyoutBody, - EuiFlyoutHeader, - EuiTitle, - EuiButtonEmpty, -} from '@elastic/eui'; import { ErrorFactory, ErrorHandler, HttpError, } from '../../../../react-services/error-management'; -import { - MAX_ENTRIES_PER_QUERY, - exportSearchToCSV, - getAllCustomRenders, -} from '../../../common/data-grid/data-grid-service'; -import { useDocViewer } from '../../../common/doc-viewer/use-doc-viewer'; -import { useDataGrid } from '../../../common/data-grid/use-data-grid'; -import DocViewer from '../../../common/doc-viewer/doc-viewer'; import { withErrorBoundary } from '../../../common/hocs/error-boundary/with-error-boundary'; import './threat_hunting_dashboard.scss'; import { SampleDataWarning } from '../../../visualize/components/sample-data-warning'; -import { - threatHuntingTableAgentColumns, - threatHuntingTableDefaultColumns, -} from '../events/threat-hunting-columns'; import { AlertsDataSourceRepository, ThreatHuntingDataSource, @@ -51,11 +26,7 @@ import { import { DiscoverNoResults } from '../../../common/no-results/no-results'; import { LoadingSearchbarProgress } from '../../../common/loading-searchbar-progress/loading-searchbar-progress'; import { useReportingCommunicateSearchContext } from '../../../common/hooks/use-reporting-communicate-search-context'; -import { wzDiscoverRenderColumns } from '../../../common/wazuh-discover/render-columns'; import { WzSearchBar } from '../../../common/search-bar'; -import DiscoverDataGridAdditionalControls from '../../../common/wazuh-discover/components/data-grid-additional-controls'; - -import DocDetailsHeader from '../../../common/wazuh-discover/components/doc-details-header'; const plugins = getPlugins(); @@ -75,7 +46,6 @@ const DashboardTH: React.FC = () => { DataSource: ThreatHuntingDataSource, repository: AlertsRepository, }); - const [results, setResults] = useState({} as SearchResponse); const { searchBarProps } = useSearchBar({ @@ -84,64 +54,10 @@ const DashboardTH: React.FC = () => { setFilters, }); const { query, absoluteDateRange } = searchBarProps; - - const [inspectedHit, setInspectedHit] = useState(undefined); - const [isExporting, setIsExporting] = useState(false); - - const sideNavDocked = getWazuhCorePlugin().hooks.useDockedSideNav(); - - const onClickInspectDoc = useMemo( - () => (index: number) => { - const rowClicked = results.hits.hits[index]; - setInspectedHit(rowClicked); - }, - [results], - ); - - const DocViewInspectButton = ({ - rowIndex, - }: EuiDataGridCellValueElementProps) => { - const inspectHintMsg = 'Inspect document details'; - return ( - - onClickInspectDoc(rowIndex)} - iconType='inspect' - aria-label={inspectHintMsg} - /> - - ); - }; - - const dataGridProps = useDataGrid({ - ariaLabelledBy: 'Threat Hunting Table', - defaultColumns: threatHuntingTableDefaultColumns, - renderColumns: wzDiscoverRenderColumns, - results, - indexPattern: dataSource?.indexPattern as IndexPattern, - DocViewInspectButton, - filters, - setFilters, - }); - - const { pagination, sorting, columnVisibility } = dataGridProps; - - const docViewerProps = useDocViewer({ - doc: inspectedHit, - indexPattern: dataSource?.indexPattern as IndexPattern, - }); - const pinnedAgent = PatternDataSourceFilterManager.getPinnedAgentFilter(dataSource?.id!) .length > 0; - useEffect(() => { - const currentColumns = !pinnedAgent - ? threatHuntingTableDefaultColumns - : threatHuntingTableAgentColumns; - columnVisibility.setVisibleColumns(currentColumns.map(({ id }) => id)); - }, [pinnedAgent]); - useReportingCommunicateSearchContext({ isSearching: isDataSourceLoading, totalResults: results?.hits?.total ?? 0, @@ -157,8 +73,6 @@ const DashboardTH: React.FC = () => { } fetchData({ query, - pagination, - sorting, dateRange: absoluteDateRange, }) .then(results => { @@ -174,37 +88,9 @@ const DashboardTH: React.FC = () => { }, [ JSON.stringify(fetchFilters), JSON.stringify(query), - JSON.stringify(pagination), - JSON.stringify(sorting), JSON.stringify(absoluteDateRange), ]); - const onClickExportResults = async () => { - const params = { - indexPattern: dataSource?.indexPattern, - filters: fetchFilters ?? [], - query, - fields: columnVisibility.visibleColumns, - pagination: { - pageIndex: 0, - pageSize: results.hits.total, - }, - sorting, - }; - try { - setIsExporting(true); - await exportSearchToCSV(params); - } catch (error) { - const searchError = ErrorFactory.create(HttpError, { - error, - message: 'Error downloading csv report', - }); - ErrorHandler.handleError(searchError); - } finally { - setIsExporting(false); - } - }; - return ( {isDataSourceLoading && !dataSource ? ( @@ -275,50 +161,6 @@ const DashboardTH: React.FC = () => { hidePanelTitles: false, }} /> -
- {!isDataSourceLoading ? ( - - - - ), - }} - /> - ) : null} -
- {inspectedHit && ( - setInspectedHit(undefined)} size='m'> - - - - - - - - - - - - )}
From 2c08f43c35099bcf37197b0e44bac1ddf8b1447b Mon Sep 17 00:00:00 2001 From: Guido Modarelli <38738725+guidomodarelli@users.noreply.github.com> Date: Fri, 11 Oct 2024 10:45:10 -0300 Subject: [PATCH 37/41] Remove virustotal feature and dashboards in favor of malware dashboard (#7038) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove Virustotal from Applications list * Remove Virustotal feature and dashboards * Remove Virustotal feature and dashboards as they are obsolete * Remove VirusTotal * Fix Prettier issues * Update CHANGELOG.md Co-authored-by: Antonio <34042064+Desvelao@users.noreply.github.com> * Add VirusTotal integration for threat detection capabilities * Restore plugins/main/public/controllers/management/components/management/configuration/configuration-settings.js * Restore plugins/main/public/controllers/management/components/management/configuration/integrations/integrations.js * Restore test/cypress * Restore scripts/wazuh-alerts-generator/cli.js * Restore plugins/main/public/components/add-modules-data/sample-data.tsx * Add Virustotal application to Applications list * fix: error registering unwanted application and move VirusTotal sample data to Malware detection category * fix: move VirusTotal sample data to Malware detection category in script * fix: enhance variable name --------- Co-authored-by: Federico Rodriguez Co-authored-by: Antonio <34042064+Desvelao@users.noreply.github.com> Co-authored-by: Antonio David Gutiérrez --- CHANGELOG.md | 1 + plugins/main/common/constants.ts | 4 +- plugins/main/common/wazuh-modules.ts | 6 - .../add-modules-data/sample-data.tsx | 21 +- .../data-source/pattern/alerts/index.ts | 1 - .../pattern/alerts/virustotal/index.ts | 1 - .../virustotal/virustotal-data-source.ts | 28 - .../common/modules/modules-defaults.tsx | 18 - .../main/public/components/overview/index.ts | 1 - .../virustotal/dashboard/dashboard.tsx | 168 --- .../virustotal/dashboard/dashboard_panels.ts | 989 ------------------ .../dashboard/dashboard_panels_kpis.ts | 304 ------ .../overview/virustotal/dashboard/index.tsx | 1 - .../dashboard/virustotal_dashboard.scss | 10 - .../virustotal/events/virustotal-columns.tsx | 40 - plugins/main/public/utils/applications.ts | 26 - .../agents/index.ts | 90 +- plugins/main/server/routes/wazuh-reporting.ts | 259 +++-- plugins/wazuh-core/common/constants.ts | 2 +- scripts/wazuh-alerts-generator/cli.js | 13 +- 20 files changed, 202 insertions(+), 1781 deletions(-) delete mode 100644 plugins/main/public/components/common/data-source/pattern/alerts/virustotal/index.ts delete mode 100644 plugins/main/public/components/common/data-source/pattern/alerts/virustotal/virustotal-data-source.ts delete mode 100644 plugins/main/public/components/overview/virustotal/dashboard/dashboard.tsx delete mode 100644 plugins/main/public/components/overview/virustotal/dashboard/dashboard_panels.ts delete mode 100644 plugins/main/public/components/overview/virustotal/dashboard/dashboard_panels_kpis.ts delete mode 100644 plugins/main/public/components/overview/virustotal/dashboard/index.tsx delete mode 100644 plugins/main/public/components/overview/virustotal/dashboard/virustotal_dashboard.scss delete mode 100644 plugins/main/public/components/overview/virustotal/events/virustotal-columns.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index d1b27fe8de..9d1480b279 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,7 @@ All notable changes to the Wazuh app project will be documented in this file. - 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) ## Wazuh v4.9.1 - OpenSearch Dashboards 2.13.0 - Revision 03 diff --git a/plugins/main/common/constants.ts b/plugins/main/common/constants.ts index 9442a5b76f..40ef55817b 100644 --- a/plugins/main/common/constants.ts +++ b/plugins/main/common/constants.ts @@ -81,11 +81,11 @@ export const WAZUH_SAMPLE_ALERTS_CATEGORIES_TYPE_ALERTS = { { audit: true }, { openscap: true }, { ciscat: true }, + { virustotal: true }, { yara: true }, ], [WAZUH_SAMPLE_ALERTS_CATEGORY_THREAT_DETECTION]: [ { vulnerabilities: true }, - { virustotal: true }, { osquery: true }, { docker: true }, { mitre: true }, @@ -243,8 +243,6 @@ export const DATA_SOURCE_FILTER_CONTROLLED_MITRE_ATTACK_RULE = 'mitre-attack-rule'; export const DATA_SOURCE_FILTER_CONTROLLED_MITRE_ATTACK_RULE_ID = 'hidden-mitre-attack-rule-id'; -export const DATA_SOURCE_FILTER_CONTROLLED_VIRUSTOTAL_RULE_GROUP = - 'virustotal-rule-group'; export const DATA_SOURCE_FILTER_CONTROLLED_GOOGLE_CLOUD_RULE_GROUP = 'gcp-rule-group'; export const DATA_SOURCE_FILTER_CONTROLLED_MALWARE_DETECTION_RULE_GROUP = diff --git a/plugins/main/common/wazuh-modules.ts b/plugins/main/common/wazuh-modules.ts index 82eb87c3bf..f251c03f0d 100644 --- a/plugins/main/common/wazuh-modules.ts +++ b/plugins/main/common/wazuh-modules.ts @@ -99,12 +99,6 @@ export const WAZUH_MODULES = { description: 'Security events related to your Google Cloud Platform services, collected directly via GCP API.', // TODO GCP }, - virustotal: { - title: 'VirusTotal', - appId: 'virustotal', - description: - 'Alerts resulting from VirusTotal analysis of suspicious files via an integration with their API.', - }, mitre: { title: 'MITRE ATT&CK', appId: 'mitre-attack', diff --git a/plugins/main/public/components/add-modules-data/sample-data.tsx b/plugins/main/public/components/add-modules-data/sample-data.tsx index ee7ab442ca..d3c33250af 100644 --- a/plugins/main/public/components/add-modules-data/sample-data.tsx +++ b/plugins/main/public/components/add-modules-data/sample-data.tsx @@ -37,7 +37,6 @@ import { malwareDetection, mitreAttack, office365, - virustotal, vulnerabilityDetection, } from '../../utils/applications'; @@ -47,14 +46,18 @@ const sampleSecurityInformationApplication = [ office365.title, googleCloud.title, github.title, -]; + 'authorization', + 'ssh', + 'web', +].join(', '); const sampleThreatDetectionApplication = [ vulnerabilityDetection.title, - virustotal.title, docker.title, mitreAttack.title, -]; +].join(', '); + +const sampleMalwareDetection = ['malware', 'VirusTotal', 'YARA'].join(', '); export default class WzSampleData extends Component { categories: { @@ -77,23 +80,19 @@ export default class WzSampleData extends Component { this.categories = [ { title: 'Sample security information', - description: `Sample data, visualizations and dashboards for security information (${sampleSecurityInformationApplication.join( - ', ', - )}, authorization, ssh, web).`, + description: `Sample data, visualizations and dashboards for security information (${sampleSecurityInformationApplication}).`, image: '', categorySampleAlertsIndex: 'security', }, { title: `Sample ${malwareDetection.title}`, - description: `Sample data, visualizations and dashboards for events of ${malwareDetection.title} (${malwareDetection.title}).`, + description: `Sample data, visualizations and dashboards for events of ${malwareDetection.title} (${sampleMalwareDetection}).`, image: '', categorySampleAlertsIndex: 'auditing-policy-monitoring', }, { title: 'Sample threat detection and response', - description: `Sample data, visualizations and dashboards for threat events of detection and response (${sampleThreatDetectionApplication.join( - ', ', - )}).`, + description: `Sample data, visualizations and dashboards for threat events of detection and response (${sampleThreatDetectionApplication}).`, image: '', categorySampleAlertsIndex: 'threat-detection', }, diff --git a/plugins/main/public/components/common/data-source/pattern/alerts/index.ts b/plugins/main/public/components/common/data-source/pattern/alerts/index.ts index effcfe3e7b..c093c8a4fe 100644 --- a/plugins/main/public/components/common/data-source/pattern/alerts/index.ts +++ b/plugins/main/public/components/common/data-source/pattern/alerts/index.ts @@ -8,7 +8,6 @@ export * from './docker'; export * from './malware-detection'; export * from './vulnerabilities'; export * from './hipaa'; -export * from './virustotal'; export * from './nist-800-53'; export * from './mitre-attack'; export * from './pci-dss'; diff --git a/plugins/main/public/components/common/data-source/pattern/alerts/virustotal/index.ts b/plugins/main/public/components/common/data-source/pattern/alerts/virustotal/index.ts deleted file mode 100644 index ffed0ecacd..0000000000 --- a/plugins/main/public/components/common/data-source/pattern/alerts/virustotal/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './virustotal-data-source'; diff --git a/plugins/main/public/components/common/data-source/pattern/alerts/virustotal/virustotal-data-source.ts b/plugins/main/public/components/common/data-source/pattern/alerts/virustotal/virustotal-data-source.ts deleted file mode 100644 index bd477527a1..0000000000 --- a/plugins/main/public/components/common/data-source/pattern/alerts/virustotal/virustotal-data-source.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { tFilter } from '../../../index'; -import { DATA_SOURCE_FILTER_CONTROLLED_VIRUSTOTAL_RULE_GROUP } from '../../../../../../../common/constants'; -import { AlertsDataSource } from '../alerts-data-source'; - -const VIRUSTOTAL_GROUP_KEY = 'rule.groups'; -const VIRUSTOTAL_GROUP_VALUE = 'virustotal'; - -export class VirusTotalDataSource extends AlertsDataSource { - constructor(id: string, title: string) { - super(id, title); - } - - getRuleGroupsFilter() { - return super.getRuleGroupsFilter( - VIRUSTOTAL_GROUP_KEY, - VIRUSTOTAL_GROUP_VALUE, - DATA_SOURCE_FILTER_CONTROLLED_VIRUSTOTAL_RULE_GROUP, - ); - } - - getFixedFilters(): tFilter[] { - return [ - ...super.getFixedFiltersClusterManager(), - ...this.getRuleGroupsFilter(), - ...super.getFixedFilters(), - ]; - } -} diff --git a/plugins/main/public/components/common/modules/modules-defaults.tsx b/plugins/main/public/components/common/modules/modules-defaults.tsx index 926216572a..0fc4b4b5bc 100644 --- a/plugins/main/public/components/common/modules/modules-defaults.tsx +++ b/plugins/main/public/components/common/modules/modules-defaults.tsx @@ -38,7 +38,6 @@ import { gdprColumns } from '../../overview/gdpr/events/gdpr-columns'; import { tscColumns } from '../../overview/tsc/events/tsc-columns'; import { githubColumns } from '../../overview/github/events/github-columns'; import { mitreAttackColumns } from '../../overview/mitre/events/mitre-attack-columns'; -import { virustotalColumns } from '../../overview/virustotal/events/virustotal-columns'; import { malwareDetectionColumns } from '../../overview/malware-detection/events/malware-detection-columns'; import { WAZUH_VULNERABILITIES_PATTERN } from '../../../../common/constants'; import { @@ -55,7 +54,6 @@ import { DashboardAWS, DashboardOffice365, DashboardThreatHunting, - DashboardVirustotal, DashboardGoogleCloud, DashboardVuls, InventoryVuls, @@ -64,7 +62,6 @@ import { DockerDataSource, AlertsVulnerabilitiesDataSource, AWSDataSource, - VirusTotalDataSource, FIMDataSource, GitHubDataSource, MalwareDetectionDataSource, @@ -311,21 +308,6 @@ export const ModulesDefaults = { ], availableFor: ['manager', 'agent'], }, - virustotal: { - tabs: [ - { - id: 'dashboard', - name: 'Dashboard', - buttons: [ButtonExploreAgent, ButtonModuleGenerateReport], - component: DashboardVirustotal, - }, - renderDiscoverTab({ - tableColumns: virustotalColumns, - DataSource: VirusTotalDataSource, - }), - ], - availableFor: ['manager', 'agent'], - }, docker: { init: 'dashboard', tabs: [ diff --git a/plugins/main/public/components/overview/index.ts b/plugins/main/public/components/overview/index.ts index 74f6becf54..03bc993a63 100644 --- a/plugins/main/public/components/overview/index.ts +++ b/plugins/main/public/components/overview/index.ts @@ -12,5 +12,4 @@ export { DashboardPCIDSS } from './pci/dashboards'; export { DashboardOffice365 } from './office/dashboard'; export { DashboardThreatHunting } from './threat-hunting/dashboard'; export { DashboardTSC } from './tsc/dashboards'; -export { DashboardVirustotal } from './virustotal/dashboard'; export { DashboardVuls, InventoryVuls } from './vulnerabilities'; diff --git a/plugins/main/public/components/overview/virustotal/dashboard/dashboard.tsx b/plugins/main/public/components/overview/virustotal/dashboard/dashboard.tsx deleted file mode 100644 index 29cf0cff74..0000000000 --- a/plugins/main/public/components/overview/virustotal/dashboard/dashboard.tsx +++ /dev/null @@ -1,168 +0,0 @@ -import React, { useState, useEffect } from 'react'; -import { getPlugins } from '../../../../kibana-services'; -import { ViewMode } from '../../../../../../../src/plugins/embeddable/public'; -import { SearchResponse } from '../../../../../../../src/core/server'; -import { IndexPattern } from '../../../../../../../src/plugins/data/common'; -import { getDashboardPanels } from './dashboard_panels'; -import { I18nProvider } from '@osd/i18n/react'; -import useSearchBar from '../../../common/search-bar/use-search-bar'; -import { getKPIsPanel } from './dashboard_panels_kpis'; -import { - ErrorFactory, - ErrorHandler, - HttpError, -} from '../../../../react-services/error-management'; -import { withErrorBoundary } from '../../../common/hocs/error-boundary/with-error-boundary'; -import { SampleDataWarning } from '../../../visualize/components/sample-data-warning'; -import { - AlertsDataSourceRepository, - PatternDataSource, - tParsedIndexPattern, - useDataSource, -} from '../../../common/data-source'; -import { LoadingSearchbarProgress } from '../../../common/loading-searchbar-progress/loading-searchbar-progress'; -import { DiscoverNoResults } from '../../../common/no-results/no-results'; -import { VirusTotalDataSource } from '../../../common/data-source/pattern/alerts/virustotal/virustotal-data-source'; -import './virustotal_dashboard.scss'; -import { useReportingCommunicateSearchContext } from '../../../common/hooks/use-reporting-communicate-search-context'; -import { WzSearchBar } from '../../../common/search-bar'; - -const plugins = getPlugins(); - -const DashboardByRenderer = plugins.dashboard.DashboardContainerByValueRenderer; - -const DashboardVT: React.FC = () => { - const AlertsRepository = new AlertsDataSourceRepository(); - const { - filters, - dataSource, - fetchFilters, - fixedFilters, - isLoading: isDataSourceLoading, - fetchData, - setFilters, - } = useDataSource({ - DataSource: VirusTotalDataSource, - repository: AlertsRepository, - }); - - const [results, setResults] = useState({} as SearchResponse); - - const { searchBarProps } = useSearchBar({ - indexPattern: dataSource?.indexPattern as IndexPattern, - filters, - setFilters, - }); - const { query, absoluteDateRange } = searchBarProps; - - useReportingCommunicateSearchContext({ - isSearching: isDataSourceLoading, - totalResults: results?.hits?.total ?? 0, - indexPattern: dataSource?.indexPattern, - filters: fetchFilters, - query: query, - time: absoluteDateRange, - }); - - useEffect(() => { - if (isDataSourceLoading) { - return; - } - fetchData({ - query, - dateRange: absoluteDateRange, - }) - .then(results => { - setResults(results); - }) - .catch(error => { - const searchError = ErrorFactory.create(HttpError, { - error, - message: 'Error fetching data', - }); - ErrorHandler.handleError(searchError); - }); - }, [ - isDataSourceLoading, - JSON.stringify(fetchFilters), - JSON.stringify(query), - JSON.stringify(absoluteDateRange), - ]); - - return ( - - {isDataSourceLoading && !dataSource ? ( - - ) : ( - <> - - {!isDataSourceLoading && dataSource && results?.hits?.total > 0 ? ( - - ) : null} - {dataSource && results?.hits?.total === 0 ? ( - - ) : null} -
0 - ? '' - : 'wz-no-display' - }`} - > - - -
- - )} -
- ); -}; - -export const DashboardVirustotal = withErrorBoundary(DashboardVT); diff --git a/plugins/main/public/components/overview/virustotal/dashboard/dashboard_panels.ts b/plugins/main/public/components/overview/virustotal/dashboard/dashboard_panels.ts deleted file mode 100644 index 1ec019da2b..0000000000 --- a/plugins/main/public/components/overview/virustotal/dashboard/dashboard_panels.ts +++ /dev/null @@ -1,989 +0,0 @@ -import { DashboardPanelState } from '../../../../../../../../src/plugins/dashboard/public/application'; -import { EmbeddableInput } from '../../../../../../../../src/plugins/embeddable/public'; - -/* WARNING: The panel id must be unique including general and agents visualizations. Otherwise, the visualizations will not refresh when we pin an agent, because they are cached by id */ - -/* Overview visualizations */ - -const getVisStateTop5UniqueMaliciousFilesPerAgent = ( - indexPatternId: string, -) => { - return { - id: 'Wazuh-App-Overview-Virustotal-Malicious-Per-Agent', - title: 'Top 5 agents with unique malicious files', - type: 'pie', - params: { - type: 'pie', - addTooltip: true, - addLegend: true, - legendPosition: 'right', - isDonut: true, - labels: { - show: false, - values: true, - last_level: true, - truncate: 100, - }, - }, - data: { - searchSource: { - query: { - language: 'kuery', - query: '', - }, - filter: [ - { - meta: { - index: 'wazuh-alerts', - negate: true, - disabled: false, - alias: null, - type: 'phrase', - key: 'data.virustotal.malicious', - value: '0', - params: { - query: '0', - type: 'phrase', - }, - }, - query: { - match: { - 'data.virustotal.malicious': { - query: '0', - type: 'phrase', - }, - }, - }, - $state: { - store: 'appState', - }, - }, - ], - index: indexPatternId, - }, - references: [ - { - name: 'kibanaSavedObjectMeta.searchSourceJSON.index', - type: 'index-pattern', - id: indexPatternId, - }, - ], - aggs: [ - { - id: '1', - enabled: true, - type: 'cardinality', - schema: 'metric', - params: { field: 'data.virustotal.source.md5' }, - }, - { - id: '2', - enabled: true, - type: 'terms', - schema: 'segment', - params: { - field: 'agent.name', - size: 5, - order: 'desc', - orderBy: '1', - }, - }, - ], - }, - }; -}; - -const getVisStateLastScannedFiles = (indexPatternId: string) => { - return { - id: 'Wazuh-App-Overview-Virustotal-Last-Files-Pie', - title: 'Last scanned files', - type: 'pie', - params: { - type: 'pie', - addTooltip: true, - addLegend: true, - legendPosition: 'right', - isDonut: true, - labels: { - show: false, - values: true, - last_level: true, - truncate: 100, - }, - }, - uiState: { - vis: { legendOpen: true }, - }, - data: { - searchSource: { - query: { - language: 'kuery', - query: '', - }, - filter: [], - index: indexPatternId, - }, - references: [ - { - name: 'kibanaSavedObjectMeta.searchSourceJSON.index', - type: 'index-pattern', - id: indexPatternId, - }, - ], - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: { customLabel: 'Files' }, - }, - { - id: '2', - enabled: true, - type: 'terms', - schema: 'segment', - params: { - field: 'data.virustotal.source.file', - size: 5, - order: 'desc', - orderBy: '1', - }, - }, - ], - }, - }; -}; - -const getVisStateAlertsEvolutionByAgents = (indexPatternId: string) => { - return { - id: 'Wazuh-App-Overview-Virustotal-Alerts-Evolution', - title: 'Alerts evolution by agents', - type: 'histogram', - params: { - type: 'histogram', - grid: { categoryLines: false }, - categoryAxes: [ - { - id: 'CategoryAxis-1', - type: 'category', - position: 'bottom', - show: true, - style: {}, - scale: { type: 'linear' }, - labels: { show: true, filter: true, truncate: 100 }, - title: {}, - }, - ], - valueAxes: [ - { - id: 'ValueAxis-1', - name: 'LeftAxis-1', - type: 'value', - position: 'left', - show: true, - style: {}, - scale: { type: 'linear', mode: 'normal' }, - labels: { show: true, rotate: 0, filter: false, truncate: 100 }, - title: { text: 'Count' }, - }, - ], - seriesParams: [ - { - show: true, - type: 'histogram', - mode: 'stacked', - data: { label: 'Count', id: '1' }, - valueAxis: 'ValueAxis-1', - drawLinesBetweenPoints: true, - lineWidth: 2, - showCircles: true, - }, - ], - addTooltip: true, - addLegend: true, - legendPosition: 'right', - times: [], - addTimeMarker: false, - labels: { show: false }, - thresholdLine: { - show: false, - value: 10, - width: 1, - style: 'full', - color: '#E7664C', - }, - dimensions: { - x: { - accessor: 0, - format: { id: 'date', params: { pattern: 'YYYY-MM-DD HH:mm' } }, - params: { - date: true, - interval: 'PT3H', - intervalOpenSearchValue: 3, - intervalOpenSearchUnit: 'h', - format: 'YYYY-MM-DD HH:mm', - bounds: { - min: '2020-04-17T12:11:35.943Z', - max: '2020-04-24T12:11:35.944Z', - }, - }, - label: 'timestamp per 3 hours', - aggType: 'date_histogram', - }, - y: [ - { - accessor: 2, - format: { id: 'number' }, - params: {}, - label: 'Count', - aggType: 'count', - }, - ], - series: [ - { - accessor: 1, - format: { - id: 'string', - params: { - parsedUrl: { - origin: 'http://localhost:5601', - pathname: '/app/kibana', - basePath: '', - }, - }, - }, - params: {}, - label: 'Top 5 unusual terms in agent.name', - aggType: 'significant_terms', - }, - ], - }, - radiusRatio: 50, - }, - uiState: { - vis: { - defaultColors: { - '0 - 7': 'rgb(247,251,255)', - '7 - 13': 'rgb(219,233,246)', - '13 - 20': 'rgb(187,214,235)', - '20 - 26': 'rgb(137,190,220)', - '26 - 33': 'rgb(83,158,205)', - '33 - 39': 'rgb(42,123,186)', - '39 - 45': 'rgb(11,85,159)', - }, - legendOpen: true, - }, - }, - data: { - searchSource: { - query: { - language: 'kuery', - query: '', - }, - filter: [ - { - meta: { - index: 'wazuh-alerts', - negate: false, - disabled: false, - alias: null, - type: 'exists', - key: 'data.virustotal.positives', - value: 'exists', - }, - exists: { - field: 'data.virustotal.positives', - }, - $state: { - store: 'appState', - }, - }, - { - meta: { - index: 'wazuh-alerts', - negate: true, - disabled: false, - alias: null, - type: 'phrase', - key: 'data.virustotal.positives', - value: '0', - params: { - query: 0, - type: 'phrase', - }, - }, - query: { - match: { - 'data.virustotal.positives': { - query: 0, - type: 'phrase', - }, - }, - }, - $state: { - store: 'appState', - }, - }, - ], - index: indexPatternId, - }, - references: [ - { - name: 'kibanaSavedObjectMeta.searchSourceJSON.index', - type: 'index-pattern', - id: indexPatternId, - }, - ], - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: {}, - }, - { - id: '3', - enabled: true, - type: 'terms', - schema: 'group', - params: { - field: 'agent.name', - orderBy: '1', - order: 'desc', - size: 5, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - }, - }, - { - id: '2', - enabled: true, - type: 'date_histogram', - schema: 'segment', - params: { - field: 'timestamp', - timeRange: { from: 'now-7d', to: 'now' }, - useNormalizedEsInterval: true, - scaleMetricValues: false, - interval: 'auto', - drop_partials: false, - min_doc_count: 1, - extended_bounds: {}, - }, - }, - ], - }, - }; -}; - -const getVisStateMaliciousFilesAlertsEvolution = (indexPatternId: string) => { - return { - id: 'Wazuh-App-Overview-Virustotal-Malicious-Evolution', - title: 'Malicious files alerts evolution', - type: 'histogram', - params: { - type: 'histogram', - grid: { categoryLines: false, style: { color: '#eee' } }, - categoryAxes: [ - { - id: 'CategoryAxis-1', - type: 'category', - position: 'bottom', - show: true, - style: {}, - scale: { type: 'linear' }, - labels: { show: true, filter: true, truncate: 100 }, - title: {}, - }, - ], - valueAxes: [ - { - id: 'ValueAxis-1', - name: 'LeftAxis-1', - type: 'value', - position: 'left', - show: true, - style: {}, - scale: { type: 'linear', mode: 'normal' }, - labels: { show: true, rotate: 0, filter: false, truncate: 100 }, - title: { text: 'Malicious' }, - }, - ], - seriesParams: [ - { - show: 'true', - type: 'histogram', - mode: 'stacked', - data: { label: 'Malicious', id: '1' }, - valueAxis: 'ValueAxis-1', - drawLinesBetweenPoints: true, - showCircles: true, - }, - ], - addTooltip: true, - addLegend: false, - legendPosition: 'right', - times: [], - addTimeMarker: false, - }, - data: { - searchSource: { - query: { - language: 'kuery', - query: '', - }, - filter: [ - { - meta: { - index: 'wazuh-alerts', - negate: false, - disabled: false, - alias: null, - type: 'exists', - key: 'data.virustotal.malicious', - value: 'exists', - }, - exists: { - field: 'data.virustotal.malicious', - }, - $state: { - store: 'appState', - }, - }, - { - meta: { - index: 'wazuh-alerts', - negate: true, - disabled: false, - alias: null, - type: 'phrase', - key: 'data.virustotal.malicious', - value: '0', - params: { - query: 0, - type: 'phrase', - }, - }, - query: { - match: { - 'data.virustotal.malicious': { - query: 0, - type: 'phrase', - }, - }, - }, - $state: { - store: 'appState', - }, - }, - ], - index: indexPatternId, - }, - references: [ - { - name: 'kibanaSavedObjectMeta.searchSourceJSON.index', - type: 'index-pattern', - id: indexPatternId, - }, - ], - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: { customLabel: 'Malicious' }, - }, - { - id: '2', - enabled: true, - type: 'date_histogram', - schema: 'segment', - params: { - field: 'timestamp', - interval: 'auto', - customInterval: '2h', - min_doc_count: 1, - extended_bounds: {}, - }, - }, - ], - }, - }; -}; - -const getVisStateLastFiles = (indexPatternId: string) => { - return { - id: 'Wazuh-App-Overview-Virustotal-Files-Table', - title: 'Last files', - type: 'table', - params: { - perPage: 10, - showPartialRows: false, - showMeticsAtAllLevels: false, - sort: { columnIndex: 2, direction: 'desc' }, - showTotal: false, - showToolbar: true, - totalFunc: 'sum', - }, - uiState: { - vis: { params: { sort: { columnIndex: 2, direction: 'desc' } } }, - }, - data: { - searchSource: { - query: { - language: 'kuery', - query: '', - }, - filter: [], - index: indexPatternId, - }, - references: [ - { - name: 'kibanaSavedObjectMeta.searchSourceJSON.index', - type: 'index-pattern', - id: indexPatternId, - }, - ], - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: { customLabel: 'Count' }, - }, - { - id: '4', - enabled: true, - type: 'terms', - schema: 'bucket', - params: { - field: 'data.virustotal.source.file', - size: 10, - order: 'desc', - orderBy: '1', - customLabel: 'File', - }, - }, - { - id: '2', - enabled: true, - type: 'terms', - schema: 'bucket', - params: { - field: 'data.virustotal.permalink', - size: 1, - order: 'desc', - orderBy: '1', - customLabel: 'Link', - }, - }, - ], - }, - }; -}; - -/* Agent visualizations */ - -const getVisStateAgentLastScannedFiles = (indexPatternId: string) => { - return { - id: 'Wazuh-App-Agents-Virustotal-Last-Files-Pie', - title: 'Last scanned files', - type: 'pie', - params: { - type: 'pie', - addTooltip: true, - addLegend: true, - legendPosition: 'right', - isDonut: true, - labels: { show: false, values: true, last_level: true, truncate: 100 }, - }, - uiState: { vis: { legendOpen: true } }, - data: { - searchSource: { - query: { - language: 'kuery', - query: '', - }, - filter: [], - index: indexPatternId, - }, - references: [ - { - name: 'kibanaSavedObjectMeta.searchSourceJSON.index', - type: 'index-pattern', - id: indexPatternId, - }, - ], - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: { customLabel: 'Files' }, - }, - { - id: '2', - enabled: true, - type: 'terms', - schema: 'segment', - params: { - field: 'data.virustotal.source.file', - size: 5, - order: 'desc', - orderBy: '1', - }, - }, - ], - }, - }; -}; - -const getVisStateAgentMaliciousFilesAlertsEvolution = ( - indexPatternId: string, -) => { - return { - id: 'Wazuh-App-Agents-Virustotal-Malicious-Evolution', - title: 'Malicious files alerts Evolution', - type: 'histogram', - params: { - type: 'histogram', - grid: { categoryLines: false, style: { color: '#eee' } }, - categoryAxes: [ - { - id: 'CategoryAxis-1', - type: 'category', - position: 'bottom', - show: true, - style: {}, - scale: { type: 'linear' }, - labels: { show: true, filter: true, truncate: 100 }, - title: {}, - }, - ], - valueAxes: [ - { - id: 'ValueAxis-1', - name: 'LeftAxis-1', - type: 'value', - position: 'left', - show: true, - style: {}, - scale: { type: 'linear', mode: 'normal' }, - labels: { show: true, rotate: 0, filter: false, truncate: 100 }, - title: { text: 'Malicious' }, - }, - ], - seriesParams: [ - { - show: 'true', - type: 'histogram', - mode: 'stacked', - data: { label: 'Malicious', id: '1' }, - valueAxis: 'ValueAxis-1', - drawLinesBetweenPoints: true, - showCircles: true, - }, - ], - addTooltip: true, - addLegend: false, - legendPosition: 'right', - times: [], - addTimeMarker: false, - }, - data: { - searchSource: { - query: { - language: 'kuery', - query: '', - }, - filter: [ - { - meta: { - index: 'wazuh-alerts', - negate: false, - disabled: false, - alias: null, - type: 'exists', - key: 'data.virustotal.positives', - value: 'exists', - }, - exists: { - field: 'data.virustotal.positives', - }, - $state: { - store: 'appState', - }, - }, - { - meta: { - index: 'wazuh-alerts', - negate: true, - disabled: false, - alias: null, - type: 'phrase', - key: 'data.virustotal.positives', - value: '0', - params: { - query: 0, - type: 'phrase', - }, - }, - query: { - match: { - 'data.virustotal.positives': { - query: 0, - type: 'phrase', - }, - }, - }, - $state: { - store: 'appState', - }, - }, - ], - index: indexPatternId, - }, - references: [ - { - name: 'kibanaSavedObjectMeta.searchSourceJSON.index', - type: 'index-pattern', - id: indexPatternId, - }, - ], - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: { customLabel: 'Malicious' }, - }, - { - id: '2', - enabled: true, - type: 'date_histogram', - schema: 'segment', - params: { - field: 'timestamp', - interval: 'auto', - customInterval: '2h', - min_doc_count: 1, - extended_bounds: {}, - }, - }, - ], - }, - }; -}; - -const getVisStateAgentLastFiles = (indexPatternId: string) => { - return { - id: 'Wazuh-App-Agents-Virustotal-Files-Table', - title: 'Last files', - type: 'table', - params: { - perPage: 10, - showPartialRows: false, - showMeticsAtAllLevels: false, - sort: { columnIndex: 2, direction: 'desc' }, - showTotal: false, - showToolbar: true, - totalFunc: 'sum', - }, - uiState: { - vis: { params: { sort: { columnIndex: 2, direction: 'desc' } } }, - }, - data: { - searchSource: { - query: { - language: 'kuery', - query: '', - }, - filter: [], - index: indexPatternId, - }, - references: [ - { - name: 'kibanaSavedObjectMeta.searchSourceJSON.index', - type: 'index-pattern', - id: indexPatternId, - }, - ], - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: { customLabel: 'Count' }, - }, - { - id: '4', - enabled: true, - type: 'terms', - schema: 'bucket', - params: { - field: 'data.virustotal.source.file', - size: 10, - order: 'desc', - orderBy: '1', - customLabel: 'File', - }, - }, - { - id: '2', - enabled: true, - type: 'terms', - schema: 'bucket', - params: { - field: 'data.virustotal.permalink', - size: 1, - order: 'desc', - orderBy: '1', - missingBucket: true, - missingBucketLabel: '-', - customLabel: 'Link', - }, - }, - ], - }, - }; -}; - -/* Definitiion of panels */ - -export const getDashboardPanels = ( - indexPatternId: string, - pinnedAgent?: boolean, -): { - [panelId: string]: DashboardPanelState< - EmbeddableInput & { [k: string]: unknown } - >; -} => { - const pinnedAgentPanels = { - '6': { - gridData: { - w: 12, - h: 9, - x: 0, - y: 0, - i: '6', - }, - type: 'visualization', - explicitInput: { - id: '6', - savedVis: getVisStateAgentLastScannedFiles(indexPatternId), - }, - }, - '7': { - gridData: { - w: 36, - h: 9, - x: 12, - y: 0, - i: '7', - }, - type: 'visualization', - explicitInput: { - id: '7', - savedVis: getVisStateAgentMaliciousFilesAlertsEvolution(indexPatternId), - }, - }, - '8': { - gridData: { - w: 48, - h: 20, - x: 0, - y: 9, - i: '8', - }, - type: 'visualization', - explicitInput: { - id: '8', - savedVis: getVisStateAgentLastFiles(indexPatternId), - }, - }, - }; - - const panels = { - '1': { - gridData: { - w: 24, - h: 13, - x: 0, - y: 0, - i: '1', - }, - type: 'visualization', - explicitInput: { - id: '1', - savedVis: getVisStateTop5UniqueMaliciousFilesPerAgent(indexPatternId), - }, - }, - '2': { - gridData: { - w: 24, - h: 13, - x: 28, - y: 0, - i: '2', - }, - type: 'visualization', - explicitInput: { - id: '2', - savedVis: getVisStateLastScannedFiles(indexPatternId), - }, - }, - '3': { - gridData: { - w: 48, - h: 20, - x: 0, - y: 13, - i: '3', - }, - type: 'visualization', - explicitInput: { - id: '3', - savedVis: getVisStateAlertsEvolutionByAgents(indexPatternId), - }, - }, - '4': { - gridData: { - w: 48, - h: 9, - x: 0, - y: 23, - i: '4', - }, - type: 'visualization', - explicitInput: { - id: '4', - savedVis: getVisStateMaliciousFilesAlertsEvolution(indexPatternId), - }, - }, - '5': { - gridData: { - w: 48, - h: 20, - x: 0, - y: 32, - i: '5', - }, - type: 'visualization', - explicitInput: { - id: '5', - savedVis: getVisStateLastFiles(indexPatternId), - }, - }, - }; - - return pinnedAgent ? pinnedAgentPanels : panels; -}; diff --git a/plugins/main/public/components/overview/virustotal/dashboard/dashboard_panels_kpis.ts b/plugins/main/public/components/overview/virustotal/dashboard/dashboard_panels_kpis.ts deleted file mode 100644 index 3a738bcc66..0000000000 --- a/plugins/main/public/components/overview/virustotal/dashboard/dashboard_panels_kpis.ts +++ /dev/null @@ -1,304 +0,0 @@ -import { DashboardPanelState } from '../../../../../../../../src/plugins/dashboard/public/application'; -import { EmbeddableInput } from '../../../../../../../../src/plugins/embeddable/public'; - -const getVisStateTotalMalicious = (indexPatternId: string) => { - return { - id: 'Wazuh-App-Overview-Virustotal-Total-Malicious', - title: 'Total Malicious', - type: 'metric', - params: { - addTooltip: true, - addLegend: false, - type: 'metric', - metric: { - percentageMode: false, - useRanges: false, - colorSchema: 'Reds', - metricColorMode: 'Labels', - colorsRange: [ - { - from: 0, - to: 0, - }, - { - from: 0, - to: 0, - }, - ], - labels: { - show: true, - }, - invertColors: false, - style: { - bgFill: '#000', - bgColor: false, - labelColor: false, - subText: '', - fontSize: 40, - }, - }, - }, - data: { - searchSource: { - query: { - language: 'kuery', - query: '', - }, - filter: [], - index: indexPatternId, - }, - references: [ - { - name: 'kibanaSavedObjectMeta.searchSourceJSON.index', - type: 'index-pattern', - id: indexPatternId, - }, - ], - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: { customLabel: ' ' }, - }, - { - id: '2', - enabled: true, - type: 'filters', - params: { - filters: [ - { - input: { - query: 'data.virustotal.malicious: 1', - language: 'kuery', - }, - label: '- Total malicious', - }, - ], - }, - schema: 'group', - }, - ], - }, - }; -}; - -const getVisStateTotalPositives = (indexPatternId: string) => { - return { - id: 'Wazuh-App-Overview-Virustotal-Total-Positives', - title: 'Total Positives', - type: 'metric', - params: { - addTooltip: true, - addLegend: false, - type: 'metric', - metric: { - percentageMode: false, - useRanges: false, - colorSchema: 'Greens', - metricColorMode: 'Labels', - colorsRange: [ - { - from: 0, - to: 0, - }, - { - from: 0, - to: 0, - }, - ], - labels: { - show: true, - }, - invertColors: false, - style: { - bgFill: '#000', - bgColor: false, - labelColor: false, - subText: '', - fontSize: 40, - }, - }, - }, - data: { - searchSource: { - query: { - language: 'kuery', - query: '', - }, - filter: [], - index: indexPatternId, - }, - references: [ - { - name: 'kibanaSavedObjectMeta.searchSourceJSON.index', - type: 'index-pattern', - id: indexPatternId, - }, - ], - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: { customLabel: ' ' }, - }, - { - id: '2', - enabled: true, - type: 'filters', - params: { - filters: [ - { - input: { - query: 'data.virustotal.positives: *', - language: 'kuery', - }, - label: '- Total Positives', - }, - ], - }, - schema: 'group', - }, - ], - }, - }; -}; - -const getVisStateTotal = (indexPatternId: string) => { - return { - id: 'Wazuh-App-Overview-Virustotal-Total', - title: 'Total', - type: 'metric', - params: { - addTooltip: true, - addLegend: false, - type: 'metric', - metric: { - percentageMode: false, - useRanges: false, - colorSchema: 'Greens', - metricColorMode: 'Labels', - colorsRange: [ - { - from: 0, - to: 0, - }, - { - from: 0, - to: 0, - }, - ], - labels: { - show: true, - }, - invertColors: false, - style: { - bgFill: '#000', - bgColor: false, - labelColor: false, - subText: '', - fontSize: 40, - }, - }, - }, - data: { - searchSource: { - query: { - language: 'kuery', - query: '', - }, - filter: [], - index: indexPatternId, - }, - references: [ - { - name: 'kibanaSavedObjectMeta.searchSourceJSON.index', - type: 'index-pattern', - id: indexPatternId, - }, - ], - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: { customLabel: ' ' }, - }, - { - id: '2', - enabled: true, - type: 'filters', - params: { - filters: [ - { - input: { - query: 'data.virustotal:*', - language: 'kuery', - }, - label: '- Total', - }, - ], - }, - schema: 'group', - }, - ], - }, - }; -}; - -export const getKPIsPanel = ( - indexPatternId: string, -): { - [panelId: string]: DashboardPanelState< - EmbeddableInput & { [k: string]: unknown } - >; -} => { - return { - '1': { - gridData: { - w: 12, - h: 6, - x: 6, - y: 0, - i: '1', - }, - type: 'visualization', - explicitInput: { - id: '1', - savedVis: getVisStateTotalMalicious(indexPatternId), - }, - }, - '2': { - gridData: { - w: 12, - h: 6, - x: 18, - y: 0, - i: '2', - }, - type: 'visualization', - explicitInput: { - id: '2', - savedVis: getVisStateTotalPositives(indexPatternId), - }, - }, - '3': { - gridData: { - w: 12, - h: 6, - x: 30, - y: 0, - i: '3', - }, - type: 'visualization', - explicitInput: { - id: '3', - savedVis: getVisStateTotal(indexPatternId), - }, - }, - }; -}; diff --git a/plugins/main/public/components/overview/virustotal/dashboard/index.tsx b/plugins/main/public/components/overview/virustotal/dashboard/index.tsx deleted file mode 100644 index b58b6c9229..0000000000 --- a/plugins/main/public/components/overview/virustotal/dashboard/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export * from './dashboard'; diff --git a/plugins/main/public/components/overview/virustotal/dashboard/virustotal_dashboard.scss b/plugins/main/public/components/overview/virustotal/dashboard/virustotal_dashboard.scss deleted file mode 100644 index 6e8f3eab43..0000000000 --- a/plugins/main/public/components/overview/virustotal/dashboard/virustotal_dashboard.scss +++ /dev/null @@ -1,10 +0,0 @@ -.virustotal-dashboard-responsive { - @media (max-width: 767px) { - .react-grid-layout { - height: auto !important; - } - .dshLayout-isMaximizedPanel { - height: calc(100vh - 44px) !important; - } - } -} diff --git a/plugins/main/public/components/overview/virustotal/events/virustotal-columns.tsx b/plugins/main/public/components/overview/virustotal/events/virustotal-columns.tsx deleted file mode 100644 index 790561a9e4..0000000000 --- a/plugins/main/public/components/overview/virustotal/events/virustotal-columns.tsx +++ /dev/null @@ -1,40 +0,0 @@ -import { tDataGridColumn } from '../../../common/data-grid'; -import React from 'react'; -import { EuiLink } from '@elastic/eui'; - -export const virustotalColumns: tDataGridColumn[] = [ - { - id: 'timestamp', - isSortable: true, - defaultSortDirection: 'desc', - }, - { - id: 'agent.name', - }, - { - id: 'data.virustotal.source.file', - }, - { - id: 'data.virustotal.permalink', - render: value => { - if (!value) { - return '-'; - } else { - return ( - - {value} - - ); - } - }, - }, - { - id: 'data.virustotal.malicious', - }, - { - id: 'data.virustotal.positives', - }, - { - id: 'data.virustotal.total', - }, -]; diff --git a/plugins/main/public/utils/applications.ts b/plugins/main/public/utils/applications.ts index 4db8e2d751..76ecbc060c 100644 --- a/plugins/main/public/utils/applications.ts +++ b/plugins/main/public/utils/applications.ts @@ -232,31 +232,6 @@ export const mitreAttack = { }`, }; -export const virustotal = { - category: 'wz-category-threat-intelligence', - id: 'virustotal', - title: i18n.translate('wz-app-virustotal-title', { - defaultMessage: 'VirusTotal', - }), - breadcrumbLabel: i18n.translate('wz-app-virustotal-breadcrumbLabel', { - defaultMessage: 'VirusTotal', - }), - description: i18n.translate('wz-app-virustotal-description', { - defaultMessage: - 'Alerts resulting from VirusTotal analysis of suspicious files via an integration with their API.', - }), - euiIconType: 'monitoringApp', - order: 303, - showInOverviewApp: true, - showInAgentMenu: true, - redirectTo: () => - `/overview/?tab=virustotal&tabView=dashboard${ - store.getState()?.appStateReducers?.currentAgentData?.id - ? `&agentId=${store.getState()?.appStateReducers?.currentAgentData?.id}` - : '' - }`, -}; - const pciDss = { category: 'wz-category-security-operations', id: 'pci-dss', @@ -841,7 +816,6 @@ export const Applications = [ threatHunting, vulnerabilityDetection, mitreAttack, - virustotal, pciDss, hipaa, gdpr, diff --git a/plugins/main/server/lib/reporting/summary-tables-definitions/agents/index.ts b/plugins/main/server/lib/reporting/summary-tables-definitions/agents/index.ts index 46dee71df3..c84014feea 100644 --- a/plugins/main/server/lib/reporting/summary-tables-definitions/agents/index.ts +++ b/plugins/main/server/lib/reporting/summary-tables-definitions/agents/index.ts @@ -6,15 +6,13 @@ const generalAlertsSummary = { AggregationFields['rule.id'], AggregationFields['rule.description'], AggregationFields['rule.level'], - ] -} + ], +}; const generalGroupsSummary = { title: 'Groups summary', - aggs: [ - AggregationFields['rule.groups'], - ] -} + aggs: [AggregationFields['rule.groups']], +}; const awsAlertsSummary = { title: 'Alerts summary', @@ -22,33 +20,24 @@ const awsAlertsSummary = { AggregationFields['rule.id'], AggregationFields['rule.description'], AggregationFields['rule.level'], - ] -} + ], +}; const fimAlertsSummary = { title: 'Alerts summary', aggs: [ AggregationFields['syscheck.path'], AggregationFields['rule.description'], - ] -} + ], +}; const gcpAlertsSummary = { title: 'Alerts summary', aggs: [ AggregationFields['rule.id'], AggregationFields['rule.description'], AggregationFields['rule.level'], - ] -} - -const virustotalAlertsSummary = { - title: 'Alerts summary', - aggs: [ - AggregationFields['rule.id'], - AggregationFields['rule.description'], - AggregationFields['rule.level'], - ] -} + ], +}; const osqueryAlertsSummary = { title: 'Alerts summary', @@ -58,8 +47,8 @@ const osqueryAlertsSummary = { AggregationFields['agent.name'], AggregationFields['data.osquery.pack'], AggregationFields['data.osquery.calendarTime'], - ] -} + ], +}; const mitreAlertsSummary = { title: 'Alerts summary', @@ -67,8 +56,8 @@ const mitreAlertsSummary = { AggregationFields['rule.id'], AggregationFields['rule.description'], AggregationFields['rule.level'], - ] -} + ], +}; const ciscatAlertsSummary = { title: 'Alerts summary', @@ -76,16 +65,16 @@ const ciscatAlertsSummary = { AggregationFields['data.cis.rule_title'], AggregationFields['data.cis.group'], AggregationFields['data.cis.result'], - ] -} + ], +}; const pmAlertsSummary = { title: 'Alerts summary', aggs: [ AggregationFields['rule.description'], AggregationFields['data.title'], - ] -} + ], +}; const tscAlertsSummary = { title: 'Alerts summary', @@ -93,8 +82,8 @@ const tscAlertsSummary = { AggregationFields['agent.name'], AggregationFields['rule.tsc'], AggregationFields['rule.description'], - ] -} + ], +}; const githubAlertsSummary = { title: 'Alerts summary', @@ -102,18 +91,14 @@ const githubAlertsSummary = { AggregationFields['agent.name'], AggregationFields['data.github.org'], AggregationFields['rule.description'], - ] -} + ], +}; // 'Wazuh-App-Agents-GDPR-Last-alerts' const gdprLastAlerts = { title: 'Last alerts', - aggs: [ - AggregationFields['rule.gdpr'], - AggregationFields['rule.description'], - ] - -} + aggs: [AggregationFields['rule.gdpr'], AggregationFields['rule.description']], +}; // 'Wazuh-App-Agents-PCI-Last-alerts' const pciLastAlerts = { @@ -121,8 +106,8 @@ const pciLastAlerts = { aggs: [ AggregationFields['rule.pci_dss'], AggregationFields['rule.description'], - ] -} + ], +}; // 'Wazuh-App-Agents-NIST-Last-alerts' const nistLastAlerts = { @@ -131,8 +116,8 @@ const nistLastAlerts = { AggregationFields['rule.nist_800_53'], AggregationFields['rule.level'], AggregationFields['rule.description'], - ] -} + ], +}; // 'Wazuh-App-Agents-HIPAA-Last-alerts' const hipaaLastAlerts = { @@ -141,8 +126,8 @@ const hipaaLastAlerts = { AggregationFields['rule.hipaa'], AggregationFields['rule.level'], AggregationFields['rule.description'], - ] -} + ], +}; // 'Wazuh-App-Agents-OSCAP-Last-alerts' const oscapLastAlerts = { @@ -150,8 +135,8 @@ const oscapLastAlerts = { aggs: [ AggregationFields['data.oscap.check.title'], AggregationFields['data.oscap.scan.profile.title'], - ] -} + ], +}; // 'Wazuh-App-Agents-Audit-Last-alerts' const auditLastAlerts = { @@ -160,8 +145,8 @@ const auditLastAlerts = { AggregationFields['rule.description'], AggregationFields['data.audit.exe'], AggregationFields['data.audit.type'], - ] -} + ], +}; const dockerAlertsSummary = { title: 'Events summary', @@ -169,8 +154,8 @@ const dockerAlertsSummary = { AggregationFields['data.docker.Actor.Attributes.name'], AggregationFields['data.docker.Action'], AggregationFields['timestamp'], - ] -} + ], +}; export default { general: [generalAlertsSummary, generalGroupsSummary], @@ -181,7 +166,6 @@ export default { nist: [nistLastAlerts], gcp: [gcpAlertsSummary], tsc: [tscAlertsSummary], - virustotal: [virustotalAlertsSummary], osquery: [osqueryAlertsSummary], mitre: [mitreAlertsSummary], ciscat: [ciscatAlertsSummary], @@ -191,4 +175,4 @@ export default { gdpr: [gdprLastAlerts], pci: [pciLastAlerts], docker: [dockerAlertsSummary], -} +}; diff --git a/plugins/main/server/routes/wazuh-reporting.ts b/plugins/main/server/routes/wazuh-reporting.ts index 7f78a27458..fe4fde4d70 100644 --- a/plugins/main/server/routes/wazuh-reporting.ts +++ b/plugins/main/server/routes/wazuh-reporting.ts @@ -18,16 +18,23 @@ export function WazuhReportingRoutes(router: IRouter) { const agentIDValidation = schema.string({ minLength: 3, - validate: (agentID: string) => /^\d{3,}$/.test(agentID) ? undefined : 'must be 0-9 are allowed' + validate: (agentID: string) => + /^\d{3,}$/.test(agentID) ? undefined : 'must be 0-9 are allowed', }); const groupIDValidation = schema.string({ minLength: 1, - validate: (agentID: string) => /^(?!^(\.{1,2}|all)$)[\w\.\-]+$/.test(agentID) ? undefined : 'must be A-z, 0-9, _, . are allowed. It must not be ., .. or all.' + validate: (agentID: string) => + /^(?!^(\.{1,2}|all)$)[\w\.\-]+$/.test(agentID) + ? undefined + : 'must be A-z, 0-9, _, . are allowed. It must not be ., .. or all.', }); const ReportFilenameValidation = schema.string({ - validate: (agentID: string) => /^[\w\-\.]+\.pdf$/.test(agentID) ? undefined : 'must be A-z, 0-9, _, ., and - are allowed. It must end with .pdf.' + validate: (agentID: string) => + /^[\w\-\.]+\.pdf$/.test(agentID) + ? undefined + : 'must be A-z, 0-9, _, ., and - are allowed. It must end with .pdf.', }); const moduleIDValidation = schema.oneOf([ @@ -43,7 +50,6 @@ export function WazuhReportingRoutes(router: IRouter) { schema.literal('ciscat'), schema.literal('vuls'), schema.literal('mitre'), - schema.literal('virustotal'), schema.literal('docker'), schema.literal('osquery'), schema.literal('oscap'), @@ -54,129 +60,154 @@ export function WazuhReportingRoutes(router: IRouter) { schema.literal('tsc'), ]); - router.post({ - path: '/reports/modules/{moduleID}', - validate: { - body: schema.object({ - array: schema.any(), - browserTimezone: schema.string(), - serverSideQuery: schema.maybe(schema.any()), - filters: schema.maybe(schema.any()), - agents: schema.maybe(schema.oneOf([agentIDValidation, schema.boolean()])), - components: schema.maybe(schema.any()), - searchBar: schema.maybe(schema.string()), - section: schema.maybe(schema.string()), - tab: schema.string(), - tables: schema.maybe(schema.any()), - time: schema.oneOf([schema.object({ - from: schema.string(), - to: schema.string() - }), schema.string()]), - indexPatternTitle: schema.string(), - apiId: schema.string() - }), - params: schema.object({ - moduleID: moduleIDValidation - }) - } - }, - (context, request, response) => ctrl.createReportsModules(context, request, response) + router.post( + { + path: '/reports/modules/{moduleID}', + validate: { + body: schema.object({ + array: schema.any(), + browserTimezone: schema.string(), + serverSideQuery: schema.maybe(schema.any()), + filters: schema.maybe(schema.any()), + agents: schema.maybe( + schema.oneOf([agentIDValidation, schema.boolean()]), + ), + components: schema.maybe(schema.any()), + searchBar: schema.maybe(schema.string()), + section: schema.maybe(schema.string()), + tab: schema.string(), + tables: schema.maybe(schema.any()), + time: schema.oneOf([ + schema.object({ + from: schema.string(), + to: schema.string(), + }), + schema.string(), + ]), + indexPatternTitle: schema.string(), + apiId: schema.string(), + }), + params: schema.object({ + moduleID: moduleIDValidation, + }), + }, + }, + (context, request, response) => + ctrl.createReportsModules(context, request, response), ); - router.post({ - path: '/reports/groups/{groupID}', - validate: { - body: schema.object({ - browserTimezone: schema.string(), - filters: schema.maybe(schema.any()), - components: schema.maybe(schema.any()), - section: schema.maybe(schema.string()), - apiId: schema.string() - }), - params: schema.object({ - groupID: groupIDValidation - }) - } - }, - (context, request, response) => ctrl.createReportsGroups(context, request, response) + router.post( + { + path: '/reports/groups/{groupID}', + validate: { + body: schema.object({ + browserTimezone: schema.string(), + filters: schema.maybe(schema.any()), + components: schema.maybe(schema.any()), + section: schema.maybe(schema.string()), + apiId: schema.string(), + }), + params: schema.object({ + groupID: groupIDValidation, + }), + }, + }, + (context, request, response) => + ctrl.createReportsGroups(context, request, response), ); - router.post({ - path: '/reports/agents/{agentID}', - validate: { - body: schema.object({ - browserTimezone: schema.string(), - filters: schema.any(), - components: schema.maybe(schema.any()), - section: schema.maybe(schema.string()), - apiId: schema.string() - }), - params: schema.object({ - agentID: agentIDValidation - }) - } - }, - (context, request, response) => ctrl.createReportsAgentsConfiguration(context, request, response) + router.post( + { + path: '/reports/agents/{agentID}', + validate: { + body: schema.object({ + browserTimezone: schema.string(), + filters: schema.any(), + components: schema.maybe(schema.any()), + section: schema.maybe(schema.string()), + apiId: schema.string(), + }), + params: schema.object({ + agentID: agentIDValidation, + }), + }, + }, + (context, request, response) => + ctrl.createReportsAgentsConfiguration(context, request, response), ); - router.post({ - path: '/reports/agents/{agentID}/inventory', - validate: { - body: schema.object({ - array: schema.any(), - browserTimezone: schema.string(), - serverSideQuery: schema.maybe(schema.any()), - filters: schema.maybe(schema.any()), - agents: schema.maybe(schema.oneOf([schema.string(), schema.boolean()])), - components: schema.maybe(schema.any()), - searchBar: schema.maybe(schema.oneOf([schema.string(), schema.boolean()])), - section: schema.maybe(schema.string()), - tab: schema.string(), - tables: schema.maybe(schema.any()), - time: schema.oneOf([schema.object({ - from: schema.string(), - to: schema.string() - }), schema.string()]), - indexPatternTitle: schema.string(), - apiId: schema.string() - }), - params: schema.object({ - agentID: agentIDValidation - }) - } - }, - (context, request, response) => ctrl.createReportsAgentsInventory(context, request, response) + router.post( + { + path: '/reports/agents/{agentID}/inventory', + validate: { + body: schema.object({ + array: schema.any(), + browserTimezone: schema.string(), + serverSideQuery: schema.maybe(schema.any()), + filters: schema.maybe(schema.any()), + agents: schema.maybe( + schema.oneOf([schema.string(), schema.boolean()]), + ), + components: schema.maybe(schema.any()), + searchBar: schema.maybe( + schema.oneOf([schema.string(), schema.boolean()]), + ), + section: schema.maybe(schema.string()), + tab: schema.string(), + tables: schema.maybe(schema.any()), + time: schema.oneOf([ + schema.object({ + from: schema.string(), + to: schema.string(), + }), + schema.string(), + ]), + indexPatternTitle: schema.string(), + apiId: schema.string(), + }), + params: schema.object({ + agentID: agentIDValidation, + }), + }, + }, + (context, request, response) => + ctrl.createReportsAgentsInventory(context, request, response), ); // Fetch specific report - router.get({ - path: '/reports/{name}', - validate: { - params: schema.object({ - name: ReportFilenameValidation - }) - } - }, - (context, request, response) => ctrl.getReportByName(context, request, response) + router.get( + { + path: '/reports/{name}', + validate: { + params: schema.object({ + name: ReportFilenameValidation, + }), + }, + }, + (context, request, response) => + ctrl.getReportByName(context, request, response), ); // Delete specific report - router.delete({ - path: '/reports/{name}', - validate: { - params: schema.object({ - name: ReportFilenameValidation - }) - } - }, - (context, request, response) => ctrl.deleteReportByName(context, request, response) - ) + router.delete( + { + path: '/reports/{name}', + validate: { + params: schema.object({ + name: ReportFilenameValidation, + }), + }, + }, + (context, request, response) => + ctrl.deleteReportByName(context, request, response), + ); // Fetch the reports list - router.get({ - path: '/reports', - validate: false - }, - (context, request, response) => ctrl.getReports(context, request, response) + router.get( + { + path: '/reports', + validate: false, + }, + (context, request, response) => ctrl.getReports(context, request, response), ); } diff --git a/plugins/wazuh-core/common/constants.ts b/plugins/wazuh-core/common/constants.ts index 604ab8db86..3b51f2e9bf 100644 --- a/plugins/wazuh-core/common/constants.ts +++ b/plugins/wazuh-core/common/constants.ts @@ -82,11 +82,11 @@ export const WAZUH_SAMPLE_ALERTS_CATEGORIES_TYPE_ALERTS = { { audit: true }, { openscap: true }, { ciscat: true }, + { virustotal: true }, { yara: true }, ], [WAZUH_SAMPLE_ALERTS_CATEGORY_THREAT_DETECTION]: [ { vulnerabilities: true }, - { virustotal: true }, { osquery: true }, { docker: true }, { mitre: true }, diff --git a/scripts/wazuh-alerts-generator/cli.js b/scripts/wazuh-alerts-generator/cli.js index 960cb418df..bb76d94843 100644 --- a/scripts/wazuh-alerts-generator/cli.js +++ b/scripts/wazuh-alerts-generator/cli.js @@ -107,14 +107,15 @@ 'web', 'windows', ], - 'auditing-policy-monitoring': ['audit', 'ciscat', 'openscap', 'rootcheck'], - 'thread-detection': [ - 'docker', - 'mitre', - 'osquery', + 'auditing-policy-monitoring': [ + 'audit', + 'ciscat', + 'openscap', + 'rootcheck', 'virustotal', - 'vulnerabilities', + 'yara', ], + 'thread-detection': ['docker', 'mitre', 'osquery', 'vulnerabilities'], }; function displayHelp() { From 79837fe6718f60a809bdaa0fe386936dd32d7e8f Mon Sep 17 00:00:00 2001 From: Federico Rodriguez Date: Tue, 15 Oct 2024 16:13:24 +0200 Subject: [PATCH 38/41] Add custom saved queries and fix duplicate requests (#7090) * Add custom saved queries * Add changelog * Add setTimeFilter function to save and update saved queries * Remove absolute date and add fingerprint to lastReloadRequestTime * Add explanation to fingerprint state * Add support for setting and updating refresh interval * Update saveSavedQuery function to handle newSavedQuery * Refactor saved query functions for better organization * Refactor functions to accept options for first time use * Add absolute date range for data grids * Refactor saved query hooks for setQuery and setFilters * Remove saved query clearing functionality * Refactor useSavedQuery function for better readability * Delete unused test and function for saved queries * Add jest spy for setFilters in useSearchBar hook test * Fix search-bar autorefresh feature * Apply autoRefreshFingerprint in dashboards * Add fingerprint to Vulnerabilities module * Refactor useSearchBar test for readability * Fix unit test * Prettier * Hide save query button in flyout search bar * Fix absolute date string format * By default show the save query button in the saved queries popover --------- Co-authored-by: Guido Modarelli --- CHANGELOG.md | 1 + plugins/main/common/constants.ts | 3 + .../common/data-grid/use-data-grid.ts | 1 + .../data-source/hooks/use-data-source.ts | 1 - .../common/hooks/saved_query/constants.ts | 1 + .../hooks/saved_query/use_saved_query.ts | 185 +++++++++++++++ .../common/hooks/use-time-filter.ts | 17 +- .../components/common/permissions/button.tsx | 17 +- .../common/search-bar/search-bar.tsx | 10 +- .../common/search-bar/use-search-bar.test.ts | 45 +++- .../common/search-bar/use-search-bar.ts | 87 +++++-- .../wazuh-discover/config/histogram-chart.ts | 2 + .../common/wazuh-discover/wz-discover.tsx | 40 +++- .../wazuh-discover/wz-flyout-discover.tsx | 65 ++++-- .../components/configuration_cards.tsx | 3 + .../cluster/components/overview_cards.tsx | 8 +- .../cluster/dashboard/dashboard.tsx | 16 +- .../dashboards/dashboard.tsx | 16 +- .../compliance-table/compliance-table.tsx | 15 +- .../overview/docker/dashboards/dashboard.tsx | 16 +- .../overview/fim/dashboard/dashboard.tsx | 16 +- .../overview/gdpr/dashboards/dashboard.tsx | 16 +- .../overview/github/dashboards/dashboard.tsx | 16 +- .../github/panel/config/drilldown-action.tsx | 5 +- .../github/panel/config/drilldown-actor.tsx | 5 +- .../panel/config/drilldown-organization.tsx | 5 +- .../panel/config/drilldown-repository.tsx | 5 +- .../google-cloud/dashboards/dashboard.tsx | 16 +- .../overview/hipaa/dashboards/dashboard.tsx | 16 +- .../malware-detection/dashboard/dashboard.tsx | 16 +- .../overview/mitre/dashboard/dashboard.tsx | 16 +- .../overview/mitre/framework/mitre.tsx | 19 +- .../overview/nist/dashboards/dashboard.tsx | 16 +- .../overview/office/dashboard/dashboard.tsx | 19 +- .../public/components/overview/overview.tsx | 13 +- .../overview/pci/dashboards/dashboard.tsx | 16 +- .../dashboards/dashboardTabsPanels.tsx | 16 +- .../dashboards/dashboard_analysis_engine.tsx | 3 + .../dashboards/dashboard_listener_engine.tsx | 3 + .../threat-hunting/dashboard/dashboard.tsx | 19 +- .../overview/tsc/dashboards/dashboard.tsx | 16 +- .../virustotal/dashboard/dashboard.tsx | 19 +- .../dashboards/inventory/inventory.tsx | 3 +- .../dashboards/overview/dashboard.tsx | 212 +++++++++--------- .../management/common/resources-handler.ts | 3 +- plugins/main/public/kibana-services.ts | 2 +- plugins/main/public/react-services/index.ts | 1 + .../public/react-services/state-storage.ts | 42 ++++ 48 files changed, 809 insertions(+), 294 deletions(-) create mode 100644 plugins/main/public/components/common/hooks/saved_query/constants.ts create mode 100644 plugins/main/public/components/common/hooks/saved_query/use_saved_query.ts create mode 100644 plugins/main/public/react-services/state-storage.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e4db2d778..8d55a1c879 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ All notable changes to the Wazuh app project will be documented in this file. - Fixed style when unnpinned an agent in endpoint summary section [#7015](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7015) - Fixed overflow style on a long value filter [#7021](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7021) - Fixed buttons enabled for a readonly user in `Endpoint groups` section [#7056](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7056) +- Fixed the automatic page refresh in dashboards and prevent duplicate requests [#7090](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7090) ### Changed diff --git a/plugins/main/common/constants.ts b/plugins/main/common/constants.ts index 62eb2fc7ec..8c1ba88829 100644 --- a/plugins/main/common/constants.ts +++ b/plugins/main/common/constants.ts @@ -528,3 +528,6 @@ export const SEARCH_BAR_DEBOUNCE_UPDATE_TIME = 400; // ID used to refer the createOsdUrlStateStorage state export const OSD_URL_STATE_STORAGE_ID = 'state:storeInSessionStorage'; + +export const APP_STATE_URL_KEY = '_a'; +export const GLOBAL_STATE_URL_KEY = '_g'; diff --git a/plugins/main/public/components/common/data-grid/use-data-grid.ts b/plugins/main/public/components/common/data-grid/use-data-grid.ts index a330fc5ad1..9caf231c31 100644 --- a/plugins/main/public/components/common/data-grid/use-data-grid.ts +++ b/plugins/main/public/components/common/data-grid/use-data-grid.ts @@ -236,5 +236,6 @@ export const useDataGrid = (props: tDataGridProps): EuiDataGridProps => { onChangeItemsPerPage: onChangeItemsPerPage, onChangePage: onChangePage, }, + setPagination, } as EuiDataGridProps; }; diff --git a/plugins/main/public/components/common/data-source/hooks/use-data-source.ts b/plugins/main/public/components/common/data-source/hooks/use-data-source.ts index 6a026e7b3a..0fec9b7db9 100644 --- a/plugins/main/public/components/common/data-source/hooks/use-data-source.ts +++ b/plugins/main/public/components/common/data-source/hooks/use-data-source.ts @@ -98,7 +98,6 @@ export function useDataSource< const { filters: initialFilters = [...defaultFilters], fetchFilters: initialFetchFilters = [], - fixedFilters: initialFixedFilters = [], DataSource: DataSourceConstructor, repository, factory: injectedFactory, diff --git a/plugins/main/public/components/common/hooks/saved_query/constants.ts b/plugins/main/public/components/common/hooks/saved_query/constants.ts new file mode 100644 index 0000000000..59d4f85684 --- /dev/null +++ b/plugins/main/public/components/common/hooks/saved_query/constants.ts @@ -0,0 +1 @@ +export const SAVED_QUERY = 'savedQuery'; diff --git a/plugins/main/public/components/common/hooks/saved_query/use_saved_query.ts b/plugins/main/public/components/common/hooks/saved_query/use_saved_query.ts new file mode 100644 index 0000000000..de1b8ec4f8 --- /dev/null +++ b/plugins/main/public/components/common/hooks/saved_query/use_saved_query.ts @@ -0,0 +1,185 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Any modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { useState, useEffect } from 'react'; +import { + DataPublicPluginStart, + RefreshInterval, + SavedQuery, + TimeRange, + Query, + Filter, +} from '../../../../../../../src/plugins/data/public'; +import NavigationService from '../../../../react-services/navigation-service'; +import { OSD_URL_STATE_STORAGE_ID } from '../../../../../common/constants'; +import { getDataPlugin, getUiSettings } from '../../../../kibana-services'; +import { createOsdUrlStateStorage } from '../../../../../../../src/plugins/opensearch_dashboards_utils/public'; +import OsdUrlStateStorage from '../../../../react-services/state-storage'; + +interface Options { + firstTime?: boolean; +} + +interface UseSavedQueriesProps { + queryService: DataPublicPluginStart['query']; + setTimeFilter: (timeFilter: TimeRange) => void; + setRefreshInterval: (refreshInterval: RefreshInterval) => void; + setQuery: (query?: Query) => void; + setFilters: (filters: Filter[]) => void; +} + +interface UseSavedQueriesReturn { + savedQuery?: SavedQuery; + setSavedQuery: (savedQuery: SavedQuery) => void; + clearSavedQuery: () => void; +} + +export const useSavedQuery = ( + props: UseSavedQueriesProps, +): UseSavedQueriesReturn => { + // Handle saved queries + const [savedQuery, setSavedQuery] = useState(); + const data = getDataPlugin(); + const config = getUiSettings(); + const history = NavigationService.getInstance().getHistory(); + const osdUrlStateStorage = createOsdUrlStateStorage({ + useHash: config.get(OSD_URL_STATE_STORAGE_ID), + history: history, + }); + + const getAppFilters = ( + newSavedQuery?: SavedQuery, + { firstTime }: Options = { firstTime: false }, + ) => { + const { filterManager } = props.queryService; + // When the page reloads, savedQuery starts as undefined, so retrieve the time and refreshInterval from the URL. + return firstTime + ? filterManager.getAppFilters() + : newSavedQuery?.attributes.filters ?? []; + }; + + const getQuery = ( + newSavedQuery?: SavedQuery, + { firstTime }: Options = { firstTime: false }, + ) => { + const { queryString } = props.queryService; + // When the page reloads, savedQuery starts as undefined, so retrieve the time and refreshInterval from the URL. + return firstTime + ? queryString.getQuery() + : newSavedQuery?.attributes.query ?? { query: '', language: 'kuery' }; + }; + + const getTimeFilter = ( + newSavedQuery?: SavedQuery, + { firstTime }: Options = { firstTime: false }, + ) => { + const { timefilter } = props.queryService; + // When the page reloads, savedQuery starts as undefined, so retrieve the time and refreshInterval from the URL. + return firstTime + ? timefilter.timefilter.getTime() + : newSavedQuery?.attributes.timefilter; + }; + + const getRefreshInterval = ( + newSavedQuery?: SavedQuery, + { firstTime }: Options = { firstTime: false }, + ) => { + const { timefilter } = props.queryService; + // When the page reloads, savedQuery starts as undefined, so retrieve the time and refreshInterval from the URL. + return firstTime + ? timefilter.timefilter.getRefreshInterval() + : newSavedQuery?.attributes.timefilter?.refreshInterval; + }; + + const setTimeFilter = (timeFilter: TimeRange) => { + props.setTimeFilter(timeFilter); + props.queryService.timefilter.timefilter.setTime(timeFilter); + }; + + const saveSavedQuery = async ( + newSavedQuery?: SavedQuery, + { firstTime }: Options = { firstTime: false }, + ) => { + setSavedQuery(newSavedQuery); + const filters = getAppFilters(newSavedQuery, { firstTime }); + const query = getQuery(newSavedQuery, { firstTime }); + await OsdUrlStateStorage(data, osdUrlStateStorage).replaceUrlAppState({ + savedQuery: newSavedQuery?.id, + }); + props.setFilters(filters); + props.setQuery(query); + if (newSavedQuery?.attributes.timefilter) { + setTimeFilter(getTimeFilter(newSavedQuery, { firstTime })); + props.setRefreshInterval( + getRefreshInterval(newSavedQuery, { firstTime }), + ); + } + }; + + const updateSavedQuery = async ( + savedQuery: SavedQuery, + { firstTime }: { firstTime?: boolean } = { firstTime: false }, + ) => { + saveSavedQuery(savedQuery, { firstTime }); + }; + + const clearSavedQuery = () => { + // remove saved query from url + saveSavedQuery(undefined); + }; + + // Effect is used to convert a saved query id into an object + useEffect(() => { + const fetchSavedQuery = async () => { + try { + const savedQueryId = OsdUrlStateStorage( + data, + osdUrlStateStorage, + ).getAppStateFromUrl().savedQuery as string; + if (!savedQueryId) return; + // fetch saved query + const savedQuery = await props.queryService.savedQueries.getSavedQuery( + savedQueryId, + ); + updateSavedQuery(savedQuery, { firstTime: true }); + } catch (error) { + clearSavedQuery(); + } + }; + + fetchSavedQuery(); + }, [props.queryService, props.queryService.savedQueries]); + + return { + savedQuery, + setSavedQuery: updateSavedQuery, + clearSavedQuery, + }; +}; diff --git a/plugins/main/public/components/common/hooks/use-time-filter.ts b/plugins/main/public/components/common/hooks/use-time-filter.ts index 384169f65f..f580cb38aa 100644 --- a/plugins/main/public/components/common/hooks/use-time-filter.ts +++ b/plugins/main/public/components/common/hooks/use-time-filter.ts @@ -30,15 +30,30 @@ export function useTimeFilter() { const [timeFilter, setTimeFilter] = useState( globalStateFromUrl?.time ?? timefilter.getTime(), ); + const [refreshInterval, setRefreshInterval] = useState( + globalStateFromUrl?.refreshInterval ?? timefilter.getRefreshInterval(), + ); const [timeHistory, setTimeHistory] = useState(timefilter._history); useEffect(() => { const subscription = timefilter.getTimeUpdate$().subscribe(() => { setTimeFilter(timefilter.getTime()); setTimeHistory(timefilter._history); }); + const subscriptionRefreshInterval = timefilter + .getRefreshIntervalUpdate$() + .subscribe(() => { + setRefreshInterval(timefilter.getRefreshInterval()); + }); return () => { subscription.unsubscribe(); + subscriptionRefreshInterval.unsubscribe(); }; }, []); - return { timeFilter, setTimeFilter: timefilter.setTime, timeHistory }; + return { + timeFilter, + setTimeFilter: timefilter.setTime, + refreshInterval, + setRefreshInterval: timefilter.setRefreshInterval, + timeHistory, + }; } diff --git a/plugins/main/public/components/common/permissions/button.tsx b/plugins/main/public/components/common/permissions/button.tsx index 6033960584..5f4d920e69 100644 --- a/plugins/main/public/components/common/permissions/button.tsx +++ b/plugins/main/public/components/common/permissions/button.tsx @@ -18,18 +18,19 @@ import { EuiButtonEmpty, EuiButtonIcon, EuiLink, + EuiButtonProps, } from '@elastic/eui'; import { IWzElementPermissionsProps, WzElementPermissions } from './element'; -interface IWzButtonPermissionsProps - extends Omit< - IWzElementPermissionsProps, - 'children' | 'additionalPropsFunction' - > { - buttonType?: 'default' | 'empty' | 'icon' | 'link' | 'switch'; - rest: any; -} +type IWzButtonPermissionsProps = Omit< + IWzElementPermissionsProps, + 'children' | 'additionalPropsFunction' +> & + React.ButtonHTMLAttributes & + EuiButtonProps & { + buttonType?: 'default' | 'empty' | 'icon' | 'link' | 'switch'; + }; export const WzButtonPermissions = ({ buttonType = 'default', diff --git a/plugins/main/public/components/common/search-bar/search-bar.tsx b/plugins/main/public/components/common/search-bar/search-bar.tsx index 3d713958af..50001fb25c 100644 --- a/plugins/main/public/components/common/search-bar/search-bar.tsx +++ b/plugins/main/public/components/common/search-bar/search-bar.tsx @@ -13,10 +13,14 @@ export interface WzSearchBarProps extends SearchBarProps { preQueryBar?: React.ReactElement; postFilters?: React.ReactElement; hideFixedFilters?: boolean; + showSaveQueryButton?: boolean; + showSaveQuery?: boolean; } export const WzSearchBar = ({ fixedFilters = [], + showSaveQueryButton = true, + showSaveQuery = true, preQueryBar, hideFixedFilters, postFilters, @@ -48,7 +52,11 @@ export const WzSearchBar = ({ > {preQueryBar ? {preQueryBar} : null} - + ) : null} diff --git a/plugins/main/public/components/common/search-bar/use-search-bar.test.ts b/plugins/main/public/components/common/search-bar/use-search-bar.test.ts index 6b0fc60ab1..e0c04a6315 100644 --- a/plugins/main/public/components/common/search-bar/use-search-bar.test.ts +++ b/plugins/main/public/components/common/search-bar/use-search-bar.test.ts @@ -16,6 +16,8 @@ import { getDataPlugin } from '../../../kibana-services'; import * as timeFilterHook from '../hooks/use-time-filter'; import * as queryManagerHook from '../hooks/use-query'; import { AppState } from '../../../react-services/app-state'; +import NavigationService from '../../../react-services/navigation-service'; +import { createHashHistory, History } from 'history'; /** * Mocking Data Plugin @@ -23,8 +25,12 @@ import { AppState } from '../../../react-services/app-state'; jest.mock('../../../kibana-services', () => { return { getDataPlugin: jest.fn(), + getUiSettings: jest.fn().mockImplementation(() => ({ + get: () => true, + })), }; }); + /* using osd mock utils */ const mockDataPlugin = dataPluginMock.createStartContract(); const mockedGetDataPlugin = getDataPlugin as jest.Mock; @@ -42,10 +48,25 @@ mockedGetDataPlugin.mockImplementation( unsubscribe: jest.fn(), })), }, + timefilter: { + ...mockDataPlugin.query.queryString.timefilter, + timefilter: { + getRefreshInterval: jest.fn().mockImplementation(() => ({ + value: 0, + pause: false, + })), + getAutoRefreshFetch$: jest.fn().mockImplementation(() => ({ + subscribe: jest + .fn() + .mockImplementation(() => ({ unsubscribe: jest.fn() })), + })), + }, + }, }, }, } as Start), ); + /////////////////////////////////////////////////////////// const mockedDefaultIndexPatternData: Partial = { @@ -55,6 +76,9 @@ const mockedDefaultIndexPatternData: Partial = { }; describe('[hook] useSearchBarConfiguration', () => { + let history: History; + let navigationService: NavigationService; + beforeAll(() => { /***** mock use-time-filter hook *****/ const spyUseTimeFilter = jest.spyOn(timeFilterHook, 'useTimeFilter'); @@ -76,6 +100,11 @@ describe('[hook] useSearchBarConfiguration', () => { spyUseQueryManager.mockImplementation(() => [mockQueryResult, jest.fn()]); }); + beforeEach(() => { + history = createHashHistory(); + navigationService = NavigationService.getInstance(history); + }); + it('should return default app index pattern when not receiving a default index pattern', async () => { jest .spyOn(AppState, 'getCurrentPattern') @@ -87,7 +116,11 @@ describe('[hook] useSearchBarConfiguration', () => { .spyOn(mockDataPlugin.query.filterManager, 'getFilters') .mockReturnValue([]); // @ts-ignore - const { result, waitForNextUpdate } = renderHook(() => useSearchBar({})); + const { result, waitForNextUpdate } = renderHook(() => + useSearchBar({ + setFilters: jest.fn(), + }), + ); await waitForNextUpdate(); expect(mockDataPlugin.indexPatterns.getDefault).toBeCalled(); expect(result.current.searchBarProps.indexPatterns).toMatchObject([ @@ -143,7 +176,7 @@ describe('[hook] useSearchBarConfiguration', () => { const { result, waitForNextUpdate } = renderHook(() => useSearchBar({ indexPattern: mockedExampleIndexPatternData as IndexPattern, - setFilters: jest.fn() + setFilters: jest.fn(), }), ); expect(result.current.searchBarProps.indexPatterns).toMatchObject([ @@ -174,11 +207,11 @@ describe('[hook] useSearchBarConfiguration', () => { .mockReturnValue([]); const { result, waitForNextUpdate, rerender } = renderHook( // @ts-ignore - (props) => useSearchBar(props), + props => useSearchBar(props), { initialProps: { indexPattern: mockedExampleIndexPatternData as IndexPattern, - setFilters: jest.fn() + setFilters: jest.fn(), }, }, ); @@ -195,10 +228,10 @@ describe('[hook] useSearchBarConfiguration', () => { .mockResolvedValue(newExampleIndexPatternData); rerender({ indexPattern: newExampleIndexPatternData as IndexPattern, - setFilters: jest.fn() + setFilters: jest.fn(), }); expect(result.current.searchBarProps.indexPatterns).toMatchObject([ newExampleIndexPatternData, ]); - }) + }); }); diff --git a/plugins/main/public/components/common/search-bar/use-search-bar.ts b/plugins/main/public/components/common/search-bar/use-search-bar.ts index b11c0e5113..747527e217 100644 --- a/plugins/main/public/components/common/search-bar/use-search-bar.ts +++ b/plugins/main/public/components/common/search-bar/use-search-bar.ts @@ -1,4 +1,5 @@ import { useEffect, useState } from 'react'; +import { isEqual } from 'lodash'; import { SearchBarProps, TimeRange, @@ -9,14 +10,14 @@ import { } from '../../../../../../src/plugins/data/public'; import { getDataPlugin } from '../../../kibana-services'; import { useQueryManager, useTimeFilter } from '../hooks'; -import { transformDateRange } from './search-bar-service'; +import { useSavedQuery } from '../hooks/saved_query/use_saved_query'; // Input - types type tUseSearchBarCustomInputs = { indexPattern: IndexPattern; setFilters: (filters: Filter[]) => void; setTimeFilter?: (timeRange: TimeRange) => void; - setQuery?: (query: Query) => void; + setQuery?: (query?: Query) => void; onFiltersUpdated?: (filters: Filter[]) => void; onQuerySubmitted?: ( payload: { dateRange: TimeRange; query?: Query }, @@ -31,9 +32,10 @@ type tUserSearchBarResponse = { searchBarProps: Partial< SearchBarProps & { useDefaultBehaviors: boolean; - absoluteDateRange: TimeRange; } >; + fingerprint: number; + autoRefreshFingerprint: number; }; /** @@ -44,25 +46,40 @@ type tUserSearchBarResponse = { const useSearchBarConfiguration = ( props: tUseSearchBarProps, ): tUserSearchBarResponse => { - const { indexPattern, filters: defaultFilters, setFilters } = props; + const { indexPattern, filters = [], setFilters } = props; // dependencies const { timeFilter: globalTimeFilter, timeHistory, setTimeFilter: setGlobalTimeFilter, + setRefreshInterval, } = useTimeFilter(); - const filters = defaultFilters ?? []; const [timeFilter, setTimeFilter] = useState(globalTimeFilter); const [query, setQuery] = props?.setQuery ? useState(props?.query || { query: '', language: 'kuery' }) : useQueryManager(); - // This absoluteDateRange is used to ensure that the date range is the same when we make the - // pagination request with relative dates like "Last 24 hours" - const [absoluteDateRange, setAbsoluteDateRange] = useState( - transformDateRange(globalTimeFilter), + /* The state of the fingerprint is meant to pass this value to "lastReloadRequestTime" in + * the Dashboards embeddables so they refresh when the user clicks on the Update button in the search bar. + */ + const [fingerprint, setFingerprint] = useState(Date.now()); + + /* + This fingerprint is used for auto refresh of time filter + */ + const [autoRefreshFingerprint, setAutoRefreshFingerprint] = useState( + Date.now(), ); + + const { query: queryService } = getDataPlugin(); + const { savedQuery, setSavedQuery, clearSavedQuery } = useSavedQuery({ + queryService, + setTimeFilter, + setRefreshInterval, + setFilters, + setQuery, + }); // states const [isLoading, setIsLoading] = useState(true); const [indexPatternSelected, setIndexPatternSelected] = @@ -74,10 +91,20 @@ const useSearchBarConfiguration = ( } }, [indexPattern]); + useEffect(() => setTimeFilter(globalTimeFilter), [globalTimeFilter]); + useEffect(() => { initSearchBar(); }, []); + // Subscribe to changes in the search bar auto refresh feature (every 5 seconds, etc.) + useEffect(() => { + const subscription = queryService.timefilter.timefilter + .getAutoRefreshFetch$() + .subscribe(() => setAutoRefreshFingerprint(Date.now())); + return () => subscription.unsubscribe(); + }, []); + /** * Initialize the searchbar props with the corresponding index pattern and filters */ @@ -106,10 +133,10 @@ const useSearchBarConfiguration = ( /** * Search bar properties necessary to render and initialize the osd search bar component */ + const searchBarProps: Partial< SearchBarProps & { useDefaultBehaviors: boolean; - absoluteDateRange: TimeRange; } > = { isLoading, @@ -117,7 +144,6 @@ const useSearchBarConfiguration = ( filters, query, timeHistory, - absoluteDateRange, dateRangeFrom: timeFilter.from, dateRangeTo: timeFilter.to, onFiltersUpdated: (userFilters: Filter[]) => { @@ -126,28 +152,51 @@ const useSearchBarConfiguration = ( : console.warn('setFilters function is not defined'); props?.onFiltersUpdated && props?.onFiltersUpdated(userFilters); }, + refreshInterval: + queryService.timefilter.timefilter.getRefreshInterval().value, + isRefreshPaused: + queryService.timefilter.timefilter.getRefreshInterval().pause, + onRefreshChange: (options: { + isPaused: boolean; + refreshInterval: number; + }) => { + const { timefilter } = queryService.timefilter; + timefilter.setRefreshInterval({ + value: options.refreshInterval, + pause: options.isPaused, + }); + }, onQuerySubmit: ( payload: { dateRange: TimeRange; query?: Query }, _isUpdate?: boolean, ): void => { - const { dateRange, query } = payload; + const { dateRange: newDateRange, query: newQuery } = payload; // its necessary execute setter to apply query filters // when the hook receives the dateRange use the setter instead the global setTimeFilter props?.setTimeFilter - ? props?.setTimeFilter(dateRange) - : setGlobalTimeFilter(dateRange); - props?.setQuery ? props?.setQuery(query) : setQuery(query); + ? props?.setTimeFilter(newDateRange) + : setGlobalTimeFilter(newDateRange); + props?.setQuery ? props?.setQuery(newQuery) : setQuery(newQuery); props?.onQuerySubmitted && props?.onQuerySubmitted(payload); - setTimeFilter(dateRange); - setAbsoluteDateRange(transformDateRange(dateRange)); - setQuery(query); + // Change the fingerprint only when the search parameter are all the same. This should happen only when the user clicks on Update button + if (isEqual(newDateRange, timeFilter) && isEqual(query, newQuery)) { + setFingerprint(Date.now()); + } + + setTimeFilter(newDateRange); + setQuery(newQuery); }, // its necessary to use saved queries. if not, the load saved query not work - useDefaultBehaviors: true, + onClearSavedQuery: clearSavedQuery, + onSaved: setSavedQuery, + onSavedQueryUpdated: setSavedQuery, + savedQuery, }; return { searchBarProps, + fingerprint, + autoRefreshFingerprint, }; }; diff --git a/plugins/main/public/components/common/wazuh-discover/config/histogram-chart.ts b/plugins/main/public/components/common/wazuh-discover/config/histogram-chart.ts index 5c7966dfbd..db8a791986 100644 --- a/plugins/main/public/components/common/wazuh-discover/config/histogram-chart.ts +++ b/plugins/main/public/components/common/wazuh-discover/config/histogram-chart.ts @@ -135,6 +135,7 @@ export const histogramChartInput = ( query, dateRangeFrom, dateRangeTo, + lastReloadRequestTime, ) => ({ viewMode: ViewMode.VIEW, panels: getDiscoverPanels(indexPatternId), @@ -154,4 +155,5 @@ export const histogramChartInput = ( value: 15, }, hidePanelTitles: true, + lastReloadRequestTime, }); diff --git a/plugins/main/public/components/common/wazuh-discover/wz-discover.tsx b/plugins/main/public/components/common/wazuh-discover/wz-discover.tsx index f679f0a142..cfd96a987b 100644 --- a/plugins/main/public/components/common/wazuh-discover/wz-discover.tsx +++ b/plugins/main/public/components/common/wazuh-discover/wz-discover.tsx @@ -12,6 +12,7 @@ import { EuiFlyoutHeader, EuiPanel, } from '@elastic/eui'; +import { TimeRange } from '../../../../../../src/plugins/data/public'; import { IntlProvider } from 'react-intl'; import { IndexPattern } from '../../../../../../src/plugins/data/common'; import { SearchResponse } from '../../../../../../src/core/server'; @@ -48,6 +49,7 @@ import { import DiscoverDataGridAdditionalControls from './components/data-grid-additional-controls'; import { wzDiscoverRenderColumns } from './render-columns'; import { WzSearchBar } from '../search-bar'; +import { transformDateRange } from '../search-bar/search-bar-service'; import DocDetailsHeader from './components/doc-details-header'; export const MAX_ENTRIES_PER_QUERY = 10000; @@ -110,13 +112,15 @@ const WazuhDiscoverComponent = (props: WazuhDiscoverProps) => { ); }; - const { searchBarProps } = useSearchBar({ + const { searchBarProps, fingerprint, autoRefreshFingerprint } = useSearchBar({ indexPattern: dataSource?.indexPattern as IndexPattern, filters, setFilters, }); - const { query, absoluteDateRange } = searchBarProps; - + const { query, dateRangeFrom, dateRangeTo } = searchBarProps; + const [absoluteDateRange, setAbsoluteDateRange] = useState( + transformDateRange({ from: dateRangeFrom, to: dateRangeTo }), + ); const dataGridProps = useDataGrid({ ariaLabelledBy: 'Discover events table', defaultColumns: defaultTableColumns, @@ -129,13 +133,15 @@ const WazuhDiscoverComponent = (props: WazuhDiscoverProps) => { setFilters, }); - const { pagination, sorting, columnVisibility } = dataGridProps; + const { pagination, setPagination, sorting, columnVisibility } = + dataGridProps; useEffect(() => { if (isDataSourceLoading) { return; } setIndexPattern(dataSource?.indexPattern); + fetchData({ query, pagination, @@ -150,12 +156,27 @@ const WazuhDiscoverComponent = (props: WazuhDiscoverProps) => { }); ErrorHandler.handleError(searchError); }); + }, [absoluteDateRange, JSON.stringify(sorting), JSON.stringify(pagination)]); + + useEffect(() => { + if (isDataSourceLoading) { + return; + } + setIndexPattern(dataSource?.indexPattern); + setPagination(pagination => ({ + ...pagination, + pageIndex: 0, + })); + setAbsoluteDateRange( + transformDateRange({ from: dateRangeFrom, to: dateRangeTo }), + ); }, [ JSON.stringify(fetchFilters), JSON.stringify(query), - JSON.stringify(sorting), - JSON.stringify(pagination), - JSON.stringify(absoluteDateRange), + dateRangeFrom, + dateRangeTo, + fingerprint, + autoRefreshFingerprint, ]); const timeField = indexPattern?.timeFieldName @@ -239,8 +260,9 @@ const WazuhDiscoverComponent = (props: WazuhDiscoverProps) => { AlertsRepository.getStoreIndexPatternId(), fetchFilters, query, - absoluteDateRange.from, - absoluteDateRange.to, + dateRangeFrom, + dateRangeTo, + fingerprint, )} /> diff --git a/plugins/main/public/components/common/wazuh-discover/wz-flyout-discover.tsx b/plugins/main/public/components/common/wazuh-discover/wz-flyout-discover.tsx index 93cb855a4f..f0e2e4199f 100644 --- a/plugins/main/public/components/common/wazuh-discover/wz-flyout-discover.tsx +++ b/plugins/main/public/components/common/wazuh-discover/wz-flyout-discover.tsx @@ -9,6 +9,7 @@ import { EuiPanel, EuiText, } from '@elastic/eui'; +import { TimeRange } from '../../../../../../src/plugins/data/public'; import { HitsCounter } from '../../../kibana-integrations/discover/application/components/hits_counter'; import { formatNumWithCommas } from '../../../kibana-integrations/discover/application/helpers'; import { IntlProvider } from 'react-intl'; @@ -36,6 +37,7 @@ import { } from '../data-source'; import DocDetails from './components/doc-details'; import { WzSearchBar } from '../search-bar/search-bar'; +import { transformDateRange } from '../search-bar/search-bar-service'; import { MAX_ENTRIES_PER_QUERY } from '../data-grid/data-grid-service'; export const DEFAULT_PAGE_SIZE_OPTIONS = [20, 50, 100]; export const DEFAULT_PAGE_SIZE = 20; @@ -116,7 +118,7 @@ const WazuhFlyoutDiscoverComponent = (props: WazuhDiscoverProps) => { to: timeFilter.to, }); - const { searchBarProps } = useSearchBar({ + const { searchBarProps, fingerprint, autoRefreshFingerprint } = useSearchBar({ indexPattern: dataSource?.indexPattern as IndexPattern, filters, setFilters, @@ -124,7 +126,9 @@ const WazuhFlyoutDiscoverComponent = (props: WazuhDiscoverProps) => { setTimeFilter: setDateRange, } as tUseSearchBarProps); - const { absoluteDateRange } = searchBarProps; + const [absoluteDateRange, setAbsoluteDateRange] = useState( + transformDateRange({ from: dateRange.from, to: dateRange.to }), + ); const parseSorting = useMemo(() => { if (!sorting) { @@ -142,11 +146,12 @@ const WazuhFlyoutDiscoverComponent = (props: WazuhDiscoverProps) => { return; } setIndexPattern(dataSource?.indexPattern); + fetchData({ query, - dateRange: absoluteDateRange, pagination, sorting: parseSorting, + dateRange: absoluteDateRange, }) .then((response: SearchResponse) => { setPagination({ @@ -154,20 +159,35 @@ const WazuhFlyoutDiscoverComponent = (props: WazuhDiscoverProps) => { }); setResults(response); }) - .catch((error: HttpError) => { + .catch(error => { const searchError = ErrorFactory.create(HttpError, { error, message: 'Error fetching data', }); ErrorHandler.handleError(searchError); }); + }, [absoluteDateRange, JSON.stringify(sorting), JSON.stringify(pagination)]); + + useEffect(() => { + if (isDataSourceLoading) { + return; + } + + setPagination(pagination => ({ + ...pagination, + pageIndex: 0, + })); + setAbsoluteDateRange( + transformDateRange({ from: dateRange.from, to: dateRange.to }), + ); }, [ isDataSourceLoading, JSON.stringify(fetchFilters), JSON.stringify(query), - JSON.stringify(sorting), - JSON.stringify(pagination), - JSON.stringify(absoluteDateRange), + dateRange.from, + dateRange.to, + fingerprint, + autoRefreshFingerprint, ]); const toggleDetails = item => { @@ -278,6 +298,7 @@ const WazuhFlyoutDiscoverComponent = (props: WazuhDiscoverProps) => { {...searchBarProps} useDefaultBehaviors={false} hideFixedFilters + showSaveQueryButton={false} /> {!isDataSourceLoading && results?.hits?.total === 0 && ( @@ -307,21 +328,21 @@ const WazuhFlyoutDiscoverComponent = (props: WazuhDiscoverProps) => { : undefined } /> - {absoluteDateRange ? ( - - - - {formatUIDate(absoluteDateRange?.from)} -{' '} - {formatUIDate(absoluteDateRange?.to)} - - - - ) : null} + + + + + {`${formatUIDate( + absoluteDateRange?.from, + )} - ${formatUIDate(absoluteDateRange?.to)}`} + + + { const configurationItemsList = [ { @@ -126,6 +128,7 @@ export const ConfigurationCards = ({ value: 15, }, hidePanelTitles: false, + lastReloadRequestTime, }} /> ) : ( diff --git a/plugins/main/public/components/management/cluster/components/overview_cards.tsx b/plugins/main/public/components/management/cluster/components/overview_cards.tsx index a68bfc0d89..5b6db7ac3f 100644 --- a/plugins/main/public/components/management/cluster/components/overview_cards.tsx +++ b/plugins/main/public/components/management/cluster/components/overview_cards.tsx @@ -31,6 +31,7 @@ interface OverviewCardsProps { indexPattern: tParsedIndexPattern; clusterName?: string; filters: tFilter[]; + lastReloadRequestTime: number; } const plugins = getPlugins(); @@ -52,6 +53,7 @@ export const OverviewCards = ({ indexPattern, clusterName, filters, + lastReloadRequestTime, }: OverviewCardsProps) => { return ( <> @@ -211,7 +213,10 @@ export const OverviewCards = ({ filters: filters, useMargins: true, id: 'ct-dashboard-tab', - timeRange: searchBarProps?.absoluteDateRange, + timeRange: { + from: searchBarProps?.dateRangeFrom, + to: searchBarProps?.dateRangeTo, + }, title: 'Cluster Timelions dashboard', description: 'Dashboard of the Cluster Timelions', query: searchBarProps.query, @@ -220,6 +225,7 @@ export const OverviewCards = ({ value: 15, }, hidePanelTitles: false, + lastReloadRequestTime, }} />
diff --git a/plugins/main/public/components/management/cluster/dashboard/dashboard.tsx b/plugins/main/public/components/management/cluster/dashboard/dashboard.tsx index c4a8e64b9a..963a008e57 100644 --- a/plugins/main/public/components/management/cluster/dashboard/dashboard.tsx +++ b/plugins/main/public/components/management/cluster/dashboard/dashboard.tsx @@ -67,12 +67,12 @@ const DashboardCT: React.FC = ({ statusRunning }) => { const [results, setResults] = useState({} as SearchResponse); - const { searchBarProps } = useSearchBar({ + const { searchBarProps, fingerprint, autoRefreshFingerprint } = useSearchBar({ indexPattern: dataSource?.indexPattern as IndexPattern, filters, setFilters, }); - const { query, absoluteDateRange } = searchBarProps; + const { query, dateRangeFrom, dateRangeTo } = searchBarProps; useEffect(() => { if (isDataSourceLoading) { @@ -80,7 +80,10 @@ const DashboardCT: React.FC = ({ statusRunning }) => { } fetchData({ query, - dateRange: absoluteDateRange, + dateRange: { + from: dateRangeFrom, + to: dateRangeTo, + }, }) .then(results => { setResults(results); @@ -95,7 +98,10 @@ const DashboardCT: React.FC = ({ statusRunning }) => { }, [ JSON.stringify(fetchFilters), JSON.stringify(query), - JSON.stringify(absoluteDateRange), + dateRangeFrom, + dateRangeTo, + fingerprint, + autoRefreshFingerprint, ]); const setBooleans = (component: string | null) => { @@ -182,6 +188,7 @@ const DashboardCT: React.FC = ({ statusRunning }) => { results={results} indexPattern={dataSource?.indexPattern} filters={fetchFilters ?? []} + lastReloadRequestTime={fingerprint} /> ) : null} {state.showConfig ? ( @@ -192,6 +199,7 @@ const DashboardCT: React.FC = ({ statusRunning }) => { results={results} indexPatternId={dataSource?.id} filters={fetchFilters ?? []} + lastReloadRequestTime={fingerprint} /> ) : null} {state.showNodes ? : null} diff --git a/plugins/main/public/components/overview/amazon-web-services/dashboards/dashboard.tsx b/plugins/main/public/components/overview/amazon-web-services/dashboards/dashboard.tsx index 6692bdd095..c472f7bb18 100644 --- a/plugins/main/public/components/overview/amazon-web-services/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/amazon-web-services/dashboards/dashboard.tsx @@ -48,13 +48,13 @@ const DashboardAWSComponents: React.FC = ({}) => { const [results, setResults] = useState({} as SearchResponse); - const { searchBarProps } = useSearchBar({ + const { searchBarProps, fingerprint, autoRefreshFingerprint } = useSearchBar({ indexPattern: dataSource?.indexPattern as IndexPattern, filters, setFilters, }); - const { query, absoluteDateRange } = searchBarProps; + const { query, dateRangeFrom, dateRangeTo } = searchBarProps; useReportingCommunicateSearchContext({ isSearching: isDataSourceLoading, @@ -62,7 +62,7 @@ const DashboardAWSComponents: React.FC = ({}) => { indexPattern: dataSource?.indexPattern, filters: fetchFilters, query: query, - time: absoluteDateRange, + time: { from: dateRangeFrom, to: dateRangeTo }, }); useEffect(() => { @@ -71,7 +71,7 @@ const DashboardAWSComponents: React.FC = ({}) => { } fetchData({ query, - dateRange: absoluteDateRange, + dateRange: { from: dateRangeFrom, to: dateRangeTo }, }) .then(results => setResults(results)) .catch(error => { @@ -84,7 +84,10 @@ const DashboardAWSComponents: React.FC = ({}) => { }, [ JSON.stringify(fetchFilters), JSON.stringify(query), - JSON.stringify(absoluteDateRange), + dateRangeFrom, + dateRangeTo, + fingerprint, + autoRefreshFingerprint, ]); return ( <> @@ -121,7 +124,7 @@ const DashboardAWSComponents: React.FC = ({}) => { filters: fetchFilters || [], useMargins: true, id: 'aws-dashboard-tab', - timeRange: absoluteDateRange, + timeRange: { from: dateRangeFrom, to: dateRangeTo }, title: 'AWS dashboard', description: 'Dashboard of the AWS', query: query, @@ -130,6 +133,7 @@ const DashboardAWSComponents: React.FC = ({}) => { value: 15, }, hidePanelTitles: false, + lastReloadRequestTime: fingerprint, }} />
diff --git a/plugins/main/public/components/overview/compliance-table/compliance-table.tsx b/plugins/main/public/components/overview/compliance-table/compliance-table.tsx index d186be87a9..045ad5a32c 100644 --- a/plugins/main/public/components/overview/compliance-table/compliance-table.tsx +++ b/plugins/main/public/components/overview/compliance-table/compliance-table.tsx @@ -156,13 +156,13 @@ export const ComplianceTable = withAgentSupportModule(props => { repository: new AlertsDataSourceRepository(), }); - const { searchBarProps } = useSearchBar({ + const { searchBarProps, fingerprint, autoRefreshFingerprint } = useSearchBar({ indexPattern: dataSource?.indexPattern as IndexPattern, filters, setFilters, }); - const { absoluteDateRange } = searchBarProps; + const { dateRangeFrom, dateRangeTo } = searchBarProps; const [complianceData, setComplianceData] = useState({ descriptions: {}, complianceObject: {}, @@ -232,7 +232,7 @@ export const ComplianceTable = withAgentSupportModule(props => { const data = await fetchData({ aggs, query, - dateRange: absoluteDateRange, + dateRange: dateRange, }); return data?.aggregations?.tactics?.buckets || []; @@ -257,7 +257,7 @@ export const ComplianceTable = withAgentSupportModule(props => { props.section, dataSource, searchBarProps.query, - absoluteDateRange, + { from: dateRangeFrom, to: dateRangeTo }, ]); useEffect(() => { @@ -274,14 +274,17 @@ export const ComplianceTable = withAgentSupportModule(props => { section: props.section, fetchData, query: searchBarProps.query, - dateRange: absoluteDateRange, + dateRange: { from: dateRangeFrom, to: dateRangeTo }, }); } }, [ dataSource, JSON.stringify(searchBarProps.query), JSON.stringify(fetchFilters), - JSON.stringify(absoluteDateRange), + dateRangeFrom, + dateRangeTo, + fingerprint, + autoRefreshFingerprint, ]); return ( diff --git a/plugins/main/public/components/overview/docker/dashboards/dashboard.tsx b/plugins/main/public/components/overview/docker/dashboards/dashboard.tsx index e95a8a46d6..319b09994f 100644 --- a/plugins/main/public/components/overview/docker/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/docker/dashboards/dashboard.tsx @@ -48,13 +48,13 @@ const DashboardDockerComponent: React.FC = ({}) => { const [results, setResults] = useState({} as SearchResponse); - const { searchBarProps } = useSearchBar({ + const { searchBarProps, fingerprint, autoRefreshFingerprint } = useSearchBar({ indexPattern: dataSource?.indexPattern as IndexPattern, filters, setFilters, }); - const { query, absoluteDateRange } = searchBarProps; + const { query, dateRangeFrom, dateRangeTo } = searchBarProps; useReportingCommunicateSearchContext({ isSearching: isDataSourceLoading, @@ -62,7 +62,7 @@ const DashboardDockerComponent: React.FC = ({}) => { indexPattern: dataSource?.indexPattern, filters: fetchFilters, query: query, - time: absoluteDateRange, + time: { from: dateRangeFrom, to: dateRangeTo }, }); useEffect(() => { @@ -71,7 +71,7 @@ const DashboardDockerComponent: React.FC = ({}) => { } fetchData({ query, - dateRange: absoluteDateRange, + dateRange: { from: dateRangeFrom, to: dateRangeTo }, }) .then(results => setResults(results)) .catch(error => { @@ -84,7 +84,10 @@ const DashboardDockerComponent: React.FC = ({}) => { }, [ JSON.stringify(fetchFilters), JSON.stringify(query), - JSON.stringify(absoluteDateRange), + dateRangeFrom, + dateRangeTo, + fingerprint, + autoRefreshFingerprint, ]); return ( @@ -123,7 +126,7 @@ const DashboardDockerComponent: React.FC = ({}) => { filters: fetchFilters ?? [], useMargins: true, id: 'docker-dashboard-tab', - timeRange: absoluteDateRange, + timeRange: { from: dateRangeFrom, to: dateRangeTo }, title: 'Docker dashboard', description: 'Dashboard of Docker', query: query, @@ -132,6 +135,7 @@ const DashboardDockerComponent: React.FC = ({}) => { value: 15, }, hidePanelTitles: false, + lastReloadRequestTime: fingerprint, }} /> diff --git a/plugins/main/public/components/overview/fim/dashboard/dashboard.tsx b/plugins/main/public/components/overview/fim/dashboard/dashboard.tsx index 371bfb503a..cbecbf7704 100644 --- a/plugins/main/public/components/overview/fim/dashboard/dashboard.tsx +++ b/plugins/main/public/components/overview/fim/dashboard/dashboard.tsx @@ -48,13 +48,13 @@ const DashboardFIMComponent: React.FC = ({}) => { const [results, setResults] = useState({} as SearchResponse); - const { searchBarProps } = useSearchBar({ + const { searchBarProps, fingerprint, autoRefreshFingerprint } = useSearchBar({ indexPattern: dataSource?.indexPattern as IndexPattern, filters, setFilters, }); - const { query, absoluteDateRange } = searchBarProps; + const { query, dateRangeFrom, dateRangeTo } = searchBarProps; useReportingCommunicateSearchContext({ isSearching: isDataSourceLoading, @@ -62,7 +62,7 @@ const DashboardFIMComponent: React.FC = ({}) => { indexPattern: dataSource?.indexPattern, filters: fetchFilters, query: query, - time: absoluteDateRange, + time: { from: dateRangeFrom, to: dateRangeTo }, }); useEffect(() => { @@ -71,7 +71,7 @@ const DashboardFIMComponent: React.FC = ({}) => { } fetchData({ query, - dateRange: absoluteDateRange, + dateRange: { from: dateRangeFrom, to: dateRangeTo }, }) .then(results => setResults(results)) .catch(error => { @@ -84,7 +84,10 @@ const DashboardFIMComponent: React.FC = ({}) => { }, [ JSON.stringify(fetchFilters), JSON.stringify(query), - JSON.stringify(absoluteDateRange), + dateRangeFrom, + dateRangeTo, + fingerprint, + autoRefreshFingerprint, ]); return ( @@ -125,7 +128,7 @@ const DashboardFIMComponent: React.FC = ({}) => { filters: fetchFilters ?? [], useMargins: true, id: 'fim-dashboard-tab', - timeRange: absoluteDateRange, + timeRange: { from: dateRangeFrom, to: dateRangeTo }, title: 'File Integrity Monitoring dashboard', description: 'Dashboard of the File Integrity Monitoring', query: query, @@ -134,6 +137,7 @@ const DashboardFIMComponent: React.FC = ({}) => { value: 15, }, hidePanelTitles: false, + lastReloadRequestTime: fingerprint, }} /> diff --git a/plugins/main/public/components/overview/gdpr/dashboards/dashboard.tsx b/plugins/main/public/components/overview/gdpr/dashboards/dashboard.tsx index 382ecb0af6..5d43106d47 100644 --- a/plugins/main/public/components/overview/gdpr/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/gdpr/dashboards/dashboard.tsx @@ -47,13 +47,13 @@ const DashboardGDPRComponent: React.FC = () => { }); const [results, setResults] = useState({} as SearchResponse); - const { searchBarProps } = useSearchBar({ + const { searchBarProps, fingerprint, autoRefreshFingerprint } = useSearchBar({ indexPattern: dataSource?.indexPattern as IndexPattern, filters, setFilters, }); - const { query, absoluteDateRange } = searchBarProps; + const { query, dateRangeFrom, dateRangeTo } = searchBarProps; useReportingCommunicateSearchContext({ isSearching: isDataSourceLoading, @@ -61,7 +61,7 @@ const DashboardGDPRComponent: React.FC = () => { indexPattern: dataSource?.indexPattern, filters: fetchFilters, query: query, - time: absoluteDateRange, + time: { from: dateRangeFrom, to: dateRangeTo }, }); useEffect(() => { @@ -70,7 +70,7 @@ const DashboardGDPRComponent: React.FC = () => { } fetchData({ query, - dateRange: absoluteDateRange, + dateRange: { from: dateRangeFrom, to: dateRangeTo }, }) .then(results => { setResults(results); @@ -85,7 +85,10 @@ const DashboardGDPRComponent: React.FC = () => { }, [ JSON.stringify(fetchFilters), JSON.stringify(query), - JSON.stringify(absoluteDateRange), + dateRangeFrom, + dateRangeTo, + fingerprint, + autoRefreshFingerprint, ]); return ( @@ -124,7 +127,7 @@ const DashboardGDPRComponent: React.FC = () => { filters: fetchFilters ?? [], useMargins: true, id: 'gdpr-dashboard-tab', - timeRange: absoluteDateRange, + timeRange: { from: dateRangeFrom, to: dateRangeTo }, title: 'GDPR dashboard', description: 'Dashboard of the GDPR', query: searchBarProps.query, @@ -133,6 +136,7 @@ const DashboardGDPRComponent: React.FC = () => { value: 15, }, hidePanelTitles: false, + lastReloadRequestTime: fingerprint, }} /> diff --git a/plugins/main/public/components/overview/github/dashboards/dashboard.tsx b/plugins/main/public/components/overview/github/dashboards/dashboard.tsx index 393def651b..90a37518e6 100644 --- a/plugins/main/public/components/overview/github/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/github/dashboards/dashboard.tsx @@ -47,13 +47,13 @@ const DashboardGitHubComponent: React.FC = () => { }); const [results, setResults] = useState({} as SearchResponse); - const { searchBarProps } = useSearchBar({ + const { searchBarProps, fingerprint, autoRefreshFingerprint } = useSearchBar({ indexPattern: dataSource?.indexPattern as IndexPattern, filters, setFilters, }); - const { query, absoluteDateRange } = searchBarProps; + const { query, dateRangeFrom, dateRangeTo } = searchBarProps; useReportingCommunicateSearchContext({ isSearching: isDataSourceLoading, @@ -61,7 +61,7 @@ const DashboardGitHubComponent: React.FC = () => { indexPattern: dataSource?.indexPattern, filters: fetchFilters, query: query, - time: absoluteDateRange, + time: { from: dateRangeFrom, to: dateRangeTo }, }); useEffect(() => { @@ -70,7 +70,7 @@ const DashboardGitHubComponent: React.FC = () => { } fetchData({ query, - dateRange: absoluteDateRange, + dateRange: { from: dateRangeFrom, to: dateRangeTo }, }) .then(results => { setResults(results); @@ -85,7 +85,10 @@ const DashboardGitHubComponent: React.FC = () => { }, [ JSON.stringify(fetchFilters), JSON.stringify(query), - JSON.stringify(absoluteDateRange), + dateRangeFrom, + dateRangeTo, + fingerprint, + autoRefreshFingerprint, ]); return ( @@ -124,7 +127,7 @@ const DashboardGitHubComponent: React.FC = () => { filters: fetchFilters ?? [], useMargins: true, id: 'github-dashboard-tab', - timeRange: absoluteDateRange, + timeRange: { from: dateRangeFrom, to: dateRangeTo }, title: 'GitHub dashboard', description: 'Dashboard of the GitHub', query: searchBarProps.query, @@ -133,6 +136,7 @@ const DashboardGitHubComponent: React.FC = () => { value: 15, }, hidePanelTitles: false, + lastReloadRequestTime: fingerprint, }} /> diff --git a/plugins/main/public/components/overview/github/panel/config/drilldown-action.tsx b/plugins/main/public/components/overview/github/panel/config/drilldown-action.tsx index e711a36fc6..d5e571faa5 100644 --- a/plugins/main/public/components/overview/github/panel/config/drilldown-action.tsx +++ b/plugins/main/public/components/overview/github/panel/config/drilldown-action.tsx @@ -129,7 +129,10 @@ export const DrilldownConfigAction = (drilldownProps: ModuleConfigProps) => { filters: fetchFilters ?? [], useMargins: true, id: 'github-drilldown-action-dashboard-tab', - timeRange: searchBarProps?.absoluteDateRange, + timeRange: { + from: searchBarProps.dateRangeFrom, + to: searchBarProps.dateRangeTo, + }, title: 'GitHub drilldown action dashboard', description: 'Dashboard of the GitHub drilldown action', query: searchBarProps.query, diff --git a/plugins/main/public/components/overview/github/panel/config/drilldown-actor.tsx b/plugins/main/public/components/overview/github/panel/config/drilldown-actor.tsx index 6bcede34dc..42cb7381b8 100644 --- a/plugins/main/public/components/overview/github/panel/config/drilldown-actor.tsx +++ b/plugins/main/public/components/overview/github/panel/config/drilldown-actor.tsx @@ -129,7 +129,10 @@ export const DrilldownConfigActor = (drilldownProps: ModuleConfigProps) => { filters: fetchFilters ?? [], useMargins: true, id: 'github-drilldown-action-dashboard-tab', - timeRange: searchBarProps?.absoluteDateRange, + timeRange: { + from: searchBarProps.dateRangeFrom, + to: searchBarProps.dateRangeTo, + }, title: 'GitHub drilldown action dashboard', description: 'Dashboard of the GitHub drilldown action', query: searchBarProps.query, diff --git a/plugins/main/public/components/overview/github/panel/config/drilldown-organization.tsx b/plugins/main/public/components/overview/github/panel/config/drilldown-organization.tsx index 6cdac16307..ece1caad00 100644 --- a/plugins/main/public/components/overview/github/panel/config/drilldown-organization.tsx +++ b/plugins/main/public/components/overview/github/panel/config/drilldown-organization.tsx @@ -131,7 +131,10 @@ export const DrilldownConfigOrganization = ( filters: fetchFilters ?? [], useMargins: true, id: 'github-drilldown-action-dashboard-tab', - timeRange: searchBarProps?.absoluteDateRange, + timeRange: { + from: searchBarProps.dateRangeFrom, + to: searchBarProps.dateRangeTo, + }, title: 'GitHub drilldown action dashboard', description: 'Dashboard of the GitHub drilldown action', query: searchBarProps.query, diff --git a/plugins/main/public/components/overview/github/panel/config/drilldown-repository.tsx b/plugins/main/public/components/overview/github/panel/config/drilldown-repository.tsx index c2a5e01a92..28bf58517e 100644 --- a/plugins/main/public/components/overview/github/panel/config/drilldown-repository.tsx +++ b/plugins/main/public/components/overview/github/panel/config/drilldown-repository.tsx @@ -131,7 +131,10 @@ export const DrilldownConfigRepository = ( filters: fetchFilters ?? [], useMargins: true, id: 'github-drilldown-action-dashboard-tab', - timeRange: searchBarProps?.absoluteDateRange, + timeRange: { + from: searchBarProps.dateRangeFrom, + to: searchBarProps.dateRangeTo, + }, title: 'GitHub drilldown action dashboard', description: 'Dashboard of the GitHub drilldown action', query: searchBarProps.query, diff --git a/plugins/main/public/components/overview/google-cloud/dashboards/dashboard.tsx b/plugins/main/public/components/overview/google-cloud/dashboards/dashboard.tsx index 1566f0d965..630bfb4c74 100644 --- a/plugins/main/public/components/overview/google-cloud/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/google-cloud/dashboards/dashboard.tsx @@ -47,13 +47,13 @@ const DashboardGoogleCloudComponent: React.FC = () => { const [results, setResults] = useState({} as SearchResponse); - const { searchBarProps } = useSearchBar({ + const { searchBarProps, fingerprint, autoRefreshFingerprint } = useSearchBar({ indexPattern: dataSource?.indexPattern as IndexPattern, filters, setFilters, }); - const { query, absoluteDateRange } = searchBarProps; + const { query, dateRangeFrom, dateRangeTo } = searchBarProps; useReportingCommunicateSearchContext({ isSearching: isDataSourceLoading, @@ -61,7 +61,7 @@ const DashboardGoogleCloudComponent: React.FC = () => { indexPattern: dataSource?.indexPattern, filters: fetchFilters, query: query, - time: absoluteDateRange, + time: { from: dateRangeFrom, to: dateRangeTo }, }); useEffect(() => { @@ -70,7 +70,7 @@ const DashboardGoogleCloudComponent: React.FC = () => { } fetchData({ query, - dateRange: absoluteDateRange, + dateRange: { from: dateRangeFrom, to: dateRangeTo }, }) .then(results => setResults(results)) .catch(error => { @@ -83,7 +83,10 @@ const DashboardGoogleCloudComponent: React.FC = () => { }, [ JSON.stringify(fetchFilters), JSON.stringify(query), - JSON.stringify(absoluteDateRange), + dateRangeFrom, + dateRangeTo, + fingerprint, + autoRefreshFingerprint, ]); return ( @@ -123,7 +126,7 @@ const DashboardGoogleCloudComponent: React.FC = () => { filters: fetchFilters ?? [], useMargins: true, id: 'google-cloud-detector-dashboard-tab', - timeRange: absoluteDateRange, + timeRange: { from: dateRangeFrom, to: dateRangeTo }, title: 'Google Cloud detector dashboard', description: 'Dashboard of the Google Cloud', query: searchBarProps.query, @@ -132,6 +135,7 @@ const DashboardGoogleCloudComponent: React.FC = () => { value: 15, }, hidePanelTitles: false, + lastReloadRequestTime: fingerprint, }} /> diff --git a/plugins/main/public/components/overview/hipaa/dashboards/dashboard.tsx b/plugins/main/public/components/overview/hipaa/dashboards/dashboard.tsx index 812b515537..7327d8bf44 100644 --- a/plugins/main/public/components/overview/hipaa/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/hipaa/dashboards/dashboard.tsx @@ -47,13 +47,13 @@ const DashboardHIPAAComponent: React.FC = () => { }); const [results, setResults] = useState({} as SearchResponse); - const { searchBarProps } = useSearchBar({ + const { searchBarProps, fingerprint, autoRefreshFingerprint } = useSearchBar({ indexPattern: dataSource?.indexPattern as IndexPattern, filters, setFilters, }); - const { query, absoluteDateRange } = searchBarProps; + const { query, dateRangeFrom, dateRangeTo } = searchBarProps; useReportingCommunicateSearchContext({ isSearching: isDataSourceLoading, @@ -61,7 +61,7 @@ const DashboardHIPAAComponent: React.FC = () => { indexPattern: dataSource?.indexPattern, filters: fetchFilters, query: query, - time: absoluteDateRange, + time: { from: dateRangeFrom, to: dateRangeTo }, }); useEffect(() => { @@ -70,7 +70,7 @@ const DashboardHIPAAComponent: React.FC = () => { } fetchData({ query, - dateRange: absoluteDateRange, + dateRange: { from: dateRangeFrom, to: dateRangeTo }, }) .then(results => { setResults(results); @@ -85,7 +85,10 @@ const DashboardHIPAAComponent: React.FC = () => { }, [ JSON.stringify(fetchFilters), JSON.stringify(query), - JSON.stringify(absoluteDateRange), + dateRangeFrom, + dateRangeTo, + fingerprint, + autoRefreshFingerprint, ]); return ( @@ -124,7 +127,7 @@ const DashboardHIPAAComponent: React.FC = () => { filters: fetchFilters ?? [], useMargins: true, id: 'hipaa-dashboard-tab', - timeRange: absoluteDateRange, + timeRange: { from: dateRangeFrom, to: dateRangeTo }, title: 'HIPAA dashboard', description: 'Dashboard of the HIPAA', query: searchBarProps.query, @@ -133,6 +136,7 @@ const DashboardHIPAAComponent: React.FC = () => { value: 15, }, hidePanelTitles: false, + lastReloadRequestTime: fingerprint, }} /> diff --git a/plugins/main/public/components/overview/malware-detection/dashboard/dashboard.tsx b/plugins/main/public/components/overview/malware-detection/dashboard/dashboard.tsx index 8d5b4b12df..37a60ea493 100644 --- a/plugins/main/public/components/overview/malware-detection/dashboard/dashboard.tsx +++ b/plugins/main/public/components/overview/malware-detection/dashboard/dashboard.tsx @@ -48,13 +48,13 @@ const DashboardMalwareDetectionComponent: React.FC = ({}) => { const [results, setResults] = useState({} as SearchResponse); - const { searchBarProps } = useSearchBar({ + const { searchBarProps, fingerprint, autoRefreshFingerprint } = useSearchBar({ indexPattern: dataSource?.indexPattern as IndexPattern, filters, setFilters, }); - const { query, absoluteDateRange } = searchBarProps; + const { query, dateRangeFrom, dateRangeTo } = searchBarProps; useReportingCommunicateSearchContext({ isSearching: isDataSourceLoading, @@ -62,7 +62,7 @@ const DashboardMalwareDetectionComponent: React.FC = ({}) => { indexPattern: dataSource?.indexPattern, filters: fetchFilters, query: query, - time: absoluteDateRange, + time: { from: dateRangeFrom, to: dateRangeTo }, }); useEffect(() => { @@ -71,7 +71,7 @@ const DashboardMalwareDetectionComponent: React.FC = ({}) => { } fetchData({ query, - dateRange: absoluteDateRange, + dateRange: { from: dateRangeFrom, to: dateRangeTo }, }) .then(results => setResults(results)) .catch(error => { @@ -84,7 +84,10 @@ const DashboardMalwareDetectionComponent: React.FC = ({}) => { }, [ JSON.stringify(fetchFilters), JSON.stringify(query), - JSON.stringify(absoluteDateRange), + dateRangeFrom, + dateRangeTo, + fingerprint, + autoRefreshFingerprint, ]); return ( @@ -125,7 +128,7 @@ const DashboardMalwareDetectionComponent: React.FC = ({}) => { filters: fetchFilters ?? [], useMargins: true, id: 'malware-detection-dashboard-tab', - timeRange: absoluteDateRange, + timeRange: { from: dateRangeFrom, to: dateRangeTo }, title: 'Malware Detection dashboard', description: 'Dashboard of the Malware Detection', query: query, @@ -134,6 +137,7 @@ const DashboardMalwareDetectionComponent: React.FC = ({}) => { value: 15, }, hidePanelTitles: false, + lastReloadRequestTime: fingerprint, }} /> diff --git a/plugins/main/public/components/overview/mitre/dashboard/dashboard.tsx b/plugins/main/public/components/overview/mitre/dashboard/dashboard.tsx index deaf0f5056..3d4fb28912 100644 --- a/plugins/main/public/components/overview/mitre/dashboard/dashboard.tsx +++ b/plugins/main/public/components/overview/mitre/dashboard/dashboard.tsx @@ -45,12 +45,12 @@ export const DashboardMITRE: React.FC = () => { const [results, setResults] = useState({} as SearchResponse); - const { searchBarProps } = useSearchBar({ + const { searchBarProps, fingerprint, autoRefreshFingerprint } = useSearchBar({ indexPattern: dataSource?.indexPattern as IndexPattern, filters, setFilters, }); - const { query, absoluteDateRange } = searchBarProps; + const { query, dateRangeFrom, dateRangeTo } = searchBarProps; useReportingCommunicateSearchContext({ isSearching: isDataSourceLoading, @@ -58,7 +58,7 @@ export const DashboardMITRE: React.FC = () => { indexPattern: dataSource?.indexPattern, filters: fetchFilters, query: query, - time: absoluteDateRange, + time: { from: dateRangeFrom, to: dateRangeTo }, }); useEffect(() => { @@ -67,7 +67,7 @@ export const DashboardMITRE: React.FC = () => { } fetchData({ query, - dateRange: absoluteDateRange, + dateRange: { from: dateRangeFrom, to: dateRangeTo }, }) .then(results => { setResults(results); @@ -82,7 +82,10 @@ export const DashboardMITRE: React.FC = () => { }, [ JSON.stringify(fetchFilters), JSON.stringify(query), - JSON.stringify(absoluteDateRange), + dateRangeFrom, + dateRangeTo, + fingerprint, + autoRefreshFingerprint, ]); return ( @@ -121,7 +124,7 @@ export const DashboardMITRE: React.FC = () => { filters: fetchFilters ?? [], useMargins: true, id: 'mitre-dashboard-tab-filters', - timeRange: absoluteDateRange, + timeRange: { from: dateRangeFrom, to: dateRangeTo }, title: 'MITRE dashboard filters', description: 'Dashboard of the MITRE filters', query: query, @@ -130,6 +133,7 @@ export const DashboardMITRE: React.FC = () => { value: 15, }, hidePanelTitles: false, + lastReloadRequestTime: fingerprint, }} /> diff --git a/plugins/main/public/components/overview/mitre/framework/mitre.tsx b/plugins/main/public/components/overview/mitre/framework/mitre.tsx index 9a37658387..7ed5f4aee0 100644 --- a/plugins/main/public/components/overview/mitre/framework/mitre.tsx +++ b/plugins/main/public/components/overview/mitre/framework/mitre.tsx @@ -68,13 +68,13 @@ const MitreComponent = props => { repository: new AlertsDataSourceRepository(), }); - const { searchBarProps } = useSearchBar({ + const { searchBarProps, fingerprint, autoRefreshFingerprint } = useSearchBar({ indexPattern: dataSource?.indexPattern as IndexPattern, filters, setFilters: setFilters, }); - const { absoluteDateRange } = searchBarProps; + const { dateRangeFrom, dateRangeTo } = searchBarProps; const [mitreState, setMitreState] = useState({ tacticsObject: {}, selectedTactics: {}, @@ -83,7 +83,10 @@ const MitreComponent = props => { const [filterParams, setFilterParams] = useState({ filters: fetchFilters, query: searchBarProps?.query, - time: absoluteDateRange, + time: { + from: dateRangeFrom, + to: dateRangeTo, + }, }); const [indexPattern, setIndexPattern] = useState(); //Todo: Add correct type const [isLoading, setIsLoading] = useState(true); @@ -93,7 +96,10 @@ const MitreComponent = props => { let filterParams = { filters: fetchFilters, // pass the fetchFilters to use it as initial filters in the technique flyout query: searchBarProps?.query, - time: absoluteDateRange, + time: { + from: dateRangeFrom, + to: dateRangeTo, + }, }; setFilterParams(filterParams); setIsLoading(true); @@ -108,7 +114,10 @@ const MitreComponent = props => { dataSource, searchBarProps.query, JSON.stringify(filters), - JSON.stringify(absoluteDateRange), + dateRangeFrom, + dateRangeTo, + fingerprint, + autoRefreshFingerprint, ]); const buildTacticsObject = async () => { diff --git a/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx b/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx index 017efa65f3..8f22366375 100644 --- a/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx @@ -47,13 +47,13 @@ const DashboardNIST80053Component: React.FC = () => { }); const [results, setResults] = useState({} as SearchResponse); - const { searchBarProps } = useSearchBar({ + const { searchBarProps, fingerprint, autoRefreshFingerprint } = useSearchBar({ indexPattern: dataSource?.indexPattern as IndexPattern, filters, setFilters, }); - const { query, absoluteDateRange } = searchBarProps; + const { query, dateRangeFrom, dateRangeTo } = searchBarProps; useReportingCommunicateSearchContext({ isSearching: isDataSourceLoading, @@ -61,7 +61,7 @@ const DashboardNIST80053Component: React.FC = () => { indexPattern: dataSource?.indexPattern, filters: fetchFilters, query: query, - time: absoluteDateRange, + time: { from: dateRangeFrom, to: dateRangeTo }, }); useEffect(() => { @@ -70,7 +70,7 @@ const DashboardNIST80053Component: React.FC = () => { } fetchData({ query, - dateRange: absoluteDateRange, + dateRange: { from: dateRangeFrom, to: dateRangeTo }, }) .then(results => { setResults(results); @@ -85,7 +85,10 @@ const DashboardNIST80053Component: React.FC = () => { }, [ JSON.stringify(fetchFilters), JSON.stringify(query), - JSON.stringify(absoluteDateRange), + dateRangeFrom, + dateRangeTo, + fingerprint, + autoRefreshFingerprint, ]); return ( @@ -124,7 +127,7 @@ const DashboardNIST80053Component: React.FC = () => { filters: fetchFilters ?? [], useMargins: true, id: 'nist-dashboard-tab', - timeRange: absoluteDateRange, + timeRange: { from: dateRangeFrom, to: dateRangeTo }, title: 'NIST 800-53 dashboard', description: 'Dashboard of the NIST 800-53', query: searchBarProps.query, @@ -133,6 +136,7 @@ const DashboardNIST80053Component: React.FC = () => { value: 15, }, hidePanelTitles: false, + lastReloadRequestTime: fingerprint, }} /> diff --git a/plugins/main/public/components/overview/office/dashboard/dashboard.tsx b/plugins/main/public/components/overview/office/dashboard/dashboard.tsx index b3b48d1e5b..c95b9bb26a 100644 --- a/plugins/main/public/components/overview/office/dashboard/dashboard.tsx +++ b/plugins/main/public/components/overview/office/dashboard/dashboard.tsx @@ -47,12 +47,12 @@ const DashboardOffice365Component: React.FC = () => { }); const [results, setResults] = useState({} as SearchResponse); - const { searchBarProps } = useSearchBar({ + const { searchBarProps, fingerprint, autoRefreshFingerprint } = useSearchBar({ indexPattern: dataSource?.indexPattern as IndexPattern, filters, setFilters, }); - const { query, absoluteDateRange } = searchBarProps; + const { query, dateRangeFrom, dateRangeTo } = searchBarProps; useReportingCommunicateSearchContext({ isSearching: isDataSourceLoading, @@ -60,7 +60,7 @@ const DashboardOffice365Component: React.FC = () => { indexPattern: dataSource?.indexPattern, filters: fetchFilters, query: query, - time: absoluteDateRange, + time: { from: dateRangeFrom, to: dateRangeTo }, }); useEffect(() => { @@ -69,7 +69,7 @@ const DashboardOffice365Component: React.FC = () => { } fetchData({ query, - dateRange: absoluteDateRange, + dateRange: { from: dateRangeFrom, to: dateRangeTo }, }) .then(results => { setResults(results); @@ -84,7 +84,10 @@ const DashboardOffice365Component: React.FC = () => { }, [ JSON.stringify(fetchFilters), JSON.stringify(query), - JSON.stringify(absoluteDateRange), + dateRangeFrom, + dateRangeTo, + fingerprint, + autoRefreshFingerprint, ]); return ( @@ -123,7 +126,7 @@ const DashboardOffice365Component: React.FC = () => { filters: fetchFilters ?? [], useMargins: true, id: 'kpis-th-dashboard-tab', - timeRange: absoluteDateRange, + timeRange: { from: dateRangeFrom, to: dateRangeTo }, title: 'KPIs Office 365 dashboard', description: 'KPIs Dashboard of the Office 365', query: searchBarProps.query, @@ -132,6 +135,7 @@ const DashboardOffice365Component: React.FC = () => { value: 15, }, hidePanelTitles: true, + lastReloadRequestTime: fingerprint, }} /> { filters: fetchFilters ?? [], useMargins: true, id: 'office-365-detector-dashboard-tab', - timeRange: absoluteDateRange, + timeRange: { from: dateRangeFrom, to: dateRangeTo }, title: 'Office 365 detector dashboard', description: 'Dashboard of the Office 365', query: searchBarProps.query, @@ -153,6 +157,7 @@ const DashboardOffice365Component: React.FC = () => { value: 15, }, hidePanelTitles: false, + lastReloadRequestTime: fingerprint, }} /> diff --git a/plugins/main/public/components/overview/overview.tsx b/plugins/main/public/components/overview/overview.tsx index 12476ad0a7..03f236f705 100644 --- a/plugins/main/public/components/overview/overview.tsx +++ b/plugins/main/public/components/overview/overview.tsx @@ -4,7 +4,10 @@ import { Stats } from '../../controllers/overview/components/stats'; import { AppState, WzRequest } from '../../react-services'; import { OverviewWelcome } from '../common/welcome/overview-welcome'; import { MainModule } from '../common/modules/main'; -import { OSD_URL_STATE_STORAGE_ID } from '../../../common/constants'; +import { + APP_STATE_URL_KEY, + OSD_URL_STATE_STORAGE_ID, +} from '../../../common/constants'; import { WzCurrentOverviewSectionWrapper } from '../common/modules/overview-current-section-wrapper'; import { connectToQueryState, @@ -56,7 +59,9 @@ export const Overview: React.FC = withRouteResolvers({ history: history, }); - const appStateFromUrl = osdUrlStateStorage.get('_a') as AppState; + const appStateFromUrl = osdUrlStateStorage.get( + APP_STATE_URL_KEY, + ) as AppState; let initialAppState = { query: migrateLegacyQuery(data.query.queryString.getDefaultQuery()), ...appStateFromUrl, @@ -73,11 +78,11 @@ export const Overview: React.FC = withRouteResolvers({ const replaceUrlAppState = async (newPartial: AppState = {}) => { const state = { ...appStateContainer.getState(), ...newPartial }; - await osdUrlStateStorage.set('_a', state, { replace: true }); + await osdUrlStateStorage.set(APP_STATE_URL_KEY, state, { replace: true }); }; const { start, stop } = syncState({ - storageKey: '_a', + storageKey: APP_STATE_URL_KEY, stateContainer: appStateContainerModified, stateStorage: osdUrlStateStorage, }); diff --git a/plugins/main/public/components/overview/pci/dashboards/dashboard.tsx b/plugins/main/public/components/overview/pci/dashboards/dashboard.tsx index 64305d0b5c..c13e878cc4 100644 --- a/plugins/main/public/components/overview/pci/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/pci/dashboards/dashboard.tsx @@ -48,13 +48,13 @@ const DashboardPCIDSSComponent: React.FC = () => { const [results, setResults] = useState({} as SearchResponse); - const { searchBarProps } = useSearchBar({ + const { searchBarProps, fingerprint, autoRefreshFingerprint } = useSearchBar({ indexPattern: dataSource?.indexPattern as IndexPattern, filters, setFilters, }); - const { query, absoluteDateRange } = searchBarProps; + const { query, dateRangeFrom, dateRangeTo } = searchBarProps; useReportingCommunicateSearchContext({ isSearching: isDataSourceLoading, @@ -62,7 +62,7 @@ const DashboardPCIDSSComponent: React.FC = () => { indexPattern: dataSource?.indexPattern, filters: fetchFilters, query: query, - time: absoluteDateRange, + time: { from: dateRangeFrom, to: dateRangeTo }, }); useEffect(() => { @@ -71,7 +71,7 @@ const DashboardPCIDSSComponent: React.FC = () => { } fetchData({ query, - dateRange: absoluteDateRange, + dateRange: { from: dateRangeFrom, to: dateRangeTo }, }) .then(results => { setResults(results); @@ -86,7 +86,10 @@ const DashboardPCIDSSComponent: React.FC = () => { }, [ JSON.stringify(fetchFilters), JSON.stringify(query), - JSON.stringify(absoluteDateRange), + dateRangeFrom, + dateRangeTo, + fingerprint, + autoRefreshFingerprint, ]); return ( @@ -125,7 +128,7 @@ const DashboardPCIDSSComponent: React.FC = () => { filters: fetchFilters ?? [], useMargins: true, id: 'pci-dss-dashboard-tab', - timeRange: absoluteDateRange, + timeRange: { from: dateRangeFrom, to: dateRangeTo }, title: 'PCI DSS dashboard', description: 'Dashboard of the PCI DSS', query: searchBarProps.query, @@ -134,6 +137,7 @@ const DashboardPCIDSSComponent: React.FC = () => { value: 15, }, hidePanelTitles: false, + lastReloadRequestTime: fingerprint, }} /> diff --git a/plugins/main/public/components/overview/server-management-statistics/dashboards/dashboardTabsPanels.tsx b/plugins/main/public/components/overview/server-management-statistics/dashboards/dashboardTabsPanels.tsx index b261d69619..ad78f306d1 100644 --- a/plugins/main/public/components/overview/server-management-statistics/dashboards/dashboardTabsPanels.tsx +++ b/plugins/main/public/components/overview/server-management-statistics/dashboards/dashboardTabsPanels.tsx @@ -72,13 +72,13 @@ export const DashboardTabsPanels = ({ "Analysisd statistics refer to the data stored from the period indicated in the variable 'analysisd.state_interval'.", }; - const { searchBarProps } = useSearchBar({ + const { searchBarProps, fingerprint, autoRefreshFingerprint } = useSearchBar({ indexPattern: dataSource?.indexPattern as IndexPattern, filters, setFilters, }); - const { query, absoluteDateRange } = searchBarProps; + const { query, dateRangeFrom, dateRangeTo } = searchBarProps; useEffect(() => { if (isDataSourceLoading) { @@ -86,7 +86,10 @@ export const DashboardTabsPanels = ({ } fetchData({ query, - dateRange: absoluteDateRange, + dateRange: { + from: dateRangeFrom, + to: dateRangeTo, + }, }) .then(results => { setResults(results); @@ -101,7 +104,10 @@ export const DashboardTabsPanels = ({ }, [ JSON.stringify(fetchFilters), JSON.stringify(query), - JSON.stringify(absoluteDateRange), + dateRangeFrom, + dateRangeTo, + fingerprint, + autoRefreshFingerprint, ]); const selectedNodeFilter: tFilter = { @@ -168,6 +174,7 @@ export const DashboardTabsPanels = ({ = ({ @@ -22,6 +23,7 @@ const DashboardStatistics: React.FC = ({ indexPatternId, filters, searchBarProps, + lastReloadRequestTime, }) => { return (
@@ -48,6 +50,7 @@ const DashboardStatistics: React.FC = ({ value: 15, }, hidePanelTitles: false, + lastReloadRequestTime, }} />
diff --git a/plugins/main/public/components/overview/server-management-statistics/dashboards/dashboard_listener_engine.tsx b/plugins/main/public/components/overview/server-management-statistics/dashboards/dashboard_listener_engine.tsx index 8396e180f8..0ba50b68c7 100644 --- a/plugins/main/public/components/overview/server-management-statistics/dashboards/dashboard_listener_engine.tsx +++ b/plugins/main/public/components/overview/server-management-statistics/dashboards/dashboard_listener_engine.tsx @@ -14,12 +14,14 @@ interface DashboardStatisticsProps { indexPatternId: string; filters: tFilter[]; searchBarProps: any; + lastReloadRequestTime: number; } const DashboardStatistics: React.FC = ({ indexPatternId, filters, searchBarProps, + lastReloadRequestTime, }) => { return (
@@ -43,6 +45,7 @@ const DashboardStatistics: React.FC = ({ value: 15, }, hidePanelTitles: false, + lastReloadRequestTime, }} />
diff --git a/plugins/main/public/components/overview/threat-hunting/dashboard/dashboard.tsx b/plugins/main/public/components/overview/threat-hunting/dashboard/dashboard.tsx index bad298ebfa..6ab8a40b54 100644 --- a/plugins/main/public/components/overview/threat-hunting/dashboard/dashboard.tsx +++ b/plugins/main/public/components/overview/threat-hunting/dashboard/dashboard.tsx @@ -48,12 +48,12 @@ const DashboardTH: React.FC = () => { }); const [results, setResults] = useState({} as SearchResponse); - const { searchBarProps } = useSearchBar({ + const { searchBarProps, fingerprint, autoRefreshFingerprint } = useSearchBar({ indexPattern: dataSource?.indexPattern as IndexPattern, filters, setFilters, }); - const { query, absoluteDateRange } = searchBarProps; + const { query, dateRangeFrom, dateRangeTo } = searchBarProps; const pinnedAgent = PatternDataSourceFilterManager.getPinnedAgentFilter(dataSource?.id!) .length > 0; @@ -64,7 +64,7 @@ const DashboardTH: React.FC = () => { indexPattern: dataSource?.indexPattern as IndexPattern, filters: fetchFilters, query: query, - time: absoluteDateRange, + time: { from: dateRangeFrom, to: dateRangeTo }, }); useEffect(() => { @@ -73,7 +73,7 @@ const DashboardTH: React.FC = () => { } fetchData({ query, - dateRange: absoluteDateRange, + dateRange: { from: dateRangeFrom, to: dateRangeTo }, }) .then(results => { setResults(results); @@ -88,7 +88,10 @@ const DashboardTH: React.FC = () => { }, [ JSON.stringify(fetchFilters), JSON.stringify(query), - JSON.stringify(absoluteDateRange), + dateRangeFrom, + dateRangeTo, + autoRefreshFingerprint, + fingerprint, ]); return ( @@ -128,7 +131,7 @@ const DashboardTH: React.FC = () => { filters: fetchFilters ?? [], useMargins: true, id: 'kpis-th-dashboard-tab', - timeRange: absoluteDateRange, + timeRange: { from: dateRangeFrom, to: dateRangeTo }, title: 'KPIs Threat Hunting dashboard', description: 'KPIs Dashboard of the Threat Hunting', query: query, @@ -137,6 +140,7 @@ const DashboardTH: React.FC = () => { value: 15, }, hidePanelTitles: true, + lastReloadRequestTime: fingerprint, }} /> { filters: fetchFilters ?? [], useMargins: true, id: 'th-dashboard-tab', - timeRange: absoluteDateRange, + timeRange: { from: dateRangeFrom, to: dateRangeTo }, title: 'Threat Hunting dashboard', description: 'Dashboard of the Threat Hunting', query: query, @@ -159,6 +163,7 @@ const DashboardTH: React.FC = () => { value: 15, }, hidePanelTitles: false, + lastReloadRequestTime: fingerprint, }} /> diff --git a/plugins/main/public/components/overview/tsc/dashboards/dashboard.tsx b/plugins/main/public/components/overview/tsc/dashboards/dashboard.tsx index dfb3da8ee1..0d931901d6 100644 --- a/plugins/main/public/components/overview/tsc/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/tsc/dashboards/dashboard.tsx @@ -47,13 +47,13 @@ const DashboardTSCComponent: React.FC = () => { }); const [results, setResults] = useState({} as SearchResponse); - const { searchBarProps } = useSearchBar({ + const { searchBarProps, fingerprint, autoRefreshFingerprint } = useSearchBar({ indexPattern: dataSource?.indexPattern as IndexPattern, filters, setFilters, }); - const { query, absoluteDateRange } = searchBarProps; + const { query, dateRangeFrom, dateRangeTo } = searchBarProps; useReportingCommunicateSearchContext({ isSearching: isDataSourceLoading, @@ -61,7 +61,7 @@ const DashboardTSCComponent: React.FC = () => { indexPattern: dataSource?.indexPattern, filters: fetchFilters, query: query, - time: absoluteDateRange, + time: { from: dateRangeFrom, to: dateRangeTo }, }); useEffect(() => { @@ -70,7 +70,7 @@ const DashboardTSCComponent: React.FC = () => { } fetchData({ query, - dateRange: absoluteDateRange, + dateRange: { from: dateRangeFrom, to: dateRangeTo }, }) .then(results => { setResults(results); @@ -85,7 +85,10 @@ const DashboardTSCComponent: React.FC = () => { }, [ JSON.stringify(fetchFilters), JSON.stringify(query), - JSON.stringify(absoluteDateRange), + dateRangeFrom, + dateRangeTo, + fingerprint, + autoRefreshFingerprint, ]); return ( @@ -124,7 +127,7 @@ const DashboardTSCComponent: React.FC = () => { filters: fetchFilters ?? [], useMargins: true, id: 'tsc-dashboard-tab', - timeRange: absoluteDateRange, + timeRange: { from: dateRangeFrom, to: dateRangeTo }, title: 'TSC dashboard', description: 'Dashboard of the TSC', query: searchBarProps.query, @@ -133,6 +136,7 @@ const DashboardTSCComponent: React.FC = () => { value: 15, }, hidePanelTitles: false, + lastReloadRequestTime: fingerprint, }} /> diff --git a/plugins/main/public/components/overview/virustotal/dashboard/dashboard.tsx b/plugins/main/public/components/overview/virustotal/dashboard/dashboard.tsx index 29cf0cff74..4d9953f7c7 100644 --- a/plugins/main/public/components/overview/virustotal/dashboard/dashboard.tsx +++ b/plugins/main/public/components/overview/virustotal/dashboard/dashboard.tsx @@ -48,12 +48,12 @@ const DashboardVT: React.FC = () => { const [results, setResults] = useState({} as SearchResponse); - const { searchBarProps } = useSearchBar({ + const { searchBarProps, fingerprint, autoRefreshFingerprint } = useSearchBar({ indexPattern: dataSource?.indexPattern as IndexPattern, filters, setFilters, }); - const { query, absoluteDateRange } = searchBarProps; + const { query, dateRangeFrom, dateRangeTo } = searchBarProps; useReportingCommunicateSearchContext({ isSearching: isDataSourceLoading, @@ -61,7 +61,7 @@ const DashboardVT: React.FC = () => { indexPattern: dataSource?.indexPattern, filters: fetchFilters, query: query, - time: absoluteDateRange, + time: { from: dateRangeFrom, to: dateRangeTo }, }); useEffect(() => { @@ -70,7 +70,7 @@ const DashboardVT: React.FC = () => { } fetchData({ query, - dateRange: absoluteDateRange, + dateRange: { from: dateRangeFrom, to: dateRangeTo }, }) .then(results => { setResults(results); @@ -86,7 +86,10 @@ const DashboardVT: React.FC = () => { isDataSourceLoading, JSON.stringify(fetchFilters), JSON.stringify(query), - JSON.stringify(absoluteDateRange), + dateRangeFrom, + dateRangeTo, + fingerprint, + autoRefreshFingerprint, ]); return ( @@ -125,7 +128,7 @@ const DashboardVT: React.FC = () => { filters: fetchFilters ?? [], useMargins: true, id: 'kpis-virustotal-dashboard-tab', - timeRange: absoluteDateRange, + timeRange: { from: dateRangeFrom, to: dateRangeTo }, title: 'KPIs Virustotal dashboard', description: 'KPIs Dashboard of the Virustotal', query: query, @@ -134,6 +137,7 @@ const DashboardVT: React.FC = () => { value: 15, }, hidePanelTitles: true, + lastReloadRequestTime: fingerprint, }} /> { filters: fetchFilters ?? [], useMargins: true, id: 'virustotal-dashboard-tab', - timeRange: absoluteDateRange, + timeRange: { from: dateRangeFrom, to: dateRangeTo }, title: 'Virustotal dashboard', description: 'Dashboard of the Virustotal', query: query, @@ -156,6 +160,7 @@ const DashboardVT: React.FC = () => { value: 15, }, hidePanelTitles: false, + lastReloadRequestTime: fingerprint, }} /> diff --git a/plugins/main/public/components/overview/vulnerabilities/dashboards/inventory/inventory.tsx b/plugins/main/public/components/overview/vulnerabilities/dashboards/inventory/inventory.tsx index ecef54dd3a..130892fd14 100644 --- a/plugins/main/public/components/overview/vulnerabilities/dashboards/inventory/inventory.tsx +++ b/plugins/main/public/components/overview/vulnerabilities/dashboards/inventory/inventory.tsx @@ -65,7 +65,7 @@ const InventoryVulsComponent = () => { DataSource: VulnerabilitiesDataSource, repository: new VulnerabilitiesDataSourceRepository(), }); - const { searchBarProps } = useSearchBar({ + const { searchBarProps, fingerprint } = useSearchBar({ indexPattern: dataSource?.indexPattern as IndexPattern, filters, setFilters, @@ -169,6 +169,7 @@ const InventoryVulsComponent = () => { JSON.stringify(query), JSON.stringify(pagination), JSON.stringify(sorting), + fingerprint, ]); return ( diff --git a/plugins/main/public/components/overview/vulnerabilities/dashboards/overview/dashboard.tsx b/plugins/main/public/components/overview/vulnerabilities/dashboards/overview/dashboard.tsx index 2ea3d9846f..49733f23bb 100644 --- a/plugins/main/public/components/overview/vulnerabilities/dashboards/overview/dashboard.tsx +++ b/plugins/main/public/components/overview/vulnerabilities/dashboards/overview/dashboard.tsx @@ -59,7 +59,7 @@ const DashboardVulsComponent: React.FC = ({ const [results, setResults] = useState({} as SearchResponse); - const { searchBarProps } = useSearchBar({ + const { searchBarProps, fingerprint } = useSearchBar({ indexPattern: dataSource?.indexPattern as IndexPattern, filters, setFilters, @@ -91,108 +91,116 @@ const DashboardVulsComponent: React.FC = ({ {isDataSourceLoading && !dataSource ? ( ) : ( - - )} - {dataSource && results?.hits?.total === 0 ? ( - - ) : null} -
0 ? '' : 'wz-no-display' - }`} - > - -
- + -
- -
+ + {dataSource && results?.hits?.total === 0 ? ( + + ) : null} +
0 ? '' : 'wz-no-display' + }`} + > + +
+ +
+ +
+ + )}
diff --git a/plugins/main/public/controllers/management/components/management/common/resources-handler.ts b/plugins/main/public/controllers/management/components/management/common/resources-handler.ts index f0b57c0625..5832153eff 100644 --- a/plugins/main/public/controllers/management/components/management/common/resources-handler.ts +++ b/plugins/main/public/controllers/management/components/management/common/resources-handler.ts @@ -63,9 +63,8 @@ export class ResourcesHandler { /** * Get the content of any type of file Rules, Decoders, CDB lists... - * @param {String} fileName */ - async getFileContent(fileName, relativeDirname) { + async getFileContent(fileName: string, relativeDirname?: string) { try { const result: any = await WzRequest.apiReq( 'GET', diff --git a/plugins/main/public/kibana-services.ts b/plugins/main/public/kibana-services.ts index 1c536dc5e1..f8d96e0301 100644 --- a/plugins/main/public/kibana-services.ts +++ b/plugins/main/public/kibana-services.ts @@ -8,7 +8,7 @@ import { ScopedHistory, ToastsStart, AppMountParameters, -} from 'opensearch_dashboards/public'; +} from '../../../src/core/public'; import { createGetterSetter } from '../../../src/plugins/opensearch_dashboards_utils/common'; import { DataPublicPluginStart } from '../../../src/plugins/data/public'; import { VisualizationsStart } from '../../../src/plugins/visualizations/public'; diff --git a/plugins/main/public/react-services/index.ts b/plugins/main/public/react-services/index.ts index b09a1645a0..e04aaa8d42 100644 --- a/plugins/main/public/react-services/index.ts +++ b/plugins/main/public/react-services/index.ts @@ -21,3 +21,4 @@ export * from './wz-security-opensearch-dashboards-security'; export * from './wz-user-permissions'; export * from './query-config'; export * from './elastic_helpers'; +export * from './state-storage'; diff --git a/plugins/main/public/react-services/state-storage.ts b/plugins/main/public/react-services/state-storage.ts new file mode 100644 index 0000000000..d0ca3d63dc --- /dev/null +++ b/plugins/main/public/react-services/state-storage.ts @@ -0,0 +1,42 @@ +import { DataPublicPluginStart } from '../../../../src/plugins/data/public'; +import { + createStateContainer, + IOsdUrlStateStorage, + syncState as _syncState, +} from '../../../../src/plugins/opensearch_dashboards_utils/public'; +import { AppState } from './app-state'; +import { migrateLegacyQuery } from '../utils/migrate_legacy_query'; +import { APP_STATE_URL_KEY } from '../../common/constants'; + +const OsdUrlStateStorage = ( + data: DataPublicPluginStart, + osdUrlStateStorage: IOsdUrlStateStorage, +) => { + const getAppStateFromUrl = () => { + return osdUrlStateStorage.get(APP_STATE_URL_KEY) as AppState; + }; + + const getAppStateContainer = () => { + const defaultQuery = migrateLegacyQuery( + data.query.queryString.getDefaultQuery(), + ); + let initialAppState = { + query: defaultQuery, + ...getAppStateFromUrl(), + }; + return createStateContainer(initialAppState); + }; + + const replaceUrlAppState = async (newPartial: AppState = {}) => { + const state = { ...getAppStateContainer().getState(), ...newPartial }; + await osdUrlStateStorage.set(APP_STATE_URL_KEY, state, { replace: true }); + }; + + return { + getAppStateFromUrl, + getAppStateContainer, + replaceUrlAppState, + }; +}; + +export default OsdUrlStateStorage; From 1b64f9c63196ff8ab37329c28e6f8135c145c0a0 Mon Sep 17 00:00:00 2001 From: Federico Rodriguez Date: Tue, 15 Oct 2024 17:19:51 +0200 Subject: [PATCH 39/41] Bump revision to 04 (#7098) --- CHANGELOG.md | 2 +- plugins/main/opensearch_dashboards.json | 2 +- plugins/main/package.json | 2 +- plugins/wazuh-check-updates/opensearch_dashboards.json | 2 +- plugins/wazuh-check-updates/package.json | 2 +- plugins/wazuh-core/opensearch_dashboards.json | 2 +- plugins/wazuh-core/package.json | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d55a1c879..d023a77b81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ All notable changes to the Wazuh app project will be documented in this file. -## Wazuh v4.9.1 - OpenSearch Dashboards 2.13.0 - Revision 03 +## Wazuh v4.9.1 - OpenSearch Dashboards 2.13.0 - Revision 04 ### Added diff --git a/plugins/main/opensearch_dashboards.json b/plugins/main/opensearch_dashboards.json index 63bfa6d3cc..6fce1510e4 100644 --- a/plugins/main/opensearch_dashboards.json +++ b/plugins/main/opensearch_dashboards.json @@ -1,6 +1,6 @@ { "id": "wazuh", - "version": "4.9.1-03", + "version": "4.9.1-04", "opensearchDashboardsVersion": "opensearchDashboards", "configPath": ["wazuh"], "requiredPlugins": [ diff --git a/plugins/main/package.json b/plugins/main/package.json index ba9e31a4d0..af2557b1da 100644 --- a/plugins/main/package.json +++ b/plugins/main/package.json @@ -1,7 +1,7 @@ { "name": "wazuh", "version": "4.9.1", - "revision": "03", + "revision": "04", "pluginPlatform": { "version": "2.13.0" }, diff --git a/plugins/wazuh-check-updates/opensearch_dashboards.json b/plugins/wazuh-check-updates/opensearch_dashboards.json index 70c8cc9e56..ff7eb1c5e0 100644 --- a/plugins/wazuh-check-updates/opensearch_dashboards.json +++ b/plugins/wazuh-check-updates/opensearch_dashboards.json @@ -1,6 +1,6 @@ { "id": "wazuhCheckUpdates", - "version": "4.9.1-03", + "version": "4.9.1-04", "opensearchDashboardsVersion": "opensearchDashboards", "server": true, "ui": true, diff --git a/plugins/wazuh-check-updates/package.json b/plugins/wazuh-check-updates/package.json index 71d2419a06..c1bd160044 100644 --- a/plugins/wazuh-check-updates/package.json +++ b/plugins/wazuh-check-updates/package.json @@ -1,7 +1,7 @@ { "name": "wazuh-check-updates", "version": "4.9.1", - "revision": "03", + "revision": "04", "pluginPlatform": { "version": "2.13.0" }, diff --git a/plugins/wazuh-core/opensearch_dashboards.json b/plugins/wazuh-core/opensearch_dashboards.json index 0fe0d96e0d..4a80f42b28 100644 --- a/plugins/wazuh-core/opensearch_dashboards.json +++ b/plugins/wazuh-core/opensearch_dashboards.json @@ -1,6 +1,6 @@ { "id": "wazuhCore", - "version": "4.9.1-03", + "version": "4.9.1-04", "opensearchDashboardsVersion": "opensearchDashboards", "server": true, "ui": true, diff --git a/plugins/wazuh-core/package.json b/plugins/wazuh-core/package.json index 2357b581d1..44272d720a 100644 --- a/plugins/wazuh-core/package.json +++ b/plugins/wazuh-core/package.json @@ -1,7 +1,7 @@ { "name": "wazuh-core", "version": "4.9.1", - "revision": "03", + "revision": "04", "pluginPlatform": { "version": "2.13.0" }, From 8325cf24bfd87373adf8d66f3f705bcb72fe9102 Mon Sep 17 00:00:00 2001 From: Guido Modarelli <38738725+guidomodarelli@users.noreply.github.com> Date: Thu, 17 Oct 2024 04:22:05 -0300 Subject: [PATCH 40/41] Set a fixed width to the default columns on each selected field (#7060) * Remove Virustotal from Applications list * Remove Virustotal feature and dashboards * Remove Virustotal feature and dashboards as they are obsolete * Remove VirusTotal * Fix Prettier issues * Change initial widths for data grid columns * Add common data grid columns and initial widths * Refactor common data-grid columns for various events * Remove Virustotal feature from plugin README * Revert plugins/main/common/constants.ts * Revert plugins/main/common/wazuh-modules.ts * Revert plugins/main/public/components/add-modules-data/sample-data.tsx * Revert plugins/main/public/components/common/data-source/pattern/alerts/index.ts * Revert plugins/main/public/components/common/data-source/pattern/alerts/virustotal/index.ts * Revert plugins/main/test/* * Revert scripts/wazuh-alerts-generator/cli.js * Revert plugins/main/server/* * Revert plugins/main/public/components/common/* * Revert plugins/main/public/utils/applications.ts * Revert plugins/main/public/controllers/management/components/management/configuration/* * Revert plugins/main/public/components/overview/virustotal/* * Revert plugins/main/public/components/overview/index.ts * Fix Prettier issues * Refactor threatHuntingColumns with commonColumns * Update initial column widths for consistency --------- Co-authored-by: Federico Rodriguez --- CHANGELOG.md | 1 + .../config/data-grid-columns.tsx | 24 ++---- .../events/amazon-web-services-columns.tsx | 20 ++--- .../overview/common/data-grid-columns.ts | 29 ++++++++ .../overview/common/initial-width.ts | 7 ++ .../overview/docker/events/docker-columns.tsx | 22 ++---- .../file-integrity-monitoring-columns.tsx | 25 ++----- .../overview/gdpr/events/gdpr-columns.tsx | 24 ++---- .../overview/github/events/github-columns.tsx | 26 +++---- .../events/google-cloud-columns.tsx | 15 ++-- .../overview/hipaa/events/hipaa-columns.tsx | 24 ++---- .../events/malware-detection-columns.tsx | 23 ++---- .../mitre/events/mitre-attack-columns.tsx | 21 +++--- .../overview/nist/events/nist-columns.tsx | 24 ++---- .../office/events/office-365-columns.tsx | 18 ++--- .../overview/pci/events/pci-columns.tsx | 24 ++---- .../events/threat-hunting-columns.tsx | 73 +++++++------------ .../overview/tsc/events/tsc-columns.tsx | 24 ++---- .../events/vulnerabilities-columns.tsx | 15 ++-- 19 files changed, 174 insertions(+), 265 deletions(-) create mode 100644 plugins/main/public/components/overview/common/data-grid-columns.ts create mode 100644 plugins/main/public/components/overview/common/initial-width.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index a08c5e23c0..62d68df727 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ All notable changes to the Wazuh app project will be documented in this file. - Changed malware feature description [#7036](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7036) - Changed the font size of the kpi subtitles and the features descriptions [#7033](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7033) - Changed feature container margins to ensure consistent separation and uniform design. [#7034](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7034) +- Changed the initial width to the default columns on each selected field [#7059](https://github.com/wazuh/wazuh-dashboard-plugins/issues/7059) ### Fixed diff --git a/plugins/main/public/components/common/wazuh-discover/config/data-grid-columns.tsx b/plugins/main/public/components/common/wazuh-discover/config/data-grid-columns.tsx index 1f38aa247f..233c160243 100644 --- a/plugins/main/public/components/common/wazuh-discover/config/data-grid-columns.tsx +++ b/plugins/main/public/components/common/wazuh-discover/config/data-grid-columns.tsx @@ -1,22 +1,10 @@ -import React from 'react'; import { tDataGridColumn } from '../../data-grid'; +import { commonColumns } from '../../../overview/common/data-grid-columns'; export const threatHuntingColumns: tDataGridColumn[] = [ - { - id: 'timestamp', - isSortable: true, - defaultSortDirection: 'desc', - }, - { - id: 'agent.name', - }, - { - id: 'rule.description', - }, - { - id: 'rule.level', - }, - { - id: 'rule.id', - }, + commonColumns['timestamp'], + commonColumns['agent.name'], + commonColumns['rule.description'], + commonColumns['rule.level'], + commonColumns['rule.id'], ]; diff --git a/plugins/main/public/components/overview/amazon-web-services/events/amazon-web-services-columns.tsx b/plugins/main/public/components/overview/amazon-web-services/events/amazon-web-services-columns.tsx index 8f1a0541ff..df0aeda167 100644 --- a/plugins/main/public/components/overview/amazon-web-services/events/amazon-web-services-columns.tsx +++ b/plugins/main/public/components/overview/amazon-web-services/events/amazon-web-services-columns.tsx @@ -1,21 +1,13 @@ import { tDataGridColumn } from '../../../common/data-grid'; +import { commonColumns } from '../../common/data-grid-columns'; export const amazonWebServicesColumns: tDataGridColumn[] = [ - { - id: 'timestamp', - isSortable: true, - defaultSortDirection: 'desc', - }, + commonColumns.timestamp, { id: 'data.aws.source', + initialWidth: 144, }, - { - id: 'rule.description', - }, - { - id: 'rule.level', - }, - { - id: 'rule.id', - }, + commonColumns['rule.description'], + commonColumns['rule.level'], + commonColumns['rule.id'], ]; diff --git a/plugins/main/public/components/overview/common/data-grid-columns.ts b/plugins/main/public/components/overview/common/data-grid-columns.ts new file mode 100644 index 0000000000..8fb4fbe5a6 --- /dev/null +++ b/plugins/main/public/components/overview/common/data-grid-columns.ts @@ -0,0 +1,29 @@ +import { commonInitialWidth } from './initial-width'; + +export const commonColumns = { + timestamp: { + id: 'timestamp', + isSortable: true, + defaultSortDirection: 'desc', + initialWidth: commonInitialWidth.timestamp, + }, + 'agent.id': { + id: 'agent.id', + initialWidth: commonInitialWidth['agent.id'], + }, + 'agent.name': { + id: 'agent.name', + initialWidth: commonInitialWidth['agent.name'], + }, + 'rule.description': { + id: 'rule.description', + }, + 'rule.level': { + id: 'rule.level', + initialWidth: commonInitialWidth['rule.level'], + }, + 'rule.id': { + id: 'rule.id', + initialWidth: commonInitialWidth['rule.id'], + }, +} as const; diff --git a/plugins/main/public/components/overview/common/initial-width.ts b/plugins/main/public/components/overview/common/initial-width.ts new file mode 100644 index 0000000000..3f49641faa --- /dev/null +++ b/plugins/main/public/components/overview/common/initial-width.ts @@ -0,0 +1,7 @@ +export const commonInitialWidth = { + timestamp: 204, + 'agent.id': 93, + 'agent.name': 318, + 'rule.level': 93, + 'rule.id': 93, +} as const; diff --git a/plugins/main/public/components/overview/docker/events/docker-columns.tsx b/plugins/main/public/components/overview/docker/events/docker-columns.tsx index 892d66221d..8f07af124b 100644 --- a/plugins/main/public/components/overview/docker/events/docker-columns.tsx +++ b/plugins/main/public/components/overview/docker/events/docker-columns.tsx @@ -1,27 +1,21 @@ import { tDataGridColumn } from '../../../common/data-grid'; +import { commonColumns } from '../../common/data-grid-columns'; export const dockerColumns: tDataGridColumn[] = [ - { - id: 'timestamp', - isSortable: true, - defaultSortDirection: 'desc', - }, - { - id: 'agent.name', - }, + commonColumns.timestamp, + commonColumns['agent.name'], { id: 'data.docker.from', + initialWidth: 151, }, { id: 'data.docker.Type', + initialWidth: 149, }, { id: 'data.docker.Action', + initialWidth: 161, }, - { - id: 'rule.description', - }, - { - id: 'rule.level', - }, + commonColumns['rule.description'], + commonColumns['rule.level'], ]; diff --git a/plugins/main/public/components/overview/fim/events/file-integrity-monitoring-columns.tsx b/plugins/main/public/components/overview/fim/events/file-integrity-monitoring-columns.tsx index f3ca4ee0ae..1c2c9df7e9 100644 --- a/plugins/main/public/components/overview/fim/events/file-integrity-monitoring-columns.tsx +++ b/plugins/main/public/components/overview/fim/events/file-integrity-monitoring-columns.tsx @@ -1,27 +1,18 @@ import { tDataGridColumn } from '../../../common/data-grid'; +import { commonColumns } from '../../common/data-grid-columns'; export const fileIntegrityMonitoringColumns: tDataGridColumn[] = [ - { - id: 'timestamp', - isSortable: true, - defaultSortDirection: 'desc', - }, - { - id: 'agent.name', - }, + commonColumns.timestamp, + commonColumns['agent.name'], { id: 'syscheck.path', + initialWidth: 392, }, { id: 'syscheck.event', + initialWidth: 140, }, - { - id: 'rule.description', - }, - { - id: 'rule.level', - }, - { - id: 'rule.id', - }, + commonColumns['rule.description'], + commonColumns['rule.level'], + commonColumns['rule.id'], ]; diff --git a/plugins/main/public/components/overview/gdpr/events/gdpr-columns.tsx b/plugins/main/public/components/overview/gdpr/events/gdpr-columns.tsx index 0aecb6f50e..a2724c0fbe 100644 --- a/plugins/main/public/components/overview/gdpr/events/gdpr-columns.tsx +++ b/plugins/main/public/components/overview/gdpr/events/gdpr-columns.tsx @@ -1,24 +1,14 @@ import { tDataGridColumn } from '../../../common/data-grid'; +import { commonColumns } from '../../common/data-grid-columns'; export const gdprColumns: tDataGridColumn[] = [ - { - id: 'timestamp', - isSortable: true, - defaultSortDirection: 'desc', - }, - { - id: 'agent.name', - }, + commonColumns.timestamp, + commonColumns['agent.name'], { id: 'rule.gdpr', + initialWidth: 138, }, - { - id: 'rule.description', - }, - { - id: 'rule.level', - }, - { - id: 'rule.id', - }, + commonColumns['rule.description'], + commonColumns['rule.level'], + commonColumns['rule.id'], ]; diff --git a/plugins/main/public/components/overview/github/events/github-columns.tsx b/plugins/main/public/components/overview/github/events/github-columns.tsx index 764ff909d6..5fad65488d 100644 --- a/plugins/main/public/components/overview/github/events/github-columns.tsx +++ b/plugins/main/public/components/overview/github/events/github-columns.tsx @@ -1,30 +1,22 @@ import { tDataGridColumn } from '../../../common/data-grid'; +import { commonColumns } from '../../common/data-grid-columns'; export const githubColumns: tDataGridColumn[] = [ - { - id: 'timestamp', - isSortable: true, - defaultSortDirection: 'desc', - }, - { - id: 'agent.id', - }, + commonColumns.timestamp, + commonColumns['agent.id'], { id: 'data.github.repo', + initialWidth: 200, }, { id: 'data.github.actor', + initialWidth: 200, }, { id: 'data.github.org', + initialWidth: 200, }, - { - id: 'rule.description', - }, - { - id: 'rule.level', - }, - { - id: 'rule.id', - }, + commonColumns['rule.description'], + commonColumns['rule.level'], + commonColumns['rule.id'], ]; diff --git a/plugins/main/public/components/overview/google-cloud/events/google-cloud-columns.tsx b/plugins/main/public/components/overview/google-cloud/events/google-cloud-columns.tsx index 13b51d3e9a..8b983af64f 100644 --- a/plugins/main/public/components/overview/google-cloud/events/google-cloud-columns.tsx +++ b/plugins/main/public/components/overview/google-cloud/events/google-cloud-columns.tsx @@ -1,27 +1,26 @@ import { tDataGridColumn } from '../../../common/data-grid'; +import { commonColumns } from '../../common/data-grid-columns'; export const googleCloudColumns: tDataGridColumn[] = [ - { - id: 'timestamp', - isSortable: true, - defaultSortDirection: 'desc', - }, - { - id: 'agent.name', - }, + commonColumns.timestamp, + commonColumns['agent.name'], { id: 'data.gcp.jsonPayload.vmInstanceName', }, { id: 'data.gcp.resource.labels.location', + initialWidth: 261, }, { id: 'data.gcp.resource.labels.project_id', + initialWidth: 281, }, { id: 'data.gcp.resource.type', + initialWidth: 192, }, { id: 'data.gcp.severity', + initialWidth: 152, }, ]; diff --git a/plugins/main/public/components/overview/hipaa/events/hipaa-columns.tsx b/plugins/main/public/components/overview/hipaa/events/hipaa-columns.tsx index 87e75b71f1..6a5ad851ba 100644 --- a/plugins/main/public/components/overview/hipaa/events/hipaa-columns.tsx +++ b/plugins/main/public/components/overview/hipaa/events/hipaa-columns.tsx @@ -1,24 +1,14 @@ import { tDataGridColumn } from '../../../common/data-grid'; +import { commonColumns } from '../../common/data-grid-columns'; export const hipaaColumns: tDataGridColumn[] = [ - { - id: 'timestamp', - isSortable: true, - defaultSortDirection: 'desc', - }, - { - id: 'agent.name', - }, + commonColumns.timestamp, + commonColumns['agent.name'], { id: 'rule.hipaa', + initialWidth: 183, }, - { - id: 'rule.description', - }, - { - id: 'rule.level', - }, - { - id: 'rule.id', - }, + commonColumns['rule.description'], + commonColumns['rule.level'], + commonColumns['rule.id'], ]; diff --git a/plugins/main/public/components/overview/malware-detection/events/malware-detection-columns.tsx b/plugins/main/public/components/overview/malware-detection/events/malware-detection-columns.tsx index 80ba1ad133..62ec217358 100644 --- a/plugins/main/public/components/overview/malware-detection/events/malware-detection-columns.tsx +++ b/plugins/main/public/components/overview/malware-detection/events/malware-detection-columns.tsx @@ -1,24 +1,13 @@ import { tDataGridColumn } from '../../../common/data-grid'; +import { commonColumns } from '../../common/data-grid-columns'; export const malwareDetectionColumns: tDataGridColumn[] = [ - { - id: 'timestamp', - isSortable: true, - defaultSortDirection: 'desc', - }, - { - id: 'agent.name', - }, + commonColumns.timestamp, + commonColumns['agent.name'], { id: 'data.title', }, - { - id: 'rule.description', - }, - { - id: 'rule.level', - }, - { - id: 'rule.id', - }, + commonColumns['rule.description'], + commonColumns['rule.level'], + commonColumns['rule.id'], ]; diff --git a/plugins/main/public/components/overview/mitre/events/mitre-attack-columns.tsx b/plugins/main/public/components/overview/mitre/events/mitre-attack-columns.tsx index 6a339271f7..1941d0033b 100644 --- a/plugins/main/public/components/overview/mitre/events/mitre-attack-columns.tsx +++ b/plugins/main/public/components/overview/mitre/events/mitre-attack-columns.tsx @@ -1,15 +1,18 @@ import { tDataGridColumn } from '../../../common/data-grid'; +import { commonColumns } from '../../common/data-grid-columns'; export const mitreAttackColumns: tDataGridColumn[] = [ + commonColumns.timestamp, + commonColumns['agent.name'], { - id: 'timestamp', - isSortable: true, - defaultSortDirection: 'desc', + id: 'rule.mitre.id', + initialWidth: 118, }, - { id: 'agent.name' }, - { id: 'rule.mitre.id' }, - { id: 'rule.mitre.tactic' }, - { id: 'rule.description' }, - { id: 'rule.level' }, - { id: 'rule.id' }, + { + id: 'rule.mitre.tactic', + initialWidth: 280, + }, + commonColumns['rule.description'], + commonColumns['rule.level'], + commonColumns['rule.id'], ]; diff --git a/plugins/main/public/components/overview/nist/events/nist-columns.tsx b/plugins/main/public/components/overview/nist/events/nist-columns.tsx index 6242e66f33..ccfa62be68 100644 --- a/plugins/main/public/components/overview/nist/events/nist-columns.tsx +++ b/plugins/main/public/components/overview/nist/events/nist-columns.tsx @@ -1,24 +1,14 @@ import { tDataGridColumn } from '../../../common/data-grid'; +import { commonColumns } from '../../common/data-grid-columns'; export const nistColumns: tDataGridColumn[] = [ - { - id: 'timestamp', - isSortable: true, - defaultSortDirection: 'desc', - }, - { - id: 'agent.name', - }, + commonColumns.timestamp, + commonColumns['agent.name'], { id: 'rule.nist_800_53', + initialWidth: 171, }, - { - id: 'rule.description', - }, - { - id: 'rule.level', - }, - { - id: 'rule.id', - }, + commonColumns['rule.description'], + commonColumns['rule.level'], + commonColumns['rule.id'], ]; diff --git a/plugins/main/public/components/overview/office/events/office-365-columns.tsx b/plugins/main/public/components/overview/office/events/office-365-columns.tsx index 01e890bed5..65b1e7a9fa 100644 --- a/plugins/main/public/components/overview/office/events/office-365-columns.tsx +++ b/plugins/main/public/components/overview/office/events/office-365-columns.tsx @@ -1,27 +1,23 @@ import { tDataGridColumn } from '../../../common/data-grid'; +import { commonColumns } from '../../common/data-grid-columns'; export const office365Columns: tDataGridColumn[] = [ - { - id: 'timestamp', - isSortable: true, - defaultSortDirection: 'desc', - }, + commonColumns.timestamp, { id: 'data.office365.Subscription', + initialWidth: 225, }, { id: 'data.office365.Operation', }, { id: 'data.office365.UserId', + initialWidth: 226, }, { id: 'data.office365.ClientIP', + initialWidth: 191, }, - { - id: 'rule.level', - }, - { - id: 'rule.id', - }, + commonColumns['rule.level'], + commonColumns['rule.id'], ]; diff --git a/plugins/main/public/components/overview/pci/events/pci-columns.tsx b/plugins/main/public/components/overview/pci/events/pci-columns.tsx index c81284c075..4634366151 100644 --- a/plugins/main/public/components/overview/pci/events/pci-columns.tsx +++ b/plugins/main/public/components/overview/pci/events/pci-columns.tsx @@ -1,24 +1,14 @@ import { tDataGridColumn } from '../../../common/data-grid'; +import { commonColumns } from '../../common/data-grid-columns'; export const pciColumns: tDataGridColumn[] = [ - { - id: 'timestamp', - isSortable: true, - defaultSortDirection: 'desc', - }, - { - id: 'agent.name', - }, + commonColumns.timestamp, + commonColumns['agent.name'], { id: 'rule.pci_dss', + initialWidth: 160, }, - { - id: 'rule.description', - }, - { - id: 'rule.level', - }, - { - id: 'rule.id', - }, + commonColumns['rule.description'], + commonColumns['rule.level'], + commonColumns['rule.id'], ]; diff --git a/plugins/main/public/components/overview/threat-hunting/events/threat-hunting-columns.tsx b/plugins/main/public/components/overview/threat-hunting/events/threat-hunting-columns.tsx index b2364208ae..92ac7f0afe 100644 --- a/plugins/main/public/components/overview/threat-hunting/events/threat-hunting-columns.tsx +++ b/plugins/main/public/components/overview/threat-hunting/events/threat-hunting-columns.tsx @@ -1,62 +1,41 @@ import { EuiDataGridColumn } from '@elastic/eui'; import { tDataGridColumn } from '../../../common/data-grid'; +import { commonColumns } from '../../common/data-grid-columns'; export const MAX_ENTRIES_PER_QUERY = 10000; -export const threatHuntingTableDefaultColumns: tDataGridColumn[] = [ - { +const threatHuntingTableCommonColumns = { + icon: { id: 'icon', }, - { - id: 'timestamp', - isSortable: true, - defaultSortDirection: 'desc', - }, - { - id: 'agent.id', - }, - { - id: 'agent.name', - }, - { + 'rule.mitre.id': { id: 'rule.mitre.id', + initialWidth: 123, }, - { + 'rule.mitre.tactic': { id: 'rule.mitre.tactic', + initialWidth: 266, }, - { - id: 'rule.description', - }, - { - id: 'rule.level', - }, - { - id: 'rule.id', - }, +} as Record; + +export const threatHuntingTableDefaultColumns: tDataGridColumn[] = [ + threatHuntingTableCommonColumns.icon, + commonColumns.timestamp, + commonColumns['agent.id'], + commonColumns['agent.name'], + threatHuntingTableCommonColumns['rule.mitre.id'], + threatHuntingTableCommonColumns['rule.mitre.tactic'], + commonColumns['rule.description'], + commonColumns['rule.level'], + commonColumns['rule.id'], ]; export const threatHuntingTableAgentColumns: EuiDataGridColumn[] = [ - { - id: 'icon', - }, - { - id: 'timestamp', - isSortable: true, - defaultSortDirection: 'desc', - }, - { - id: 'rule.mitre.id', - }, - { - id: 'rule.mitre.tactic', - }, - { - id: 'rule.description', - }, - { - id: 'rule.level', - }, - { - id: 'rule.id', - }, + threatHuntingTableCommonColumns.icon, + commonColumns.timestamp, + threatHuntingTableCommonColumns['rule.mitre.id'], + threatHuntingTableCommonColumns['rule.mitre.tactic'], + commonColumns['rule.description'], + commonColumns['rule.level'], + commonColumns['rule.id'], ]; diff --git a/plugins/main/public/components/overview/tsc/events/tsc-columns.tsx b/plugins/main/public/components/overview/tsc/events/tsc-columns.tsx index a9fd8c2c77..dd8968e2ee 100644 --- a/plugins/main/public/components/overview/tsc/events/tsc-columns.tsx +++ b/plugins/main/public/components/overview/tsc/events/tsc-columns.tsx @@ -1,24 +1,14 @@ import { tDataGridColumn } from '../../../common/data-grid'; +import { commonColumns } from '../../common/data-grid-columns'; export const tscColumns: tDataGridColumn[] = [ - { - id: 'timestamp', - isSortable: true, - defaultSortDirection: 'desc', - }, - { - id: 'agent.name', - }, + commonColumns.timestamp, + commonColumns['agent.name'], { id: 'rule.tsc', + initialWidth: 283, }, - { - id: 'rule.description', - }, - { - id: 'rule.level', - }, - { - id: 'rule.id', - }, + commonColumns['rule.description'], + commonColumns['rule.level'], + commonColumns['rule.id'], ]; diff --git a/plugins/main/public/components/overview/vulnerabilities/events/vulnerabilities-columns.tsx b/plugins/main/public/components/overview/vulnerabilities/events/vulnerabilities-columns.tsx index d1ee7ce042..4027079f39 100644 --- a/plugins/main/public/components/overview/vulnerabilities/events/vulnerabilities-columns.tsx +++ b/plugins/main/public/components/overview/vulnerabilities/events/vulnerabilities-columns.tsx @@ -1,27 +1,26 @@ import { tDataGridColumn } from '../../../common/data-grid'; +import { commonColumns } from '../../common/data-grid-columns'; export const vulnerabilitiesColumns: tDataGridColumn[] = [ - { - id: 'timestamp', - isSortable: true, - defaultSortDirection: 'desc', - }, - { - id: 'agent.name', - }, + commonColumns.timestamp, + commonColumns['agent.name'], { id: 'data.vulnerability.cve', + initialWidth: 186, }, { id: 'data.vulnerability.severity', + initialWidth: 217, }, { id: 'data.vulnerability.package.name', + initialWidth: 257, }, { id: 'data.vulnerability.package.version', }, { id: 'data.vulnerability.status', + initialWidth: 199, }, ]; From d80e3c9cf231f5ea92f18a849dc2e966f69132eb Mon Sep 17 00:00:00 2001 From: Guido Modarelli <38738725+guidomodarelli@users.noreply.github.com> Date: Thu, 17 Oct 2024 05:56:17 -0300 Subject: [PATCH 41/41] Avoid filter hiding when adding too many of them (#7077) * Adjust max-width media query margin for mobile view * Fix filter management prevent hiding when adding multiple filters * Refactor search bar styles for responsiveness --------- Co-authored-by: Antonio <34042064+Desvelao@users.noreply.github.com> --- CHANGELOG.md | 1 + .../components/common/modules/module.scss | 4 -- .../common/search-bar/search-bar.scss | 66 +++++++++++++++++-- .../common/search-bar/search-bar.tsx | 5 +- plugins/main/public/styles/common.scss | 1 - plugins/main/public/styles/media-queries.scss | 39 ----------- 6 files changed, 66 insertions(+), 50 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62d68df727..46bd00551a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -33,6 +33,7 @@ All notable changes to the Wazuh app project will be documented in this file. - Fixed security policy exception when it contained deprecated actions [#7042](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7042) - 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) ### Removed diff --git a/plugins/main/public/components/common/modules/module.scss b/plugins/main/public/components/common/modules/module.scss index fd906406cd..8182b3d601 100644 --- a/plugins/main/public/components/common/modules/module.scss +++ b/plugins/main/public/components/common/modules/module.scss @@ -106,10 +106,6 @@ discover-app-w .sidebar-container { margin-top: -160px; } - .wz-module-header-nav { - padding-bottom: 16px; - } - .wz-module-body-agent-info > .euiFlexGroup > .euiFlexItem { max-width: unset !important; } diff --git a/plugins/main/public/components/common/search-bar/search-bar.scss b/plugins/main/public/components/common/search-bar/search-bar.scss index f45d922c38..badec25a41 100644 --- a/plugins/main/public/components/common/search-bar/search-bar.scss +++ b/plugins/main/public/components/common/search-bar/search-bar.scss @@ -1,8 +1,8 @@ -.wz-search-bar-no-padding .globalQueryBar:not(:empty) { - padding: 0px !important; -} - .wz-search-bar { + &.no-padding .globalQueryBar:not(:empty) { + padding: 0px !important; + } + > .euiFlexGroup { &:first-child { #GlobalFilterGroup { @@ -10,4 +10,62 @@ } } } + + &-query { + .osdQueryBar--withDatePicker { + align-items: flex-end; + + > :first-child { + margin-top: 8px; + margin-bottom: 4px !important; + + @media only screen and (max-width: 574px) { + margin-top: -8px; + } + } + } + } + + @media only screen and (min-width: 575px) and (max-width: 767px) { + .globalFilterGroup__filterBar { + margin-top: 4px; + } + + .globalFilterGroup__wrapper-isVisible { + margin-top: 0; + } + + .euiFlexGroup--responsive > .euiFlexItem { + margin-bottom: 0 !important; + } + } + + @media only screen and (max-width: 767px) { + .euiFlexGroup--responsive { + -webkit-flex-wrap: wrap; + flex-wrap: wrap; + margin-left: 0; + margin-right: 0; + margin-bottom: 1px; + } + } + + @media only screen and (max-width: 574px) { + .globalFilterGroup__wrapper-isVisible { + margin-top: -6px; + } + + .euiFlexGroup--responsive { + margin-bottom: -3px; + } + + > .euiFlexGroup.euiFlexGroup--gutterSmall.euiFlexGroup--directionRow.euiFlexGroup--responsive + > .euiFlexItem.euiFlexItem--flexGrowZero { + margin-bottom: 6px !important; + } + + .osdQueryBar--withDatePicker > :first-child { + margin-top: -8px; + } + } } diff --git a/plugins/main/public/components/common/search-bar/search-bar.tsx b/plugins/main/public/components/common/search-bar/search-bar.tsx index c6cc9a4bf9..e12a317b76 100644 --- a/plugins/main/public/components/common/search-bar/search-bar.tsx +++ b/plugins/main/public/components/common/search-bar/search-bar.tsx @@ -35,7 +35,7 @@ export const WzSearchBar = ({ return ( {showQuery ? ( ) : null} {showFilters ? ( - + {hideFixedFilters ? null : ( .euiFlexItem { - margin-bottom: 0 !important; - } - } - - @media only screen and (min-width: 575px) and (max-width: 767px) { - .globalFilterGroup__wrapper-isVisible { - .euiFlexItem.euiFlexItem--flexGrowZero { - margin-bottom: 0px; - } - } - } - - @media only screen and (min-width: 575px) and (max-width: 767px) { - .euiFlexGroup--responsive { - -webkit-flex-wrap: wrap; - flex-wrap: wrap; - margin-left: 0; - margin-right: 0; - margin-bottom: 6px; - margin-top: 10px; - } - } -}