From 81d093cb52c133b3064c58c901b24ad00538886a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Wed, 27 Mar 2024 13:13:10 +0100 Subject: [PATCH 01/42] feat(reporting): adapt the screenshot taking to dashboard rendering - Adapt the Generate report button to use the search context - Create state and reducers into Redux store - Create hook to send the search context from a dashboard to the Generate report button - Remove disabledReport property and use the search context instead - Replace the mechanim to take the visualizations of the screenshots from the DOM --- ...se-reporting-communicate-search-context.ts | 24 +++ .../modules/buttons/generate_report.tsx | 96 ++++++----- .../public/controllers/overview/overview.js | 1 - .../main/public/react-services/reporting.js | 79 ++++----- .../public/redux/actions/reportingActions.js | 20 ++- .../redux/reducers/reportingReducers.js | 19 ++- .../public/templates/agents/dashboards.html | 8 +- plugins/main/server/lib/reporting/printer.ts | 158 +++++++++++------- 8 files changed, 250 insertions(+), 155 deletions(-) create mode 100644 plugins/main/public/components/common/hooks/use-reporting-communicate-search-context.ts diff --git a/plugins/main/public/components/common/hooks/use-reporting-communicate-search-context.ts b/plugins/main/public/components/common/hooks/use-reporting-communicate-search-context.ts new file mode 100644 index 0000000000..d346dcc079 --- /dev/null +++ b/plugins/main/public/components/common/hooks/use-reporting-communicate-search-context.ts @@ -0,0 +1,24 @@ +import { useEffect } from 'react'; +import { useDispatch } from 'react-redux'; +import { updateReportingCommunicateSearchContext } from '../../../redux/actions/reportingActions'; +import { IIndexPattern } from '../../../../../../src/plugins/data/public'; +/** + * WORKAROUND: this hook stores the search context to be used by the Generate report button of + * module dashboards + * @param context + */ +export function useReportingCommunicateSearchContext(context: { + isLoading: boolean; + isSearching: boolean; + totalResults: number; + indexPattern: IIndexPattern; + filters: any; + time: any; + query: any; +}) { + const dispatch = useDispatch(); + useEffect(() => { + dispatch(updateReportingCommunicateSearchContext(context)); + return () => dispatch(updateReportingCommunicateSearchContext(null)); + }, [JSON.stringify(context)]); +} diff --git a/plugins/main/public/components/common/modules/buttons/generate_report.tsx b/plugins/main/public/components/common/modules/buttons/generate_report.tsx index 155963d8cb..1ead2191b5 100644 --- a/plugins/main/public/components/common/modules/buttons/generate_report.tsx +++ b/plugins/main/public/components/common/modules/buttons/generate_report.tsx @@ -16,48 +16,66 @@ import { getUiSettings } from '../../../../kibana-services'; import { ReportingService } from '../../../../react-services'; import $ from 'jquery'; import { WzButton } from '../../../common/buttons'; +import { connect } from 'react-redux'; +const mapStateToProps = state => ({ + dataSourceSearchContext: state.reportingReducers.dataSourceSearchContext, +}); -export const ButtonModuleGenerateReport = ({agent, moduleID, disabledReport}) => { - const action = useAsyncAction(async () => { - const reportingService = new ReportingService(); - const isDarkModeTheme = getUiSettings().get('theme:darkMode'); - if (isDarkModeTheme) { +export const ButtonModuleGenerateReport = connect(mapStateToProps)( + ({ agent, moduleID, dataSourceSearchContext }) => { + const disabledReport = ![ + !dataSourceSearchContext?.isLoading, + !dataSourceSearchContext?.isSearching, + dataSourceSearchContext?.totalResults, + dataSourceSearchContext?.indexPattern, + ].every(Boolean); + const totalResults = dataSourceSearchContext?.totalResults; + const action = useAsyncAction(async () => { + const reportingService = new ReportingService(); + const isDarkModeTheme = getUiSettings().get('theme:darkMode'); + if (isDarkModeTheme) { + //Patch to fix white text in dark-mode pdf reports + const defaultTextColor = '#DFE5EF'; - //Patch to fix white text in dark-mode pdf reports - const defaultTextColor = '#DFE5EF'; + //Patch to fix dark backgrounds in visualizations dark-mode pdf reports + const $labels = $('.euiButtonEmpty__text, .echLegendItem'); + const $vizBackground = $('.echChartBackground'); + const defaultVizBackground = $vizBackground.css('background-color'); - //Patch to fix dark backgrounds in visualizations dark-mode pdf reports - const $labels = $('.euiButtonEmpty__text, .echLegendItem'); - const $vizBackground = $('.echChartBackground'); - const defaultVizBackground = $vizBackground.css('background-color'); - - try { - $labels.css('color', 'black'); - $vizBackground.css('background-color', 'transparent'); - await reportingService.startVis2Png(moduleID, agent?.id || false) - $vizBackground.css('background-color', defaultVizBackground); - $labels.css('color', defaultTextColor); - } catch (e) { - $labels.css('color', defaultTextColor); - $vizBackground.css('background-color', defaultVizBackground); + try { + $labels.css('color', 'black'); + $vizBackground.css('background-color', 'transparent'); + await reportingService.startVis2Png(moduleID, agent?.id || false); + $vizBackground.css('background-color', defaultVizBackground); + $labels.css('color', defaultTextColor); + } catch (e) { + $labels.css('color', defaultTextColor); + $vizBackground.css('background-color', defaultVizBackground); + } + } else { + await reportingService.startVis2Png(moduleID, agent?.id || false); } - } else { - await reportingService.startVis2Png(moduleID, agent?.id || false) - } - }, [agent]); - - return ( - - Generate report - - ) -} + }, [agent]); + return ( + + Generate report + + ); + }, +); diff --git a/plugins/main/public/controllers/overview/overview.js b/plugins/main/public/controllers/overview/overview.js index 3060f0a533..ed2edb9a87 100644 --- a/plugins/main/public/controllers/overview/overview.js +++ b/plugins/main/public/controllers/overview/overview.js @@ -98,7 +98,6 @@ export class OverviewController { this.$scope.getMainProps = resultState => { return { section: this.tab, - disabledReport: resultState !== 'ready', agentsSelectionProps: this.agentsSelectionProps, switchSubTab: subtab => this.switchSubtab(subtab), }; diff --git a/plugins/main/public/react-services/reporting.js b/plugins/main/public/react-services/reporting.js index 2306b60d80..f714d434dc 100644 --- a/plugins/main/public/react-services/reporting.js +++ b/plugins/main/public/react-services/reporting.js @@ -22,6 +22,10 @@ import { getAngularModule, getDataPlugin, getToasts } from '../kibana-services'; import { UI_LOGGER_LEVELS } from '../../common/constants'; import { UI_ERROR_SEVERITIES } from './error-orchestrator/types'; import { getErrorOrchestrator } from './common-services'; +import store from '../redux/store'; +import domtoimage from '../utils/dom-to-image'; +import dateMath from '@elastic/datemath'; + const app = getAngularModule(); export class ReportingService { @@ -59,63 +63,54 @@ export class ReportingService { return idArray; } - async startVis2Png(tab, agents = false, syscollectorFilters = null) { + async getVisualizationsFromDOM() { + const domVisualizations = document.querySelectorAll('.visualization'); + return await Promise.all( + Array.from(domVisualizations).map(async node => { + return { + element: await domtoimage.toPng(node), + width: node.clientWidth, + height: node.clientHeight, + title: node?.parentNode?.parentNode?.parentNode?.querySelector( + 'figcaption > h2 > .embPanel__titleInner', + )?.textContent, + }; + }), + ); + } + + async getDataSourceSearchContext() { + return store.getState().reportingReducers?.dataSourceSearchContext; + } + + async startVis2Png(tab, agents = false, searchContext = null) { try { - if (this.vis2png.isWorking()) { - this.showToast('danger', 'Error', 'Report in progress', 4000); - return; - } this.$rootScope.reportBusy = true; this.$rootScope.reportStatus = 'Generating report...0%'; this.$rootScope.$applyAsync(); - this.vis2png.clear(); - - const rawVisualizations = this.rawVisualizations - .getList() - .filter(this.removeTableVis); - - let idArray = []; - if (tab === 'general') { - idArray = this.removeAgentStatusVis( - rawVisualizations.map(item => item.id), - ); - } else { - idArray = rawVisualizations.map(item => item.id); - } - - const visualizationIDList = []; - for (const item of idArray) { - const tmpHTMLElement = $(`#${item}`); - if (tmpHTMLElement[0]) { - this.vis2png.assignHTMLItem(item, tmpHTMLElement); - visualizationIDList.push(item); - } - } - - const appliedFilters = await this.visHandlers.getAppliedFilters( - syscollectorFilters, - ); + const dataSourceContext = + searchContext || (await this.getDataSourceSearchContext()); + const visualizations = await this.getVisualizationsFromDOM(); const dataplugin = await getDataPlugin(); const serverSideQuery = dataplugin.query.getOpenSearchQuery(); - const array = await this.vis2png.checkArray(visualizationIDList); - const browserTimezone = moment.tz.guess(true); const data = { - array, + array: visualizations, serverSideQuery, // Used for applying the same filters on the server side requests - filters: appliedFilters.filters, - time: appliedFilters.time, - searchBar: appliedFilters.searchBar, - tables: appliedFilters.tables, + filters: dataSourceContext.filters, + time: { + to: dateMath.parse(dataSourceContext.time.to), + from: dateMath.parse(dataSourceContext.time.to), + }, + searchBar: dataSourceContext?.query?.query || '', + tables: [], // TODO: check is this is used tab, section: agents ? 'agents' : 'overview', agents, browserTimezone, - indexPatternTitle: ( - await getDataPlugin().indexPatterns.get(AppState.getCurrentPattern()) - ).title, + indexPatternTitle: dataSourceContext.indexPattern.title, apiId: JSON.parse(AppState.getCurrentAPI()).id, }; diff --git a/plugins/main/public/redux/actions/reportingActions.js b/plugins/main/public/redux/actions/reportingActions.js index 9ada6e18e3..a6dfd76ad3 100644 --- a/plugins/main/public/redux/actions/reportingActions.js +++ b/plugins/main/public/redux/actions/reportingActions.js @@ -17,7 +17,7 @@ export const updateIsProcessing = isProcessing => { return { type: 'UPDATE_IS_PROCESSING', - isProcessing: isProcessing + isProcessing: isProcessing, }; }; @@ -28,7 +28,7 @@ export const updateIsProcessing = isProcessing => { export const updateListItemsForRemove = itemList => { return { type: 'UPDATE_LIST_ITEMS_FOR_REMOVE', - itemList: itemList + itemList: itemList, }; }; @@ -39,7 +39,7 @@ export const updateListItemsForRemove = itemList => { export const updateShowModal = showModal => { return { type: 'UPDATE_SHOW_MODAL', - showModal: showModal + showModal: showModal, }; }; @@ -49,6 +49,18 @@ export const updateShowModal = showModal => { */ export const cleanInfo = () => { return { - type: 'CLEAN_INFO' + type: 'CLEAN_INFO', }; }; + +/** + * Update reporting data source search context + * @param {Object} dataSourceSearchContext + */ +export const updateReportingCommunicateSearchContext = + dataSourceSearchContext => { + return { + type: 'UPDATE_REPORTING_DATA_SEARCH_SOURCE_CONTEXT', + dataSourceSearchContext, + }; + }; diff --git a/plugins/main/public/redux/reducers/reportingReducers.js b/plugins/main/public/redux/reducers/reportingReducers.js index 5e53baa9b2..9d5397b4c2 100644 --- a/plugins/main/public/redux/reducers/reportingReducers.js +++ b/plugins/main/public/redux/reducers/reportingReducers.js @@ -10,11 +10,14 @@ * Find more information about this on the LICENSE file. */ +import { cloneDeep } from 'lodash'; + const initialState = { isLoading: false, isProcessing: false, itemList: [], - showModal: false + showModal: false, + dataSourceSearchContext: null, }; const statusReducers = (state = initialState, action) => { @@ -22,19 +25,19 @@ const statusReducers = (state = initialState, action) => { return { ...state, isProcessing: action.isProcessing, - isLoading: action.isProcessing + isLoading: action.isProcessing, }; } if (action.type === 'UPDATE_LIST_ITEMS_FOR_REMOVE') { return { ...state, - itemList: action.itemList + itemList: action.itemList, }; } if (action.type === 'UPDATE_SHOW_MODAL') { return { ...state, - showModal: action.showModal + showModal: action.showModal, }; } if (action.type === 'CLEAN_INFO') { @@ -43,7 +46,13 @@ const statusReducers = (state = initialState, action) => { isLoading: false, isProcessing: false, itemList: [], - showModal: false + showModal: false, + }; + } + if (action.type === 'UPDATE_REPORTING_DATA_SEARCH_SOURCE_CONTEXT') { + return { + ...state, + dataSourceSearchContext: cloneDeep(action.dataSourceSearchContext), }; } diff --git a/plugins/main/public/templates/agents/dashboards.html b/plugins/main/public/templates/agents/dashboards.html index 33fe5c8c5e..04902f6592 100644 --- a/plugins/main/public/templates/agents/dashboards.html +++ b/plugins/main/public/templates/agents/dashboards.html @@ -30,7 +30,7 @@ >
@@ -115,7 +115,11 @@
-
+
item.width >= 600); - const double_vis = visualizations.filter(item => item.width < 600); - single_vis.forEach(visualization => { - const title = this.checkTitle(visualization, isAgents, tab); - this.addContent({ - id: 'singlevis' + title[0]._source.title, - text: title[0]._source.title, + private addVisualizationSingle(visualization: IVisualizationExtended) { + this.addContent({ + id: 'singlevis' + visualization.id, + text: visualization.title, + style: 'h3', + }); + this.addContent({ + columns: [{ image: visualization.element, width: 500 }], + }); + this.addNewLine(); + } + private addVisualizationSplit( + split: [IVisualizationExtended, IVisualizationExtended], + ) { + this.addContent({ + columns: split.map(visualization => ({ + id: 'splitvis' + visualization.id, + text: visualization.title, style: 'h3', - }); - this.addContent({ - columns: [{ image: visualization.element, width: 500 }], - }); - this.addNewLine(); + width: 280, + })), }); - let pair = []; + this.addContent({ + columns: split.map(visualization => ({ + image: visualization.element, + width: 270, + })), + }); - for (const item of double_vis) { - pair.push(item); - if (pair.length === 2) { - const title_1 = this.checkTitle(pair[0], isAgents, tab); - const title_2 = this.checkTitle(pair[1], isAgents, tab); + this.addNewLine(); + } + private addVisualizationSplitSingle(visualization: IVisualizationExtended) { + this.addContent({ + columns: [ + { + id: 'splitsinglevis' + visualization.id, + text: visualization.title, + style: 'h3', + width: 280, + }, + ], + }); + this.addContent({ + columns: [{ image: visualization.element, width: 280 }], + }); + this.addNewLine(); + } + addVisualizations(visualizations: IVisualization[]) { + this.logger.debug(`Add visualizations [${visualizations.length}]`); + const sanitazedVisualizations: IVisualizationExtended[] = + visualizations.map((visualization, index) => ({ + ...visualization, + title: visualization.title || '', + id: `${visualization.title || ''}.${index}`, + })); + const { single: fullWidthVisualizations, split: splitWidthVisualizations } = + sanitazedVisualizations.reduce( + (accum, visualization) => { + ( + (visualization.width >= 600 + ? accum.single + : accum.split) as IVisualizationExtended[] + ).push(visualization); + return accum; + }, + { single: [], split: [] }, + ); - this.addContent({ - columns: [ - { - id: 'splitvis' + title_1[0]._source.title, - text: title_1[0]._source.title, - style: 'h3', - width: 280, - }, - { - id: 'splitvis' + title_2[0]._source.title, - text: title_2[0]._source.title, - style: 'h3', - width: 280, - }, - ], - }); + fullWidthVisualizations.forEach(visualization => + this.addVisualizationSingle(visualization), + ); - this.addContent({ - columns: [ - { image: pair[0].element, width: 270 }, - { image: pair[1].element, width: 270 }, - ], - }); + const splitBy = 2; + const splits = splitWidthVisualizations.reduce(function ( + accum, + value, + index, + array, + ) { + if (index % splitBy === 0) + accum.push(array.slice(index, index + splitBy)); + return accum; + }, + []); - this.addNewLine(); - pair = []; + splits.forEach(split => { + if (split.length === splitBy) { + return this.addVisualizationSplit(split); } - } - - if (double_vis.length % 2 !== 0) { - const item = double_vis[double_vis.length - 1]; - const title = this.checkTitle(item, isAgents, tab); - this.addContent({ - columns: [ - { - id: 'splitsinglevis' + title[0]._source.title, - text: title[0]._source.title, - style: 'h3', - width: 280, - }, - ], - }); - this.addContent({ columns: [{ image: item.element, width: 280 }] }); - this.addNewLine(); - } + this.addVisualizationSplitSingle(split[0]); + }); } formatDate(date: Date): string { this.logger.debug(`Format date ${date}`); From 09e584c6251d7f8ca9993d69e06ce46c4e0419e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Wed, 27 Mar 2024 13:31:18 +0100 Subject: [PATCH 02/42] feat(reporting): remove unused AngularJS service to generate the reports - Remove the dependency injectiong of the unused AngularJS service to generate the reports --- .../main/public/controllers/agent/agents.js | 11 -- .../public/controllers/overview/overview.js | 10 - plugins/main/public/services/index.js | 2 - plugins/main/public/services/reporting.js | 173 ------------------ 4 files changed, 196 deletions(-) delete mode 100644 plugins/main/public/services/reporting.js diff --git a/plugins/main/public/controllers/agent/agents.js b/plugins/main/public/controllers/agent/agents.js index 522b3e0a92..6170a1ef3a 100644 --- a/plugins/main/public/controllers/agent/agents.js +++ b/plugins/main/public/controllers/agent/agents.js @@ -41,7 +41,6 @@ export class AgentsController { * @param {Object} $rootScope * @param {Object} errorHandler * @param {Object} commonData - * @param {Object} reportingService * @param {Object} visFactoryService * @param {Object} csvReq */ @@ -51,7 +50,6 @@ export class AgentsController { $rootScope, errorHandler, commonData, - reportingService, visFactoryService, csvReq, ) { @@ -63,7 +61,6 @@ export class AgentsController { this.$scope.visualizations = visualizations; this.shareAgent = new ShareAgent(); this.commonData = commonData; - this.reportingService = reportingService; this.visFactoryService = visFactoryService; this.csvReq = csvReq; this.wazuhConfig = new WazuhConfig(); @@ -192,14 +189,6 @@ export class AgentsController { this.$location.path('/manager/groups'); }; - this.$scope.exportConfiguration = enabledComponents => { - this.reportingService.startConfigReport( - this.$scope.agent, - 'agentConfig', - enabledComponents, - ); - }; - //Load try { this.$scope.getAgent(); diff --git a/plugins/main/public/controllers/overview/overview.js b/plugins/main/public/controllers/overview/overview.js index ed2edb9a87..5f8b8ea7f6 100644 --- a/plugins/main/public/controllers/overview/overview.js +++ b/plugins/main/public/controllers/overview/overview.js @@ -37,7 +37,6 @@ export class OverviewController { * @param {*} $rootScope * @param {*} errorHandler * @param {*} commonData - * @param {*} reportingService * @param {*} visFactoryService */ constructor( @@ -46,7 +45,6 @@ export class OverviewController { $rootScope, errorHandler, commonData, - reportingService, visFactoryService, $route, ) { @@ -57,7 +55,6 @@ export class OverviewController { this.errorHandler = errorHandler; this.tabVisualizations = new TabVisualizations(); this.commonData = commonData; - this.reportingService = reportingService; this.visFactoryService = visFactoryService; this.wazuhConfig = new WazuhConfig(); this.visFactoryService = VisFactoryHandler; @@ -325,13 +322,6 @@ export class OverviewController { this.$scope.$applyAsync(); } - /** - * Transform a visualization into an image - */ - startVis2Png() { - return this.reportingService.startVis2Png(this.tab); - } - /** * This fetch de agents summary */ diff --git a/plugins/main/public/services/index.js b/plugins/main/public/services/index.js index a82f4124c9..dea9069f72 100644 --- a/plugins/main/public/services/index.js +++ b/plugins/main/public/services/index.js @@ -14,7 +14,6 @@ import './theming'; import './routes'; import { CSVRequest } from './csv-request'; import { CommonData } from './common-data'; -import { ReportingService } from './reporting'; import { VisFactoryService } from './vis-factory-handler'; import './region-maps'; import './order-object-by'; @@ -28,7 +27,6 @@ app .service('errorHandler', ErrorHandler) .service('csvReq', CSVRequest) .service('commonData', CommonData) - .service('reportingService', ReportingService) .service('visFactoryService', VisFactoryService) .service('configHandler', ConfigHandler) .service('checkDaemonsStatus', CheckDaemonsStatus); diff --git a/plugins/main/public/services/reporting.js b/plugins/main/public/services/reporting.js deleted file mode 100644 index e44106bb66..0000000000 --- a/plugins/main/public/services/reporting.js +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Wazuh app - Reporting service - * 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 $ from 'jquery'; -import moment from 'moment'; -import { WazuhConfig } from '../react-services/wazuh-config'; -import { GenericRequest } from '../react-services/generic-request'; -import { ErrorHandler } from '../react-services/error-handler'; - -export class ReportingService { - constructor( - $rootScope, - vis2png, - rawVisualizations, - visHandlers, - errorHandler, - ) { - this.$rootScope = $rootScope; - this.vis2png = vis2png; - this.rawVisualizations = rawVisualizations; - this.visHandlers = visHandlers; - this.genericReq = GenericRequest; - this.errorHandler = errorHandler; - this.wazuhConfig = new WazuhConfig(); - } - removeTableVis(visList) { - const attributes = JSON.parse(visList.attributes.visState); - return attributes.type !== 'table'; - } - - removeAgentStatusVis(idArray) { - const monitoringEnabled = - this.wazuhConfig.getConfig()['wazuh.monitoring.enabled']; - if (!monitoringEnabled) { - const visArray = idArray.filter(vis => { - return vis !== 'Wazuh-App-Overview-General-Agents-status'; - }); - return visArray; - } - return idArray; - } - - async startVis2Png(tab, isAgents = false, syscollectorFilters = null) { - try { - if (this.vis2png.isWorking()) { - ErrorHandler.handle('Report in progress', 'Reporting', { - warning: true, - }); - return; - } - this.$rootScope.reportBusy = true; - this.$rootScope.reportStatus = 'Generating report...0%'; - this.$rootScope.$applyAsync(); - - this.vis2png.clear(); - - const rawVisualizations = this.rawVisualizations - .getList() - .filter(this.removeTableVis); - - let idArray = []; - if (tab === 'general') { - idArray = this.removeAgentStatusVis( - rawVisualizations.map(item => item.id), - ); - } else { - idArray = rawVisualizations.map(item => item.id); - } - - for (const item of idArray) { - const tmpHTMLElement = $(`#${item}`); - this.vis2png.assignHTMLItem(item, tmpHTMLElement); - } - - const appliedFilters = await this.visHandlers.getAppliedFilters( - syscollectorFilters, - ); - - const array = await this.vis2png.checkArray(idArray); - const name = `wazuh-${isAgents ? 'agents' : 'overview'}-${tab}-${ - (Date.now() / 1000) | 0 - }.pdf`; - - const browserTimezone = moment.tz.guess(true); - - const data = { - array, - name, - title: isAgents ? `Agents ${tab}` : `Overview ${tab}`, - filters: appliedFilters.filters, - time: appliedFilters.time, - searchBar: appliedFilters.searchBar, - tables: appliedFilters.tables, - tab, - section: isAgents ? 'agents' : 'overview', - isAgents, - browserTimezone, - }; - - await this.genericReq.request('POST', '/reports', data); - - this.$rootScope.reportBusy = false; - this.$rootScope.reportStatus = false; - this.$rootScope.$applyAsync(); - ErrorHandler.info( - 'Success. Go to Dashboard management > Reporting', - 'Reporting', - ); - - return; - } catch (error) { - this.$rootScope.reportBusy = false; - this.$rootScope.reportStatus = false; - throw error; - } - } - - async startConfigReport(obj, type, components) { - try { - this.$rootScope.reportBusy = true; - this.$rootScope.reportStatus = 'Generating PDF document...'; - this.$rootScope.$applyAsync(); - - const docType = - type === 'agentConfig' - ? `wazuh-agent-${obj.id}` - : `wazuh-group-${obj.name}`; - - const name = `${docType}-configuration-${(Date.now() / 1000) | 0}.pdf`; - const browserTimezone = moment.tz.guess(true); - - const data = { - array: [], - name, - filters: [ - type === 'agentConfig' ? { agent: obj.id } : { group: obj.name }, - ], - time: '', - searchBar: '', - tables: [], - tab: type, - browserTimezone, - components, - }; - - await this.genericReq.request('POST', '/reports', data); - - this.$rootScope.reportBusy = false; - this.$rootScope.reportStatus = false; - this.$rootScope.$applyAsync(); - ErrorHandler.info( - 'Success. Go to Dashboard management > Reporting', - 'Reporting', - ); - - return; - } catch (error) { - this.$rootScope.reportBusy = false; - this.$rootScope.reportStatus = false; - this.$rootScope.$applyAsync(); - throw error; - } - } -} From abb19d8805a41bc6a2a9ebff47bf34c91a0c56d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Wed, 27 Mar 2024 13:33:22 +0100 Subject: [PATCH 03/42] feat(reporting): remove unused import --- plugins/main/public/react-services/reporting.js | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/main/public/react-services/reporting.js b/plugins/main/public/react-services/reporting.js index f714d434dc..f263e64b1a 100644 --- a/plugins/main/public/react-services/reporting.js +++ b/plugins/main/public/react-services/reporting.js @@ -10,7 +10,6 @@ * Find more information about this on the LICENSE file. */ -import $ from 'jquery'; import moment from 'moment'; import { WazuhConfig } from '../react-services/wazuh-config'; import { AppState } from './app-state'; From 3bf249c16d6b107de39b789e67dda3df521d0779 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Wed, 27 Mar 2024 14:54:00 +0100 Subject: [PATCH 04/42] feat(reporting): enhance the toast messagen when a PDF report is generated - Add abilities to the toast message when a PDF report is generated: - Open the report - Go to Reporting application --- .../main/public/react-services/reporting.js | 76 ++++++++++++++----- .../server/controllers/wazuh-reporting.ts | 4 + 2 files changed, 63 insertions(+), 17 deletions(-) diff --git a/plugins/main/public/react-services/reporting.js b/plugins/main/public/react-services/reporting.js index f263e64b1a..ef523960b9 100644 --- a/plugins/main/public/react-services/reporting.js +++ b/plugins/main/public/react-services/reporting.js @@ -17,13 +17,23 @@ import { WzRequest } from './wz-request'; import { Vis2PNG } from '../factories/vis2png'; import { RawVisualizations } from '../factories/raw-visualizations'; import { VisHandlers } from '../factories/vis-handlers'; -import { getAngularModule, getDataPlugin, getToasts } from '../kibana-services'; +import { + getAngularModule, + getCore, + getDataPlugin, + getHttp, + getToasts, +} from '../kibana-services'; import { UI_LOGGER_LEVELS } from '../../common/constants'; import { UI_ERROR_SEVERITIES } from './error-orchestrator/types'; import { getErrorOrchestrator } from './common-services'; import store from '../redux/store'; import domtoimage from '../utils/dom-to-image'; import dateMath from '@elastic/datemath'; +import React from 'react'; +import { EuiFlexGroup, EuiFlexItem, EuiButton, EuiLink } from '@elastic/eui'; +import { reporting } from '../utils/applications'; +import { RedirectAppLinks } from '../../../../src/plugins/opensearch_dashboards_react/public'; const app = getAngularModule(); @@ -62,6 +72,50 @@ export class ReportingService { return idArray; } + renderSucessReportsToast({ filename }) { + this.showToast( + 'success', + 'Created report', + <> + + + + + See the reports on + + + + + Reporting + + + + + + + + window.open( + getHttp().basePath.prepend(`/reports/${filename}`), + '_blank', + ) + } + size='s' + > + Open report + + + + , + 1000000, + ); + } + async getVisualizationsFromDOM() { const domVisualizations = document.querySelectorAll('.visualization'); return await Promise.all( @@ -117,18 +171,12 @@ export class ReportingService { tab === 'syscollector' ? `/reports/agents/${agents}/inventory` : `/reports/modules/${tab}`; - await WzRequest.genericReq('POST', apiEndpoint, data); + const response = await WzRequest.genericReq('POST', apiEndpoint, data); this.$rootScope.reportBusy = false; this.$rootScope.reportStatus = false; this.$rootScope.$applyAsync(); - this.showToast( - 'success', - 'Created report', - 'Success. Go to Dashboard management > Reporting', - 4000, - ); - return; + this.renderSucessReportsToast({ filename: response.data.filename }); } catch (error) { this.$rootScope.reportBusy = false; this.$rootScope.reportStatus = false; @@ -168,18 +216,12 @@ export class ReportingService { type === 'agentConfig' ? `/reports/agents/${obj.id}` : `/reports/groups/${obj.name}`; - await WzRequest.genericReq('POST', apiEndpoint, data); + const response = await WzRequest.genericReq('POST', apiEndpoint, data); this.$rootScope.reportBusy = false; this.$rootScope.reportStatus = false; this.$rootScope.$applyAsync(); - this.showToast( - 'success', - 'Created report', - 'Success. Go to Dashboard management > Reporting', - 4000, - ); - return; + this.renderSucessReportsToast({ filename: response.data.filename }); } catch (error) { this.$rootScope.reportBusy = false; this.$rootScope.reportStatus = false; diff --git a/plugins/main/server/controllers/wazuh-reporting.ts b/plugins/main/server/controllers/wazuh-reporting.ts index 3b43daa7cc..e6362fbec2 100644 --- a/plugins/main/server/controllers/wazuh-reporting.ts +++ b/plugins/main/server/controllers/wazuh-reporting.ts @@ -393,6 +393,7 @@ export class WazuhReportingCtrl { body: { success: true, message: `Report ${context.wazuhEndpointParams.filename} was created`, + filename: context.wazuhEndpointParams.filename, }, }); } catch (error) { @@ -687,6 +688,7 @@ export class WazuhReportingCtrl { body: { success: true, message: `Report ${context.wazuhEndpointParams.filename} was created`, + filename: context.wazuhEndpointParams.filename, }, }); } catch (error) { @@ -1026,6 +1028,7 @@ export class WazuhReportingCtrl { body: { success: true, message: `Report ${context.wazuhEndpointParams.filename} was created`, + filename: context.wazuhEndpointParams.filename, }, }); } catch (error) { @@ -1317,6 +1320,7 @@ export class WazuhReportingCtrl { body: { success: true, message: `Report ${context.wazuhEndpointParams.filename} was created`, + filename: context.wazuhEndpointParams.filename, }, }); } catch (error) { From 23454f829ae6cc6ae45e60ed956c679fd4412c69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Wed, 27 Mar 2024 16:27:39 +0100 Subject: [PATCH 05/42] feat(reporting): replace toast title when generating the PDF reports --- plugins/main/public/react-services/reporting.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/main/public/react-services/reporting.js b/plugins/main/public/react-services/reporting.js index ef523960b9..857b35f132 100644 --- a/plugins/main/public/react-services/reporting.js +++ b/plugins/main/public/react-services/reporting.js @@ -75,7 +75,7 @@ export class ReportingService { renderSucessReportsToast({ filename }) { this.showToast( 'success', - 'Created report', + 'Report created', <> @@ -91,7 +91,7 @@ export class ReportingService { path: '', })} > - Reporting + {reporting.title} @@ -112,7 +112,7 @@ export class ReportingService { , - 1000000, + 10000, ); } From 66292159dd19b35ba5c179de162408358b8f3326 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Wed, 24 Apr 2024 08:37:23 +0200 Subject: [PATCH 06/42] fix(reporting): time.from parameter --- plugins/main/public/react-services/reporting.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/main/public/react-services/reporting.js b/plugins/main/public/react-services/reporting.js index 857b35f132..aeea9a8bdc 100644 --- a/plugins/main/public/react-services/reporting.js +++ b/plugins/main/public/react-services/reporting.js @@ -155,7 +155,7 @@ export class ReportingService { filters: dataSourceContext.filters, time: { to: dateMath.parse(dataSourceContext.time.to), - from: dateMath.parse(dataSourceContext.time.to), + from: dateMath.parse(dataSourceContext.time.from), }, searchBar: dataSourceContext?.query?.query || '', tables: [], // TODO: check is this is used From 1386a63371a8443d01ba1b3278f0463425896061 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Thu, 25 Apr 2024 14:39:03 +0200 Subject: [PATCH 07/42] feat(reporting): replace query.getOpenSearchQuery from global source to use the search context --- .../main/public/react-services/reporting.js | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/plugins/main/public/react-services/reporting.js b/plugins/main/public/react-services/reporting.js index aeea9a8bdc..4296aa842c 100644 --- a/plugins/main/public/react-services/reporting.js +++ b/plugins/main/public/react-services/reporting.js @@ -20,9 +20,9 @@ import { VisHandlers } from '../factories/vis-handlers'; import { getAngularModule, getCore, - getDataPlugin, getHttp, getToasts, + getUiSettings, } from '../kibana-services'; import { UI_LOGGER_LEVELS } from '../../common/constants'; import { UI_ERROR_SEVERITIES } from './error-orchestrator/types'; @@ -34,6 +34,11 @@ import React from 'react'; import { EuiFlexGroup, EuiFlexItem, EuiButton, EuiLink } from '@elastic/eui'; import { reporting } from '../utils/applications'; import { RedirectAppLinks } from '../../../../src/plugins/opensearch_dashboards_react/public'; +import { + buildOpenSearchQuery, + buildRangeFilter, + getOpenSearchQueryConfig, +} from '../../../../src/plugins/data/common'; const app = getAngularModule(); @@ -145,14 +150,33 @@ export class ReportingService { const dataSourceContext = searchContext || (await this.getDataSourceSearchContext()); const visualizations = await this.getVisualizationsFromDOM(); - const dataplugin = await getDataPlugin(); - const serverSideQuery = dataplugin.query.getOpenSearchQuery(); + + const timeFilter = + dataSourceContext.time && dataSourceContext.indexPattern.timeFieldName + ? buildRangeFilter( + { + name: dataSourceContext.indexPattern.timeFieldName, + type: 'date', + }, + dataSourceContext.time, + dataSourceContext.indexPattern, + ) + : null; + // Build the filters to use in the server side + // Based on https://github.com/opensearch-project/OpenSearch-Dashboards/blob/2.13.0/src/plugins/data/public/query/query_service.ts#L103-L113 + const serverSideQuery = buildOpenSearchQuery( + dataSourceContext.indexPattern, + dataSourceContext.query, + [...dataSourceContext.filters, ...(timeFilter ? [timeFilter] : [])], + getOpenSearchQueryConfig(getUiSettings()), + ); const browserTimezone = moment.tz.guess(true); const data = { array: visualizations, serverSideQuery, // Used for applying the same filters on the server side requests filters: dataSourceContext.filters, + // TODO: review for Today or This week time: { to: dateMath.parse(dataSourceContext.time.to), from: dateMath.parse(dataSourceContext.time.from), From c18ce401691c0962e8af67b8061e63dc17a9416d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Thu, 25 Apr 2024 15:14:57 +0200 Subject: [PATCH 08/42] fix(reporting): remove isLoading dependency from Generate repot button --- .../common/hooks/use-reporting-communicate-search-context.ts | 1 - .../public/components/common/modules/buttons/generate_report.tsx | 1 - 2 files changed, 2 deletions(-) diff --git a/plugins/main/public/components/common/hooks/use-reporting-communicate-search-context.ts b/plugins/main/public/components/common/hooks/use-reporting-communicate-search-context.ts index d346dcc079..0129672e59 100644 --- a/plugins/main/public/components/common/hooks/use-reporting-communicate-search-context.ts +++ b/plugins/main/public/components/common/hooks/use-reporting-communicate-search-context.ts @@ -8,7 +8,6 @@ import { IIndexPattern } from '../../../../../../src/plugins/data/public'; * @param context */ export function useReportingCommunicateSearchContext(context: { - isLoading: boolean; isSearching: boolean; totalResults: number; indexPattern: IIndexPattern; diff --git a/plugins/main/public/components/common/modules/buttons/generate_report.tsx b/plugins/main/public/components/common/modules/buttons/generate_report.tsx index 1ead2191b5..311658588f 100644 --- a/plugins/main/public/components/common/modules/buttons/generate_report.tsx +++ b/plugins/main/public/components/common/modules/buttons/generate_report.tsx @@ -25,7 +25,6 @@ const mapStateToProps = state => ({ export const ButtonModuleGenerateReport = connect(mapStateToProps)( ({ agent, moduleID, dataSourceSearchContext }) => { const disabledReport = ![ - !dataSourceSearchContext?.isLoading, !dataSourceSearchContext?.isSearching, dataSourceSearchContext?.totalResults, dataSourceSearchContext?.indexPattern, From ee1f4aa81a057ada268cb5b6e791856a6679b0b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 30 Apr 2024 10:47:28 +0200 Subject: [PATCH 09/42] feat(reporting): adapt agent inventory report to data source --- .../components/common/modules/main-agent.tsx | 92 +++++++++++-------- .../main/public/react-services/reporting.js | 21 ++++- 2 files changed, 70 insertions(+), 43 deletions(-) diff --git a/plugins/main/public/components/common/modules/main-agent.tsx b/plugins/main/public/components/common/modules/main-agent.tsx index 6baa5d2ab9..ee36bdac72 100644 --- a/plugins/main/public/components/common/modules/main-agent.tsx +++ b/plugins/main/public/components/common/modules/main-agent.tsx @@ -29,6 +29,14 @@ import { getAngularModule, getCore } from '../../../kibana-services'; import { compose } from 'redux'; import { withGlobalBreadcrumb } from '../hocs'; import { endpointSummary } from '../../../utils/applications'; +import { + AlertsDataSource, + AlertsDataSourceRepository, + PatternDataSource, + tParsedIndexPattern, + useDataSource, +} from '../data-source'; +import { useAsyncAction } from '../hooks'; export class MainModuleAgent extends Component { props!: { @@ -60,43 +68,6 @@ export class MainModuleAgent extends Component { this.router = $injector.get('$route'); } - async startReport() { - this.setState({ loadingReport: true }); - const syscollectorFilters: any[] = []; - const agent = - ( - this.props.agent || - store.getState().appStateReducers.currentAgentData || - {} - ).id || false; - if (this.props.section === 'syscollector' && agent) { - syscollectorFilters.push(this.filterHandler.managerQuery(agent, true)); - syscollectorFilters.push(this.filterHandler.agentQuery(agent)); - } - await this.reportingService.startVis2Png( - this.props.section, - agent, - syscollectorFilters.length ? syscollectorFilters : null, - ); - this.setState({ loadingReport: false }); - } - - renderReportButton() { - return ( - this.props.section === 'syscollector' && ( - - this.startReport()} - > - Generate report - - - ) - ); - } - renderTitle() { return ( @@ -121,7 +92,14 @@ export class MainModuleAgent extends Component { - {this.renderReportButton()} + {this.props.section === 'syscollector' && ( + + + + )} @@ -251,3 +229,41 @@ export default compose( } }), )(MainModuleAgent); + +const GenerateSyscollectorReportButton = ({ agent }) => { + const { + dataSource, + fetchFilters, + isLoading: isDataSourceLoading, + } = useDataSource({ + repository: new AlertsDataSourceRepository(), // this makes only works with alerts index pattern + DataSource: AlertsDataSource, + }); + + const action = useAsyncAction(async () => { + const reportingService = new ReportingService(); + const agentID = + (agent || store.getState().appStateReducers.currentAgentData || {}).id || + false; + await reportingService.startVis2Png('syscollector', agentID, { + indexPattern: dataSource.indexPattern, + query: { query: '', language: 'kuery' }, + filters: fetchFilters, + time: { + from: 'now-1d/d', + to: 'now', + }, + }); + }, [dataSource]); + + return ( + + Generate report + + ); +}; diff --git a/plugins/main/public/react-services/reporting.js b/plugins/main/public/react-services/reporting.js index 4296aa842c..ca081d9d8f 100644 --- a/plugins/main/public/react-services/reporting.js +++ b/plugins/main/public/react-services/reporting.js @@ -172,15 +172,26 @@ export class ReportingService { ); const browserTimezone = moment.tz.guess(true); + /* The report for syscollector uses the keywords for from and to properties. + They are used with the format epoch_millis on the server side to get alerts data from + vulnerable packages. If these values are parsed, will cause an error due to unexpected format. + */ + const time = + tab === 'syscollector' + ? { to: dataSourceContext.time.to, from: dataSourceContext.time.from } + : // FIXME: the Today and This week date ranges on the selector are not working + { + to: dateMath.parse(dataSourceContext.time.to, { roundUp: true }), + from: dateMath.parse(dataSourceContext.time.from, { + roundUp: true, + }), + }; + const data = { array: visualizations, serverSideQuery, // Used for applying the same filters on the server side requests filters: dataSourceContext.filters, - // TODO: review for Today or This week - time: { - to: dateMath.parse(dataSourceContext.time.to), - from: dateMath.parse(dataSourceContext.time.from), - }, + time, searchBar: dataSourceContext?.query?.query || '', tables: [], // TODO: check is this is used tab, From 6fc37b54037827f641dc8300d0e3ed76a66781c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 30 Apr 2024 13:38:32 +0200 Subject: [PATCH 10/42] fix(reporting): fix date range filter for Today and This week special date ranges --- .../components/common/search-bar/search-bar-service.ts | 4 ++-- plugins/main/public/react-services/reporting.js | 9 +++++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/plugins/main/public/components/common/search-bar/search-bar-service.ts b/plugins/main/public/components/common/search-bar/search-bar-service.ts index 641b0c9c1c..cd94435cd6 100644 --- a/plugins/main/public/components/common/search-bar/search-bar-service.ts +++ b/plugins/main/public/components/common/search-bar/search-bar-service.ts @@ -34,7 +34,7 @@ function parseQueryString() { /** * Get the forceNow query parameter */ -function getForceNow() { +export function getForceNow() { const forceNow = parseQueryString().forceNow as string; if (!forceNow) { return; @@ -90,7 +90,7 @@ export const search = async ( gte: dateMath.parse(from).toISOString(), /* roundUp: true is used to transform the osd dateform to a generic date format For instance: the "This week" date range in the date picker. - To: now/w + To: now/w From: now/w Without the roundUp the to and from date will be the same and the search will return no results or error diff --git a/plugins/main/public/react-services/reporting.js b/plugins/main/public/react-services/reporting.js index ca081d9d8f..79fcdd755d 100644 --- a/plugins/main/public/react-services/reporting.js +++ b/plugins/main/public/react-services/reporting.js @@ -39,6 +39,7 @@ import { buildRangeFilter, getOpenSearchQueryConfig, } from '../../../../src/plugins/data/common'; +import { getForceNow } from '../components/common/search-bar/search-bar-service'; const app = getAngularModule(); @@ -179,12 +180,12 @@ export class ReportingService { const time = tab === 'syscollector' ? { to: dataSourceContext.time.to, from: dataSourceContext.time.from } - : // FIXME: the Today and This week date ranges on the selector are not working - { - to: dateMath.parse(dataSourceContext.time.to, { roundUp: true }), - from: dateMath.parse(dataSourceContext.time.from, { + : { + to: dateMath.parse(dataSourceContext.time.to, { roundUp: true, + forceNow: getForceNow(), }), + from: dateMath.parse(dataSourceContext.time.from), }; const data = { From 9e940a672a65f3c1c08b25f4446b4cd5688ed9d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 30 Apr 2024 13:55:04 +0200 Subject: [PATCH 11/42] feat(reporting): adapt the dashboard of Threat Hunting and VirusTotal to the data source --- .../overview/threat-hunting/dashboard/dashboard.tsx | 13 +++++++++++++ .../overview/virustotal/dashboard/dashboard.tsx | 13 +++++++++++++ 2 files changed, 26 insertions(+) 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 e812c2f832..77dbe3c24e 100644 --- a/plugins/main/public/components/overview/threat-hunting/dashboard/dashboard.tsx +++ b/plugins/main/public/components/overview/threat-hunting/dashboard/dashboard.tsx @@ -51,6 +51,7 @@ import { } from '../../../common/data-source'; import { DiscoverNoResults } from '../../../common/no-results/no-results'; import { LoadingSpinner } from '../../../common/loading-spinner/loading-spinner'; +import { useReportingCommunicateSearchContext } from '../../../common/hooks/use-reporting-communicate-search-context'; const plugins = getPlugins(); @@ -134,6 +135,18 @@ const DashboardTH: React.FC = () => { columnVisibility.setVisibleColumns(currentColumns.map(({ id }) => id)); }, [pinnedAgent]); + useReportingCommunicateSearchContext({ + isSearching: isDataSourceLoading, + totalResults: results?.hits?.total ?? 0, + indexPattern: dataSource?.indexPattern, + filters: fetchFilters, + query: query, + time: { + from: dateRangeFrom, + to: dateRangeTo, + }, + }); + useEffect(() => { if (isDataSourceLoading) { return; diff --git a/plugins/main/public/components/overview/virustotal/dashboard/dashboard.tsx b/plugins/main/public/components/overview/virustotal/dashboard/dashboard.tsx index 67ad78581a..512b9cb8d6 100644 --- a/plugins/main/public/components/overview/virustotal/dashboard/dashboard.tsx +++ b/plugins/main/public/components/overview/virustotal/dashboard/dashboard.tsx @@ -24,6 +24,7 @@ import { LoadingSpinner } from '../../../common/loading-spinner/loading-spinner' 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'; const plugins = getPlugins(); @@ -52,6 +53,18 @@ const DashboardVT: React.FC = () => { }); const { query, dateRangeFrom, dateRangeTo } = searchBarProps; + useReportingCommunicateSearchContext({ + isSearching: isDataSourceLoading, + totalResults: results?.hits?.total ?? 0, + indexPattern: dataSource?.indexPattern, + filters: fetchFilters, + query: query, + time: { + from: dateRangeFrom, + to: dateRangeTo, + }, + }); + useEffect(() => { if (isDataSourceLoading) { return; From 73f5cc894ab49bad7746d1a2a4e75db7a814863e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 30 Apr 2024 14:49:27 +0200 Subject: [PATCH 12/42] feat(reporting): adapt the dashboard of MITRE ATT&CK to the data source --- .../overview/mitre/dashboard/dashboard.tsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/plugins/main/public/components/overview/mitre/dashboard/dashboard.tsx b/plugins/main/public/components/overview/mitre/dashboard/dashboard.tsx index baa582ba19..ed2a333210 100644 --- a/plugins/main/public/components/overview/mitre/dashboard/dashboard.tsx +++ b/plugins/main/public/components/overview/mitre/dashboard/dashboard.tsx @@ -23,6 +23,7 @@ import { tParsedIndexPattern, useDataSource, } from '../../../common/data-source'; +import { useReportingCommunicateSearchContext } from '../../../common/hooks/use-reporting-communicate-search-context'; interface DashboardThreatHuntingProps { pinnedAgent: Filter; @@ -56,6 +57,18 @@ export const DashboardMITRE: React.FC = ({ }); const { query, dateRangeFrom, dateRangeTo } = searchBarProps; + useReportingCommunicateSearchContext({ + isSearching: isDataSourceLoading, + totalResults: results?.hits?.total ?? 0, + indexPattern: dataSource?.indexPattern, + filters: fetchFilters, + query: query, + time: { + from: dateRangeFrom, + to: dateRangeTo, + }, + }); + useEffect(() => { if (isDataSourceLoading) { return; From 17bc7f3561e3d390388b10871235c15899670d7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 30 Apr 2024 14:51:05 +0200 Subject: [PATCH 13/42] fix: remove unused props and imports --- .../components/overview/mitre/dashboard/dashboard.tsx | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/plugins/main/public/components/overview/mitre/dashboard/dashboard.tsx b/plugins/main/public/components/overview/mitre/dashboard/dashboard.tsx index ed2a333210..56de38ff3a 100644 --- a/plugins/main/public/components/overview/mitre/dashboard/dashboard.tsx +++ b/plugins/main/public/components/overview/mitre/dashboard/dashboard.tsx @@ -4,7 +4,6 @@ import { ViewMode } from '../../../../../../../src/plugins/embeddable/public'; import { getDashboardPanels } from './dashboard_panels'; import { I18nProvider } from '@osd/i18n/react'; import useSearchBar from '../../../common/search-bar/use-search-bar'; -import { Filter } from '../../../../../../../src/plugins/data/common'; import { SampleDataWarning } from '../../../visualize/components'; import { IndexPattern } from '../../../../../../../src/plugins/data/common'; import { @@ -25,17 +24,11 @@ import { } from '../../../common/data-source'; import { useReportingCommunicateSearchContext } from '../../../common/hooks/use-reporting-communicate-search-context'; -interface DashboardThreatHuntingProps { - pinnedAgent: Filter; -} - const plugins = getPlugins(); const SearchBar = getPlugins().data.ui.SearchBar; const DashboardByRenderer = plugins.dashboard.DashboardContainerByValueRenderer; -export const DashboardMITRE: React.FC = ({ - pinnedAgent, -}) => { +export const DashboardMITRE: React.FC = () => { const { filters, dataSource, From 456c3dc45e4b00cf4fbfe811efea7cadbf5d7c9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Thu, 2 May 2024 14:40:26 +0200 Subject: [PATCH 14/42] feat(reporting): adapt the dashboard of Amazon Web Services to the data source --- .../amazon-web-services/dashboards/dashboard.tsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) 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 e29d7609f5..000ad37c67 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 @@ -24,6 +24,7 @@ import { } from '../../../common/data-source'; import { DiscoverNoResults } from '../../../common/no-results/no-results'; import { LoadingSpinner } from '../../../common/loading-spinner/loading-spinner'; +import { useReportingCommunicateSearchContext } from '../../../common/hooks/use-reporting-communicate-search-context'; const plugins = getPlugins(); @@ -54,6 +55,18 @@ const DashboardAWSComponents: React.FC = ({}) => { const { query, dateRangeFrom, dateRangeTo } = searchBarProps; + useReportingCommunicateSearchContext({ + isSearching: isDataSourceLoading, + totalResults: results?.hits?.total ?? 0, + indexPattern: dataSource?.indexPattern, + filters: fetchFilters, + query: query, + time: { + from: dateRangeFrom, + to: dateRangeTo, + }, + }); + useEffect(() => { if (isDataSourceLoading) { return; From 315298e58d1dab715b93f47f6b371095211c6070 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Thu, 2 May 2024 14:41:15 +0200 Subject: [PATCH 15/42] fix(reporting): error converting DOM node from map visualizations to image --- plugins/main/public/utils/dom-to-image.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugins/main/public/utils/dom-to-image.js b/plugins/main/public/utils/dom-to-image.js index 9e07aa916b..ec88dc9590 100644 --- a/plugins/main/public/utils/dom-to-image.js +++ b/plugins/main/public/utils/dom-to-image.js @@ -477,7 +477,9 @@ resolve(image); }; image.onerror = reject; - image.src = uri; + // Wazuh: fix an error creating image from map visualizations + // https://github.com/tsayen/dom-to-image/issues/243#issuecomment-414955354 + image.src = encodeURI(uri); }); } From 792ea78695acdae525dc1b7c758b3614bd9d6b96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Thu, 2 May 2024 15:27:00 +0200 Subject: [PATCH 16/42] feat(reporting): adapt the dashboard of File Integrity Monitoring to the data source --- .../components/overview/fim/dashboard/dashboard.tsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/plugins/main/public/components/overview/fim/dashboard/dashboard.tsx b/plugins/main/public/components/overview/fim/dashboard/dashboard.tsx index 0aeebbbf75..30ffff8c64 100644 --- a/plugins/main/public/components/overview/fim/dashboard/dashboard.tsx +++ b/plugins/main/public/components/overview/fim/dashboard/dashboard.tsx @@ -24,6 +24,7 @@ import { } from '../../../common/data-source'; import { DiscoverNoResults } from '../../../common/no-results/no-results'; import { LoadingSpinner } from '../../../common/loading-spinner/loading-spinner'; +import { useReportingCommunicateSearchContext } from '../../../common/hooks/use-reporting-communicate-search-context'; const plugins = getPlugins(); @@ -54,6 +55,18 @@ const DashboardFIMComponent: React.FC = ({}) => { const { query, dateRangeFrom, dateRangeTo } = searchBarProps; + useReportingCommunicateSearchContext({ + isSearching: isDataSourceLoading, + totalResults: results?.hits?.total ?? 0, + indexPattern: dataSource?.indexPattern, + filters: fetchFilters, + query: query, + time: { + from: dateRangeFrom, + to: dateRangeTo, + }, + }); + useEffect(() => { if (isDataSourceLoading) { return; From c4e35311c9bdad07e324d3f65812884dae52ed9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Fri, 3 May 2024 09:22:52 +0200 Subject: [PATCH 17/42] feat(reporting): adapt the dashboard of Malware Detection to the data source --- .../malware-detection/dashboard/dashboard.tsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) 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 ae2859eb6a..c786492f60 100644 --- a/plugins/main/public/components/overview/malware-detection/dashboard/dashboard.tsx +++ b/plugins/main/public/components/overview/malware-detection/dashboard/dashboard.tsx @@ -24,6 +24,7 @@ import { } from '../../../common/data-source'; import { DiscoverNoResults } from '../../../common/no-results/no-results'; import { LoadingSpinner } from '../../../common/loading-spinner/loading-spinner'; +import { useReportingCommunicateSearchContext } from '../../../common/hooks/use-reporting-communicate-search-context'; const plugins = getPlugins(); @@ -54,6 +55,18 @@ const DashboardMalwareDetectionComponent: React.FC = ({}) => { const { query, dateRangeFrom, dateRangeTo } = searchBarProps; + useReportingCommunicateSearchContext({ + isSearching: isDataSourceLoading, + totalResults: results?.hits?.total ?? 0, + indexPattern: dataSource?.indexPattern, + filters: fetchFilters, + query: query, + time: { + from: dateRangeFrom, + to: dateRangeTo, + }, + }); + useEffect(() => { if (isDataSourceLoading) { return; From 0fdf767c84e114902017cb957a0cfcc2b0efa158 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Fri, 3 May 2024 14:02:57 +0200 Subject: [PATCH 18/42] feat(reporting): adapt the dashboard of Docker to the data source --- .../overview/docker/dashboards/dashboard.tsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/plugins/main/public/components/overview/docker/dashboards/dashboard.tsx b/plugins/main/public/components/overview/docker/dashboards/dashboard.tsx index a3c57ca0ce..8eb991f6c3 100644 --- a/plugins/main/public/components/overview/docker/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/docker/dashboards/dashboard.tsx @@ -24,6 +24,7 @@ import { } from '../../../common/data-source'; import { DiscoverNoResults } from '../../../common/no-results/no-results'; import { LoadingSpinner } from '../../../common/loading-spinner/loading-spinner'; +import { useReportingCommunicateSearchContext } from '../../../common/hooks/use-reporting-communicate-search-context'; const plugins = getPlugins(); @@ -54,6 +55,18 @@ const DashboardDockerComponent: React.FC = ({}) => { const { query, dateRangeFrom, dateRangeTo } = searchBarProps; + useReportingCommunicateSearchContext({ + isSearching: isDataSourceLoading, + totalResults: results?.hits?.total ?? 0, + indexPattern: dataSource?.indexPattern, + filters: fetchFilters, + query: query, + time: { + from: dateRangeFrom, + to: dateRangeTo, + }, + }); + useEffect(() => { if (isDataSourceLoading) { return; From acb073fd0b3f99e954fe19b7342eb2eabd2689f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Mon, 6 May 2024 10:10:38 +0200 Subject: [PATCH 19/42] feat(reporting): adapt the dashboard of Google Cloud to the data source --- .../google-cloud/dashboards/dashboard.tsx | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) 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 b894f88785..1e25cf05f4 100644 --- a/plugins/main/public/components/overview/google-cloud/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/google-cloud/dashboards/dashboard.tsx @@ -23,6 +23,7 @@ import { import { AlertsGoogleCloudDataSource } from '../../../common/data-source/pattern/alerts/alerts-google-cloud/alerts-google-cloud-data-source'; import { DiscoverNoResults } from '../../../common/no-results/no-results'; import { LoadingSpinner } from '../../../common/loading-spinner/loading-spinner'; +import { useReportingCommunicateSearchContext } from '../../../common/hooks/use-reporting-communicate-search-context'; const plugins = getPlugins(); @@ -53,6 +54,18 @@ const DashboardGoogleCloudComponent: React.FC = () => { const { query, dateRangeFrom, dateRangeTo } = searchBarProps; + useReportingCommunicateSearchContext({ + isSearching: isDataSourceLoading, + totalResults: results?.hits?.total ?? 0, + indexPattern: dataSource?.indexPattern, + filters: fetchFilters, + query: query, + time: { + from: dateRangeFrom, + to: dateRangeTo, + }, + }); + useEffect(() => { if (isDataSourceLoading) { return; @@ -101,8 +114,8 @@ const DashboardGoogleCloudComponent: React.FC = () => { ) : null} {dataSource && results?.hits?.total > 0 ? ( - <> - + <> +
Date: Mon, 6 May 2024 10:11:48 +0200 Subject: [PATCH 20/42] fix(google-cloud): add missing button to generate the report on Dashboard tab --- .../main/public/components/common/modules/modules-defaults.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/main/public/components/common/modules/modules-defaults.tsx b/plugins/main/public/components/common/modules/modules-defaults.tsx index 8628c6fb6e..33e402b6c3 100644 --- a/plugins/main/public/components/common/modules/modules-defaults.tsx +++ b/plugins/main/public/components/common/modules/modules-defaults.tsx @@ -156,7 +156,7 @@ export const ModulesDefaults = { id: 'dashboard', name: 'Dashboard', component: DashboardGoogleCloud, - buttons: [ButtonModuleExploreAgent], + buttons: [ButtonModuleExploreAgent, ButtonModuleGenerateReport], }, renderDiscoverTab({ tableColumns: googleCloudColumns, From 3c742c09a7d19b3aa906a333ac6ade56b6e0d497 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Mon, 6 May 2024 15:21:28 +0200 Subject: [PATCH 21/42] fix(reporting): malformed table row error due to missing columns on the row for summary table when the agregations should not return buckets - Add tests --- .../lib/reporting/summary-table.test.ts | 125 ++++++++++++++++++ .../server/lib/reporting/summary-table.ts | 42 ++++-- 2 files changed, 158 insertions(+), 9 deletions(-) create mode 100644 plugins/main/server/lib/reporting/summary-table.test.ts diff --git a/plugins/main/server/lib/reporting/summary-table.test.ts b/plugins/main/server/lib/reporting/summary-table.test.ts new file mode 100644 index 0000000000..1629d5b234 --- /dev/null +++ b/plugins/main/server/lib/reporting/summary-table.test.ts @@ -0,0 +1,125 @@ +import SummaryTable from './summary-table'; +import overviewSummaryTableDefinitions from './summary-tables-definitions/overview/index'; + +describe('Summary table', () => { + it.skip.each` + summarySetup | columns + ${overviewSummaryTableDefinitions.general[0]} | ${['Rule ID', 'Description', 'Level', 'Count']} + `('get columns from summary setup', ({ summarySetup, columns }) => { + const summaryTable = new SummaryTable( + {}, + 'now/1h', + 'now', + [], + [], + summarySetup, + 'pattern', + ); + + expect(summaryTable._columns).toEqual(columns); + }); + + it.each` + aggregationsResponse | summarySetup | title | columns | rows + ${{ '2': { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ + '3': { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [], + }, + key: '4507', + doc_count: 5, + }, { + '3': { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ + '4': { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [], + }, + key: '4508 - Description', + doc_count: 6, + }], + }, + key: '4508', + doc_count: 8, + }, { + '3': { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ + '4': { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ + '5': { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [], + }, + key: 10, + doc_count: 5, + }], + }, + key: '4509 - Description', + doc_count: 21, + }], + }, + key: '4509', + doc_count: 30, + }, { + '3': { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ + '4': { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [{ + '5': { + doc_count_error_upper_bound: 0, + sum_other_doc_count: 0, + buckets: [], + }, + key: 100, + doc_count: 12, + }], + }, + key: '4510 - Description', + doc_count: 14, + }], + }, + key: '4510', + doc_count: 50, + }], + } }} | ${overviewSummaryTableDefinitions.general[0]} | ${'Alerts summary'} | ${['Rule ID', 'Description', 'Level', 'Count']} | ${[['4507', undefined, undefined, 5], ['4508', '4508 - Description', undefined, 6], ['4509', '4509 - Description', 10, 5], ['4510', '4510 - Description', 100, 12]]} + `( + 'format response to table', + ({ aggregationsResponse, summarySetup, title, columns, rows }) => { + const summaryTable = new SummaryTable( + {}, + 'now/1h', + 'now', + [], + [], + summarySetup, + 'pattern', + ); + + expect( + summaryTable._formatResponseToTable(aggregationsResponse).title, + ).toBe(title); + expect( + summaryTable._formatResponseToTable(aggregationsResponse).columns, + ).toEqual(columns); + expect( + summaryTable._formatResponseToTable(aggregationsResponse).rows, + ).toEqual(rows); + }, + ); +}); diff --git a/plugins/main/server/lib/reporting/summary-table.ts b/plugins/main/server/lib/reporting/summary-table.ts index 4bf31ab408..051f7491fe 100644 --- a/plugins/main/server/lib/reporting/summary-table.ts +++ b/plugins/main/server/lib/reporting/summary-table.ts @@ -101,7 +101,7 @@ export default class SummaryTable { this._rows = rawResponse[firstKey].buckets.reduce((totalRows, bucket) => { const nextKey = firstKey + 1; - this._buildRow(bucket, nextKey, totalRows); + this._buildRow(bucket, nextKey, totalRows, this._columns.length); return totalRows; }, []); @@ -122,17 +122,41 @@ export default class SummaryTable { bucket: any, nextAggKey: number, totalRows: any[], + totalColumns: number, row: any[] = [], ): any[] { const newRow = [...row, bucket.key]; - // If there is a next aggregation, repeat the process - if (bucket[nextAggKey.toString()]?.buckets?.length) { - bucket[nextAggKey.toString()].buckets.forEach(newBucket => { - this._buildRow(newBucket, nextAggKey + 1, totalRows, newRow); - }); - } - // Add the Count as the last item in the row - else if (bucket.doc_count) { + const indexColumn = newRow.length - 1; + + if (indexColumn < totalColumns - 1) { + // If there is a next aggregation, repeat the process + if (bucket[nextAggKey.toString()]?.buckets?.length) { + bucket[nextAggKey.toString()].buckets.forEach(newBucket => { + this._buildRow( + newBucket, + nextAggKey + 1, + totalRows, + totalColumns, + newRow, + ); + }); + } else { + // Calculate the cells to fill due to the aggregation buckets are missing + // The last column is the Count and this value is coming from the last bucket available + // totalColumns starts from 1. totalColumns - 1 gets the index of the last column + // indexColumn starts from 0 + const fillCellsLength = totalColumns - 1 - indexColumn - 1; + /* Fill the row with undefined values. + Note: The undefined values are mapped to `"-"` on the methods of the reporting. + */ + if (fillCellsLength) { + newRow.push(...Array.from({ length: fillCellsLength })); + } + newRow.push(bucket.doc_count); + totalRows.push(newRow); + } + // Add the Count as the last item in the row + } else { newRow.push(bucket.doc_count); totalRows.push(newRow); } From 2f4a4f037a06891bdd0ebc81995164d995c3fdd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 7 May 2024 08:37:51 +0200 Subject: [PATCH 22/42] fix: typo --- plugins/main/public/components/settings/api/api-table.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/main/public/components/settings/api/api-table.js b/plugins/main/public/components/settings/api/api-table.js index 3b18de2d26..edb1982251 100644 --- a/plugins/main/public/components/settings/api/api-table.js +++ b/plugins/main/public/components/settings/api/api-table.js @@ -727,7 +727,7 @@ export const ApiTable = compose( @@ -735,7 +735,7 @@ export const ApiTable = compose( { const steps = [ From fe1799e84d5a50752f5725f3a431d8ae35c430a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 14 May 2024 13:51:30 +0200 Subject: [PATCH 23/42] feat(reporting): adapt the dashboard of PCI DSS to the data source --- .../overview/pci/dashboards/dashboard.tsx | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/plugins/main/public/components/overview/pci/dashboards/dashboard.tsx b/plugins/main/public/components/overview/pci/dashboards/dashboard.tsx index 4e289ca97c..3e878a6e2c 100644 --- a/plugins/main/public/components/overview/pci/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/pci/dashboards/dashboard.tsx @@ -24,6 +24,7 @@ import { import { PCIDSSDataSource } from '../../../common/data-source/pattern/alerts/pci-dss/pci-dss-data-source'; import { DiscoverNoResults } from '../../../common/no-results/no-results'; import { LoadingSpinner } from '../../../common/loading-spinner/loading-spinner'; +import { useReportingCommunicateSearchContext } from '../../../common/hooks/use-reporting-communicate-search-context'; const plugins = getPlugins(); @@ -54,6 +55,18 @@ const DashboardPCIDSSComponent: React.FC = () => { const { query, dateRangeFrom, dateRangeTo } = searchBarProps; + useReportingCommunicateSearchContext({ + isSearching: isDataSourceLoading, + totalResults: results?.hits?.total ?? 0, + indexPattern: dataSource?.indexPattern, + filters: fetchFilters, + query: query, + time: { + from: dateRangeFrom, + to: dateRangeTo, + }, + }); + useEffect(() => { if (isDataSourceLoading) { return; @@ -89,16 +102,16 @@ const DashboardPCIDSSComponent: React.FC = () => { {isDataSourceLoading && !dataSource ? ( ) : ( -
- -
- )} +
+ +
+ )} {dataSource && results?.hits?.total === 0 ? ( ) : null} From d6a86fb77e08eee26d280327b1f2b14a8d68d6a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 14 May 2024 13:51:41 +0200 Subject: [PATCH 24/42] feat(reporting): adapt the dashboard of GDPR to the data source --- .../overview/gdpr/dashboards/dashboard.tsx | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/plugins/main/public/components/overview/gdpr/dashboards/dashboard.tsx b/plugins/main/public/components/overview/gdpr/dashboards/dashboard.tsx index e1deaa203e..7e14a64a63 100644 --- a/plugins/main/public/components/overview/gdpr/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/gdpr/dashboards/dashboard.tsx @@ -24,6 +24,7 @@ import { tParsedIndexPattern, useDataSource, } from '../../../common/data-source'; +import { useReportingCommunicateSearchContext } from '../../../common/hooks/use-reporting-communicate-search-context'; const plugins = getPlugins(); @@ -53,6 +54,18 @@ const DashboardGDPRComponent: React.FC = () => { const { query, dateRangeFrom, dateRangeTo } = searchBarProps; + useReportingCommunicateSearchContext({ + isSearching: isDataSourceLoading, + totalResults: results?.hits?.total ?? 0, + indexPattern: dataSource?.indexPattern, + filters: fetchFilters, + query: query, + time: { + from: dateRangeFrom, + to: dateRangeTo, + }, + }); + useEffect(() => { if (isDataSourceLoading) { return; @@ -88,16 +101,16 @@ const DashboardGDPRComponent: React.FC = () => { {isDataSourceLoading && !dataSource ? ( ) : ( -
- -
- )} +
+ +
+ )} {dataSource && results?.hits?.total === 0 ? ( ) : null} From ea19ee92e24e9c7e9e3b049981fa7a1d257103a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 14 May 2024 13:51:55 +0200 Subject: [PATCH 25/42] feat(reporting): adapt the dashboard of HIPAA to the data source --- .../overview/hipaa/dashboards/dashboard.tsx | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/plugins/main/public/components/overview/hipaa/dashboards/dashboard.tsx b/plugins/main/public/components/overview/hipaa/dashboards/dashboard.tsx index 85f1aed105..6e773cb83f 100644 --- a/plugins/main/public/components/overview/hipaa/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/hipaa/dashboards/dashboard.tsx @@ -24,6 +24,7 @@ import { useDataSource, } from '../../../common/data-source'; import { HIPAADataSource } from '../../../common/data-source/pattern/alerts/hipaa/hipaa-data-source'; +import { useReportingCommunicateSearchContext } from '../../../common/hooks/use-reporting-communicate-search-context'; const plugins = getPlugins(); @@ -53,6 +54,18 @@ const DashboardHIPAAComponent: React.FC = () => { const { query, dateRangeFrom, dateRangeTo } = searchBarProps; + useReportingCommunicateSearchContext({ + isSearching: isDataSourceLoading, + totalResults: results?.hits?.total ?? 0, + indexPattern: dataSource?.indexPattern, + filters: fetchFilters, + query: query, + time: { + from: dateRangeFrom, + to: dateRangeTo, + }, + }); + useEffect(() => { if (isDataSourceLoading) { return; @@ -89,16 +102,16 @@ const DashboardHIPAAComponent: React.FC = () => { {isDataSourceLoading && !dataSource ? ( ) : ( -
- -
- )} +
+ +
+ )} {dataSource && results?.hits?.total === 0 ? ( ) : null} From 70d4ad42c8961c36628f41b15fa0305c926ed1ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 14 May 2024 13:52:06 +0200 Subject: [PATCH 26/42] feat(reporting): adapt the dashboard of NIST 800-53 to the data source --- .../overview/nist/dashboards/dashboard.tsx | 33 +++++++++++++------ 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx b/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx index 2be2bfcf59..301b3d1c85 100644 --- a/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx @@ -24,6 +24,7 @@ import { tParsedIndexPattern, useDataSource, } from '../../../common/data-source'; +import { useReportingCommunicateSearchContext } from '../../../common/hooks/use-reporting-communicate-search-context'; const plugins = getPlugins(); @@ -53,6 +54,18 @@ const DashboardNIST80053Component: React.FC = () => { const { query, dateRangeFrom, dateRangeTo } = searchBarProps; + useReportingCommunicateSearchContext({ + isSearching: isDataSourceLoading, + totalResults: results?.hits?.total ?? 0, + indexPattern: dataSource?.indexPattern, + filters: fetchFilters, + query: query, + time: { + from: dateRangeFrom, + to: dateRangeTo, + }, + }); + useEffect(() => { if (isDataSourceLoading) { return; @@ -88,16 +101,16 @@ const DashboardNIST80053Component: React.FC = () => { {isDataSourceLoading && !dataSource ? ( ) : ( -
- -
- )} +
+ +
+ )} {dataSource && results?.hits?.total === 0 ? ( ) : null} From e1c37a3da56d8ad3884381a0575b6e90c8940c62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 14 May 2024 13:52:34 +0200 Subject: [PATCH 27/42] feat(reporting): adapt the dashboard of TSC to the data source --- .../overview/tsc/dashboards/dashboard.tsx | 225 +++++++++--------- 1 file changed, 119 insertions(+), 106 deletions(-) diff --git a/plugins/main/public/components/overview/tsc/dashboards/dashboard.tsx b/plugins/main/public/components/overview/tsc/dashboards/dashboard.tsx index fb49fd59b7..071d08256d 100644 --- a/plugins/main/public/components/overview/tsc/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/tsc/dashboards/dashboard.tsx @@ -11,19 +11,20 @@ import { DiscoverNoResults } from '../../../common/no-results/no-results'; import { LoadingSpinner } from '../../../common/loading-spinner/loading-spinner'; import { IndexPattern } from '../../../../../../../src/plugins/data/common'; import { - ErrorFactory, - ErrorHandler, - HttpError, + ErrorFactory, + ErrorHandler, + HttpError, } from '../../../../react-services/error-management'; import { compose } from 'redux'; import { SampleDataWarning } from '../../../visualize/components'; import { TSCDataSource } from '../../../common/data-source/pattern/alerts/tsc/tsc-data-souce'; import { - AlertsDataSourceRepository, - PatternDataSource, - tParsedIndexPattern, - useDataSource, + AlertsDataSourceRepository, + PatternDataSource, + tParsedIndexPattern, + useDataSource, } from '../../../common/data-source'; +import { useReportingCommunicateSearchContext } from '../../../common/hooks/use-reporting-communicate-search-context'; const plugins = getPlugins(); @@ -32,111 +33,123 @@ const SearchBar = getPlugins().data.ui.SearchBar; const DashboardByRenderer = plugins.dashboard.DashboardContainerByValueRenderer; const DashboardTSCComponent: React.FC = () => { - const { - filters, - dataSource, - fetchFilters, - isLoading: isDataSourceLoading, - fetchData, - setFilters, - } = useDataSource({ - DataSource: TSCDataSource, - repository: new AlertsDataSourceRepository(), - }); - const [results, setResults] = useState({} as SearchResponse); + const { + filters, + dataSource, + fetchFilters, + isLoading: isDataSourceLoading, + fetchData, + setFilters, + } = useDataSource({ + DataSource: TSCDataSource, + repository: new AlertsDataSourceRepository(), + }); + const [results, setResults] = useState({} as SearchResponse); - const { searchBarProps } = useSearchBar({ - indexPattern: dataSource?.indexPattern as IndexPattern, - filters, - setFilters, - }); + const { searchBarProps } = useSearchBar({ + indexPattern: dataSource?.indexPattern as IndexPattern, + filters, + setFilters, + }); - const { query, dateRangeFrom, dateRangeTo } = searchBarProps; + const { query, dateRangeFrom, dateRangeTo } = searchBarProps; - useEffect(() => { - if (isDataSourceLoading) { - return; - } - fetchData({ - query, - dateRange: { - from: dateRangeFrom, - to: dateRangeTo, - }, - }) - .then(results => { - setResults(results); - }) - .catch(error => { - const searchError = ErrorFactory.create(HttpError, { - error, - message: 'Error fetching alerts', - }); - ErrorHandler.handleError(searchError); - }); - }, [ - JSON.stringify(fetchFilters), - JSON.stringify(query), - JSON.stringify(dateRangeFrom), - JSON.stringify(dateRangeTo), - ]); + useReportingCommunicateSearchContext({ + isSearching: isDataSourceLoading, + totalResults: results?.hits?.total ?? 0, + indexPattern: dataSource?.indexPattern, + filters: fetchFilters, + query: query, + time: { + from: dateRangeFrom, + to: dateRangeTo, + }, + }); - return ( + useEffect(() => { + if (isDataSourceLoading) { + return; + } + fetchData({ + query, + dateRange: { + from: dateRangeFrom, + to: dateRangeTo, + }, + }) + .then(results => { + setResults(results); + }) + .catch(error => { + const searchError = ErrorFactory.create(HttpError, { + error, + message: 'Error fetching alerts', + }); + ErrorHandler.handleError(searchError); + }); + }, [ + JSON.stringify(fetchFilters), + JSON.stringify(query), + JSON.stringify(dateRangeFrom), + JSON.stringify(dateRangeTo), + ]); + + return ( + <> + <> - - <> - {isDataSourceLoading && !dataSource ? ( - - ) : ( -
- -
- )} - {dataSource && results?.hits?.total === 0 ? ( - - ) : null} - {dataSource && results?.hits?.total > 0 ? ( - <> - -
- -
- - ) : null} - -
+ {isDataSourceLoading && !dataSource ? ( + + ) : ( +
+ +
+ )} + {dataSource && results?.hits?.total === 0 ? ( + + ) : null} + {dataSource && results?.hits?.total > 0 ? ( + <> + +
+ +
+ + ) : null} - ); +
+ + ); }; export const DashboardTSC = compose(withErrorBoundary)(DashboardTSCComponent); From 1eb61fa0a224794d0c951efb51f3a20f7ff72941 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 14 May 2024 13:55:41 +0200 Subject: [PATCH 28/42] feat(reporting): adapt the dashboard of GitHub to the data source --- .../overview/github/dashboards/dashboard.tsx | 36 ++++++++++++------- 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/plugins/main/public/components/overview/github/dashboards/dashboard.tsx b/plugins/main/public/components/overview/github/dashboards/dashboard.tsx index 89c7b6d360..c97ed96c73 100644 --- a/plugins/main/public/components/overview/github/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/github/dashboards/dashboard.tsx @@ -24,7 +24,7 @@ import { useDataSource, } from '../../../common/data-source'; import { GitHubDataSource } from '../../../common/data-source/pattern/alerts/github/github-data-source'; - +import { useReportingCommunicateSearchContext } from '../../../common/hooks/use-reporting-communicate-search-context'; const plugins = getPlugins(); @@ -56,7 +56,19 @@ const DashboardGitHubComponent: React.FC = () => { setFilters, }); - const { query } = searchBarProps; + const { query, dateRangeFrom, dateRangeTo } = searchBarProps; + + useReportingCommunicateSearchContext({ + isSearching: isDataSourceLoading, + totalResults: results?.hits?.total ?? 0, + indexPattern: dataSource?.indexPattern, + filters: fetchFilters, + query: query, + time: { + from: dateRangeFrom, + to: dateRangeTo, + }, + }); useEffect(() => { if (isDataSourceLoading) { @@ -84,16 +96,16 @@ const DashboardGitHubComponent: React.FC = () => { {isDataSourceLoading && !dataSource ? ( ) : ( -
- -
- )} +
+ +
+ )} {dataSource && results?.hits?.total === 0 ? ( ) : null} From 71f35d8db0818cf1bfcabc183099e09652112ffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 14 May 2024 13:58:07 +0200 Subject: [PATCH 29/42] fix(github): fix request related to get available data on Dashboard --- .../components/overview/github/dashboards/dashboard.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/main/public/components/overview/github/dashboards/dashboard.tsx b/plugins/main/public/components/overview/github/dashboards/dashboard.tsx index c97ed96c73..0a7b115fdb 100644 --- a/plugins/main/public/components/overview/github/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/github/dashboards/dashboard.tsx @@ -87,7 +87,12 @@ const DashboardGitHubComponent: React.FC = () => { }); ErrorHandler.handleError(searchError); }); - }, [JSON.stringify(fetchFilters), JSON.stringify(query)]); + }, [ + JSON.stringify(fetchFilters), + JSON.stringify(query), + JSON.stringify(dateRangeFrom), + JSON.stringify(dateRangeTo), + ]); return ( <> From 4a18fd51e0eb352f04c32ed724018faa1b55a221 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 14 May 2024 14:06:07 +0200 Subject: [PATCH 30/42] chore: move the import of PCI DSS data source --- .../main/public/components/common/modules/modules-defaults.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/main/public/components/common/modules/modules-defaults.tsx b/plugins/main/public/components/common/modules/modules-defaults.tsx index c70e48d121..3b44fe9d65 100644 --- a/plugins/main/public/components/common/modules/modules-defaults.tsx +++ b/plugins/main/public/components/common/modules/modules-defaults.tsx @@ -58,7 +58,6 @@ import { DashboardFIM } from '../../overview/fim/dashboard/dashboard'; import { DashboardNIST80053 } from '../../overview/nist/dashboards/dashboard'; import { DashboardHIPAA } from '../../overview/hipaa/dashboards/dashboard'; import { DashboardTSC } from '../../overview/tsc/dashboards/dashboard'; -import { PCIDSSDataSource } from '../data-source/pattern/alerts/pci-dss/pci-dss-data-source'; import { DockerDataSource, AlertsDataSource, @@ -75,6 +74,7 @@ import { GDPRDataSource, ConfigurationAssessmentDataSource, HIPAADataSource, + PCIDSSDataSource, } from '../data-source'; const ALERTS_INDEX_PATTERN = 'wazuh-alerts-*'; From 5ecb887892d3f92f2ac80366baa3b58748b478b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 14 May 2024 14:11:04 +0200 Subject: [PATCH 31/42] fix(github): request to get the available data did not take into account the date range --- .../components/overview/github/dashboards/dashboard.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugins/main/public/components/overview/github/dashboards/dashboard.tsx b/plugins/main/public/components/overview/github/dashboards/dashboard.tsx index 0a7b115fdb..84408484ae 100644 --- a/plugins/main/public/components/overview/github/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/github/dashboards/dashboard.tsx @@ -76,6 +76,10 @@ const DashboardGitHubComponent: React.FC = () => { } fetchData({ query, + dateRange: { + to: dateRangeTo, + from: dateRangeFrom, + }, }) .then(results => { setResults(results); From 050af20993dde1a31e12738616c091c399b294d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 14 May 2024 15:08:49 +0200 Subject: [PATCH 32/42] remove: unused RegulatoryComplianceTabs --- .../components/common/modules/modules-defaults.tsx | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/plugins/main/public/components/common/modules/modules-defaults.tsx b/plugins/main/public/components/common/modules/modules-defaults.tsx index 3b44fe9d65..809d0beb82 100644 --- a/plugins/main/public/components/common/modules/modules-defaults.tsx +++ b/plugins/main/public/components/common/modules/modules-defaults.tsx @@ -96,17 +96,6 @@ const renderDiscoverTab = (props: WazuhDiscoverProps) => { }; }; -const RegulatoryComplianceTabs = columns => [ - DashboardTab, - { - id: 'inventory', - name: 'Controls', - buttons: [ButtonModuleExploreAgent], - component: ComplianceTable, - }, - renderDiscoverTab(DEFAULT_INDEX_PATTERN, columns), -]; - export const ModulesDefaults = { general: { init: 'events', From 70d721aa460d4470a0eee1f03f82a46bbbc5cda3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 14 May 2024 15:34:29 +0200 Subject: [PATCH 33/42] changelog: add pull request entry --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8abef82d09..5911b35699 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,11 +15,12 @@ All notable changes to the Wazuh app project will be documented in this file. - Added macOS log collector tab [#6545](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6545) - Add ability to disable the edition of configuration through API endpoints and UI [#6557](https://github.com/wazuh/wazuh-dashboard-plugins/issues/6557) - Added journald log collector tab [#6572](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6572) +- Added ability to open the report file or Reporting application from the toast message [#6558](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6558) ### Changed - Removed embedded discover [#6120](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6120) [#6235](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6235) [#6254](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6254) [#6285](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6285) [#6288](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6288) [#6290](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6290) [#6289](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6289) [#6286](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6286) [#6275](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6275) [#6287](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6287) [#6297](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6297) [#6291](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6287) [#6459](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6459) [#6434](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6434) [#6504](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6504) [#6649](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6649) [#6506](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6506) -- Develop logic of a new index for the fim module [#6227](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6227) +- Develop logic of a new index for the fim module [#6227](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6227) [#6558](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6558) - Allow editing groups for an agent from Endpoints Summary [#6250](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6250) - Change how the configuration is managed in the backend side [#6337](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6337) [#6519](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6519) [#6573](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6573) - Change the view of API is down and check connection to Server APIs application [#6337](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6337) @@ -41,6 +42,7 @@ All notable changes to the Wazuh app project will be documented in this file. ### Fixed - Fixed the scripted fields disappear when the fields of the events index pattern was refreshed [#6237](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6237) +- Fixed an error of malformed tabe row on the generation of PDF reports [#6558](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6558) ### Removed From 26e2b5565531997d47c666c79d8af97afe3cc91f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Wed, 15 May 2024 11:33:20 +0200 Subject: [PATCH 34/42] feat(reporting): adapt the dashboard of Office365 to the data source --- .../overview/office/dashboard/dashboard.tsx | 37 +++++++++++++------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/plugins/main/public/components/overview/office/dashboard/dashboard.tsx b/plugins/main/public/components/overview/office/dashboard/dashboard.tsx index 802401aa50..010586fa4c 100644 --- a/plugins/main/public/components/overview/office/dashboard/dashboard.tsx +++ b/plugins/main/public/components/overview/office/dashboard/dashboard.tsx @@ -24,6 +24,7 @@ import { import { Office365DataSource } from '../../../common/data-source/pattern/alerts/office-365/office-365-data-source'; import { DiscoverNoResults } from '../../../common/no-results/no-results'; import { LoadingSpinner } from '../../../common/loading-spinner/loading-spinner'; +import { useReportingCommunicateSearchContext } from '../../../common/hooks/use-reporting-communicate-search-context'; const plugins = getPlugins(); @@ -50,7 +51,19 @@ const DashboardOffice365Component: React.FC = () => { filters, setFilters, }); - const { query } = searchBarProps; + const { query, dateRangeFrom, dateRangeTo } = searchBarProps; + + useReportingCommunicateSearchContext({ + isSearching: isDataSourceLoading, + totalResults: results?.hits?.total ?? 0, + indexPattern: dataSource?.indexPattern, + filters: fetchFilters, + query: query, + time: { + from: dateRangeFrom, + to: dateRangeTo, + }, + }); useEffect(() => { if (isDataSourceLoading) { @@ -87,17 +100,17 @@ const DashboardOffice365Component: React.FC = () => { {isDataSourceLoading && !dataSource ? ( ) : ( -
- -
- )} +
+ +
+ )} {dataSource && results?.hits?.total === 0 ? ( ) : null} From e2113a2f212136090a88c6e653f808e7e1199703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Wed, 15 May 2024 11:33:57 +0200 Subject: [PATCH 35/42] fix: missing Generate report button on Office 365 > Dashboard --- .../components/common/modules/modules-defaults.tsx | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/plugins/main/public/components/common/modules/modules-defaults.tsx b/plugins/main/public/components/common/modules/modules-defaults.tsx index 6743b1c4df..ab3dbf5d2d 100644 --- a/plugins/main/public/components/common/modules/modules-defaults.tsx +++ b/plugins/main/public/components/common/modules/modules-defaults.tsx @@ -218,15 +218,7 @@ export const ModulesDefaults = { id: 'dashboard', name: 'Dashboard', component: DashboardOffice365, - /* For ButtonModuleExploreAgent to insert correctly according to the module's index pattern, the moduleIndexPatternTitle parameter is added. By default it applies the index patternt wazuh-alerts-* */ - buttons: [ - ({ ...props }) => ( - - ), - ], + buttons: [ButtonModuleExploreAgent, ButtonModuleGenerateReport], }, { id: 'inventory', From 0b5b03df4bde318c7c3ed6c632c0103aab4203fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Wed, 15 May 2024 11:35:13 +0200 Subject: [PATCH 36/42] fix: remove unused variables --- .../components/common/modules/modules-defaults.tsx | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/plugins/main/public/components/common/modules/modules-defaults.tsx b/plugins/main/public/components/common/modules/modules-defaults.tsx index ab3dbf5d2d..ec4b2c3d01 100644 --- a/plugins/main/public/components/common/modules/modules-defaults.tsx +++ b/plugins/main/public/components/common/modules/modules-defaults.tsx @@ -81,16 +81,6 @@ import { Office365DataSource, } from '../data-source'; -const ALERTS_INDEX_PATTERN = 'wazuh-alerts-*'; -const DEFAULT_INDEX_PATTERN = ALERTS_INDEX_PATTERN; - -const DashboardTab = { - id: 'dashboard', - name: 'Dashboard', - buttons: [ButtonModuleExploreAgent, ButtonModuleGenerateReport], - component: Dashboard, -}; - const renderDiscoverTab = (props: WazuhDiscoverProps) => { return { id: 'events', From 0a158a7789c391021cd5fb4dbd198e822d9dc5bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Wed, 15 May 2024 11:47:56 +0200 Subject: [PATCH 37/42] fix(office365): support explore by agent --- .../public/components/common/modules/modules-defaults.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/main/public/components/common/modules/modules-defaults.tsx b/plugins/main/public/components/common/modules/modules-defaults.tsx index ec4b2c3d01..1b627f4eb4 100644 --- a/plugins/main/public/components/common/modules/modules-defaults.tsx +++ b/plugins/main/public/components/common/modules/modules-defaults.tsx @@ -214,14 +214,14 @@ export const ModulesDefaults = { id: 'inventory', name: 'Panel', buttons: [ButtonModuleExploreAgent], - component: withModuleNotForAgent(OfficePanel), + component: OfficePanel, }, renderDiscoverTab({ tableColumns: office365Columns, DataSource: Office365DataSource, }), ], - availableFor: ['manager'], + availableFor: ['manager', 'agent'], }, github: { init: 'dashboard', From 7ae44f273bb5215ff28b862d619c616862fd2ec8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Wed, 15 May 2024 12:45:48 +0200 Subject: [PATCH 38/42] changelog: move entry --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c9da3ca2f..27a160f2e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,8 +20,8 @@ All notable changes to the Wazuh app project will be documented in this file. ### Changed -- Removed embedded discover [#6120](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6120) [#6235](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6235) [#6254](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6254) [#6285](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6285) [#6288](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6288) [#6290](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6290) [#6289](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6289) [#6286](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6286) [#6275](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6275) [#6287](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6287) [#6297](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6297) [#6291](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6287) [#6459](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6459) [#6434](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6434) [#6504](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6504) [#6649](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6649) [#6506](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6506) [#6537](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6537) [#6528](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6528) -- Develop logic of a new index for the fim module [#6227](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6227) [#6558](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6558) +- Removed embedded discover [#6120](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6120) [#6235](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6235) [#6254](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6254) [#6285](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6285) [#6288](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6288) [#6290](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6290) [#6289](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6289) [#6286](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6286) [#6275](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6275) [#6287](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6287) [#6297](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6297) [#6291](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6287) [#6459](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6459) [#6434](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6434) [#6504](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6504) [#6649](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6649) [#6506](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6506) [#6537](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6537) [#6528](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6528) [#6558](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6558) +- Develop logic of a new index for the fim module [#6227](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6227) - Allow editing groups for an agent from Endpoints Summary [#6250](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6250) - Change how the configuration is managed in the backend side [#6337](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6337) [#6519](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6519) [#6573](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6573) - Change the view of API is down and check connection to Server APIs application [#6337](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6337) From b8afc0abd90e86aa381783622c21df82554106c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Wed, 15 May 2024 12:47:54 +0200 Subject: [PATCH 39/42] changelog: add entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27a160f2e8..d8d52849cc 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. - Added journald log collector tab [#6572](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6572) - Added HAProxy helper settings to cluster configuration [#6653](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6653) - Added ability to open the report file or Reporting application from the toast message [#6558](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6558) +- Added support for agents to Office 365 [#6558](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6558) ### Changed From 02387c47148deba990a6bdf2219a0a2c4f0d0d18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Thu, 16 May 2024 09:13:51 +0200 Subject: [PATCH 40/42] fix: changelog --- CHANGELOG.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d8d52849cc..f5595bda48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,10 +44,8 @@ All notable changes to the Wazuh app project will be documented in this file. ### Fixed - Fixed the scripted fields disappear when the fields of the events index pattern was refreshed [#6237](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6237) - <<<<<<< HEAD -- # Fixed an error of malformed tabe row on the generation of PDF reports [#6558](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6558) +- Fixed an error of malformed tabe row on the generation of PDF reports [#6558](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6558) - Fixed the sample alerts scripts to generate valid IP ranges and file hashes [#6667](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6667) - > > > > > > > 16d03fb8ab4633f3f9955bd295636ba6f85fa45c ### Removed From 8c618e86284c3495e5355dfe15d5d956792dfb7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Thu, 16 May 2024 15:38:30 +0200 Subject: [PATCH 41/42] fix(reporting): add missing Generate report button on Inventory data - Add missing Generate report button on Inventory data - Add header with agent name link to Inventory data, Stats and Configuration from agent view - Simplify the styles of panels on Inventory data - Remove unwanted styles defined on file --- .../components/network-interfaces-table.tsx | 2 +- .../components/network-ports-table.tsx | 2 +- .../components/network-settings-table.tsx | 2 +- .../components/packages-table.tsx | 2 +- .../components/processes-table.tsx | 2 +- .../components/syscollector-metrics.tsx | 2 +- .../components/windows-updates-table.tsx | 2 +- .../agents/syscollector/inventory.scss | 3 --- .../agents/syscollector/inventory.tsx | 26 ++++++++++--------- .../endpoints-summary/agent/index.tsx | 22 +++++++++++++--- 10 files changed, 40 insertions(+), 25 deletions(-) delete mode 100644 plugins/main/public/components/agents/syscollector/inventory.scss diff --git a/plugins/main/public/components/agents/syscollector/components/network-interfaces-table.tsx b/plugins/main/public/components/agents/syscollector/components/network-interfaces-table.tsx index b7bb9c6a34..862c4e2cbe 100644 --- a/plugins/main/public/components/agents/syscollector/components/network-interfaces-table.tsx +++ b/plugins/main/public/components/agents/syscollector/components/network-interfaces-table.tsx @@ -10,7 +10,7 @@ const sortFieldSuggestion = (a, b) => (a.label > b.label ? 1 : -1); export const NetworkInterfacesTable = ({ agent }) => { return ( - + (a.label > b.label ? 1 : -1); export const NetworkPortsTable = withSOPlatformGuard( ({ agent, soPlatform }) => { return ( - + (a.label > b.label ? 1 : -1); export const NetworkSettingsTable = ({ agent }) => { return ( - + (a.label > b.label ? 1 : -1); export const PackagesTable = withSOPlatformGuard(({ agent, soPlatform }) => { return ( - + (a.label > b.label ? 1 : -1); export const ProcessesTable = withSOPlatformGuard(({ agent, soPlatform }) => { return ( - + + diff --git a/plugins/main/public/components/agents/syscollector/components/windows-updates-table.tsx b/plugins/main/public/components/agents/syscollector/components/windows-updates-table.tsx index 585726b3a8..65e3937cca 100644 --- a/plugins/main/public/components/agents/syscollector/components/windows-updates-table.tsx +++ b/plugins/main/public/components/agents/syscollector/components/windows-updates-table.tsx @@ -10,7 +10,7 @@ const sortFieldSuggestion = (a, b) => (a.label > b.label ? 1 : -1); export const WindowsUpdatesTable = ({ agent }) => { return ( - + +
{agent && agent.status === API_NAME_AGENT_STATUS.DISCONNECTED && ( - + + + + + )} - + - + - + - + {agent && agent.os && agent.os.platform === 'windows' && ( - + )} diff --git a/plugins/main/public/components/endpoints-summary/agent/index.tsx b/plugins/main/public/components/endpoints-summary/agent/index.tsx index 166b331e3b..07e72623a4 100644 --- a/plugins/main/public/components/endpoints-summary/agent/index.tsx +++ b/plugins/main/public/components/endpoints-summary/agent/index.tsx @@ -14,6 +14,7 @@ import { endpointSummary } from '../../../utils/applications'; import { withErrorBoundary, withReduxProvider } from '../../common/hocs'; import { compose } from 'redux'; import { PinnedAgentManager } from '../../wz-agent-selector/wz-agent-selector-service'; +import { MainModuleAgent } from '../../common/modules/main-agent'; export const AgentView = compose( withErrorBoundary, @@ -66,15 +67,30 @@ export const AgentView = compose( } if (tab === 'syscollector' && agent) { - return ; + return ( + <> + + + + ); } if (tab === 'stats' && agent) { - return ; + return ( + <> + + + + ); } if (tab === 'configuration' && agent) { - return ; + return ( + <> + + + + ); } return ( From 12ac4896af09ed5af539487ad13cc41729315868 Mon Sep 17 00:00:00 2001 From: Federico Rodriguez Date: Thu, 16 May 2024 17:59:41 +0200 Subject: [PATCH 42/42] Fix changelog typo --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5e84df11b..7cc0bb77e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,7 +45,7 @@ All notable changes to the Wazuh app project will be documented in this file. ### Fixed - Fixed the scripted fields disappear when the fields of the events index pattern was refreshed [#6237](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6237) -- Fixed an error of malformed tabe row on the generation of PDF reports [#6558](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6558) +- Fixed an error of malformed table row on the generation of PDF reports [#6558](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6558) - Fixed the sample alerts scripts to generate valid IP ranges and file hashes [#6667](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6667) ### Removed