Skip to content

Commit

Permalink
Adapt the reporting to the rendering of dashboards (#6558)
Browse files Browse the repository at this point in the history
* 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

* feat(reporting): remove unused AngularJS service to generate the reports

- Remove the dependency injectiong of the unused AngularJS service to
  generate the reports

* feat(reporting): remove unused import

* 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

* feat(reporting): replace toast title when generating the PDF reports

* fix(reporting): time.from parameter

* feat(reporting): replace query.getOpenSearchQuery from global source to use the search context

* fix(reporting): remove isLoading dependency from Generate repot button

* feat(reporting): adapt agent inventory report to data source

* fix(reporting): fix date range filter for Today and This week special date ranges

* feat(reporting): adapt the dashboard of Threat Hunting and VirusTotal to the data source

* feat(reporting): adapt the dashboard of MITRE ATT&CK to the data source

* fix: remove unused props and imports

* feat(reporting): adapt the dashboard of Amazon Web Services to the data source

* fix(reporting): error converting DOM node from map visualizations to image

* feat(reporting): adapt the dashboard of File Integrity Monitoring to the data source

* feat(reporting): adapt the dashboard of Malware Detection to the data source

* feat(reporting): adapt the dashboard of Docker to the data source

* feat(reporting): adapt the dashboard of Google Cloud to the data source

* fix(google-cloud): add missing button to generate the report on Dashboard tab

* 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

* fix: typo

* feat(reporting): adapt the dashboard of PCI DSS to the data source

* feat(reporting): adapt the dashboard of GDPR to the data source

* feat(reporting): adapt the dashboard of HIPAA to the data source

* feat(reporting): adapt the dashboard of NIST 800-53 to the data source

* feat(reporting): adapt the dashboard of TSC to the data source

* feat(reporting): adapt the dashboard of GitHub to the data source

* fix(github): fix request related to get available data on Dashboard

* chore: move the import of PCI DSS data source

* fix(github): request to get the available data did not take into account the date range

* remove: unused RegulatoryComplianceTabs

* changelog: add pull request entry

* feat(reporting): adapt the dashboard of Office365 to the data source

* fix: missing Generate report button on Office 365 > Dashboard

* fix: remove unused variables

* fix(office365): support explore by agent

* changelog: move entry

* changelog: add entry

* fix: changelog

* 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

* Fix changelog typo

---------

Co-authored-by: Federico Rodriguez <federico.rodriguez@wazuh.com>
  • Loading branch information
Desvelao and asteriscos authored May 16, 2024
1 parent a37e701 commit 577a524
Show file tree
Hide file tree
Showing 42 changed files with 985 additions and 616 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@ All notable changes to the Wazuh app project will be documented in this file.
- 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 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

- 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) [#6675](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6675) [#6674](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6674)
- 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) [#6675](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6675) [#6674](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6674) [#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)
Expand All @@ -43,6 +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 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const sortFieldSuggestion = (a, b) => (a.label > b.label ? 1 : -1);

export const NetworkInterfacesTable = ({ agent }) => {
return (
<EuiPanel paddingSize='m' className='wz-agent-inventory-panel'>
<EuiPanel paddingSize='m'>
<TableWzAPI
title='Network interfaces'
tableColumns={netifaceColumns}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const sortFieldSuggestion = (a, b) => (a.label > b.label ? 1 : -1);
export const NetworkPortsTable = withSOPlatformGuard(
({ agent, soPlatform }) => {
return (
<EuiPanel paddingSize='m' className='wz-agent-inventory-panel'>
<EuiPanel paddingSize='m'>
<TableWzAPI
title='Network ports'
tableColumns={portsColumns[soPlatform]}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const sortFieldSuggestion = (a, b) => (a.label > b.label ? 1 : -1);

export const NetworkSettingsTable = ({ agent }) => {
return (
<EuiPanel paddingSize='m' className='wz-agent-inventory-panel'>
<EuiPanel paddingSize='m'>
<TableWzAPI
title='Network settings'
tableColumns={netaddrColumns}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const sortFieldSuggestion = (a, b) => (a.label > b.label ? 1 : -1);

export const PackagesTable = withSOPlatformGuard(({ agent, soPlatform }) => {
return (
<EuiPanel paddingSize='m' className='wz-agent-inventory-panel'>
<EuiPanel paddingSize='m'>
<TableWzAPI
title='Packages'
tableColumns={packagesColumns[soPlatform]}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const sortFieldSuggestion = (a, b) => (a.label > b.label ? 1 : -1);

export const ProcessesTable = withSOPlatformGuard(({ agent, soPlatform }) => {
return (
<EuiPanel paddingSize='m' className='wz-agent-inventory-panel'>
<EuiPanel paddingSize='m'>
<TableWzAPI
title='Processes'
tableColumns={processColumns[soPlatform]}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export function InventoryMetrics({ agent }) {
}

return (
<EuiPanel paddingSize='s' style={{ margin: 16 }}>
<EuiPanel paddingSize='s'>
<EuiFlexGroup>
<EuiFlexItem grow={false}>
<EuiText>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const sortFieldSuggestion = (a, b) => (a.label > b.label ? 1 : -1);

export const WindowsUpdatesTable = ({ agent }) => {
return (
<EuiPanel paddingSize='m' className='wz-agent-inventory-panel'>
<EuiPanel paddingSize='m'>
<TableWzAPI
title='Windows updates'
tableColumns={windowsUpdatesColumns}
Expand Down

This file was deleted.

26 changes: 14 additions & 12 deletions plugins/main/public/components/agents/syscollector/inventory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import {
ProcessesTable,
PackagesTable,
} from './components';
import './inventory.scss';

export const SyscollectorInventory = compose(
withGuard(
Expand All @@ -49,35 +48,38 @@ export const SyscollectorInventory = compose(
}

return (
<div style={{ overflow: 'hidden' }}>
<div style={{ overflow: 'hidden', margin: '12px 16px 12px 16px' }}>
{agent && agent.status === API_NAME_AGENT_STATUS.DISCONNECTED && (
<EuiCallOut
style={{ margin: '8px 16px 8px 16px' }}
title='This agent is currently disconnected, the data may be outdated.'
iconType='iInCircle'
/>
<EuiFlexGroup gutterSize='s'>
<EuiFlexItem>
<EuiCallOut
title='This agent is currently disconnected, the data may be outdated.'
iconType='iInCircle'
/>
</EuiFlexItem>
</EuiFlexGroup>
)}
<EuiFlexGroup gutterSize='s'>
<EuiFlexItem style={{ marginBottom: 0 }}>
<EuiFlexItem>
<InventoryMetrics agent={agent}></InventoryMetrics>
</EuiFlexItem>
</EuiFlexGroup>

<EuiFlexGroup gutterSize='s'>
<EuiFlexItem grow={2} style={{ marginRight: 4, marginTop: 0 }}>
<EuiFlexItem grow={2}>
<NetworkInterfacesTable agent={agent} />
</EuiFlexItem>
<EuiFlexItem grow={2} style={{ marginLeft: 4, marginTop: 0 }}>
<EuiFlexItem grow={2}>
<NetworkPortsTable agent={agent} soPlatform={soPlatform} />
</EuiFlexItem>
</EuiFlexGroup>

<EuiFlexGroup gutterSize='s'>
<EuiFlexItem grow={3} style={{ marginRight: 4 }}>
<EuiFlexItem grow={3}>
<NetworkSettingsTable agent={agent} />
</EuiFlexItem>
{agent && agent.os && agent.os.platform === 'windows' && (
<EuiFlexItem grow={1} style={{ marginLeft: 4 }}>
<EuiFlexItem grow={1}>
<WindowsUpdatesTable agent={agent} />
</EuiFlexItem>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
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: {
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)]);
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,48 +16,65 @@ 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?.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 (
<WzButton
buttonType='empty'
iconType='document'
isLoading={action.running}
onClick={action.run}
isDisabled={disabledReport}
tooltip={disabledReport ? {position: 'top', content: 'No results match for this search criteria.'} : undefined}
>
Generate report
</WzButton>
)
}
}, [agent]);

return (
<WzButton
buttonType='empty'
iconType='document'
isLoading={action.running}
onClick={action.run}
isDisabled={disabledReport}
tooltip={
disabledReport && totalResults === 0
? {
position: 'top',
content: 'No results match for this search criteria.',
}
: undefined
}
>
Generate report
</WzButton>
);
},
);
92 changes: 54 additions & 38 deletions plugins/main/public/components/common/modules/main-agent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,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!: {
Expand Down Expand Up @@ -61,43 +69,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' && (
<EuiFlexItem grow={false} style={{ marginRight: 4, marginTop: 6 }}>
<EuiButtonEmpty
iconType='document'
isLoading={this.state.loadingReport}
onClick={async () => this.startReport()}
>
Generate report
</EuiButtonEmpty>
</EuiFlexItem>
)
);
}

renderTitle() {
return (
<EuiFlexGroup>
Expand All @@ -123,7 +94,14 @@ export class MainModuleAgent extends Component {
</span>
</EuiFlexItem>
<EuiFlexItem />
{this.renderReportButton()}
{this.props.section === 'syscollector' && (
<EuiFlexItem
grow={false}
style={{ marginRight: 4, marginTop: 6 }}
>
<GenerateSyscollectorReportButton agent={this.props.agent} />
</EuiFlexItem>
)}
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>
Expand Down Expand Up @@ -253,3 +231,41 @@ export default compose(
}
}),
)(MainModuleAgent);

const GenerateSyscollectorReportButton = ({ agent }) => {
const {
dataSource,
fetchFilters,
isLoading: isDataSourceLoading,
} = useDataSource<tParsedIndexPattern, PatternDataSource>({
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 (
<EuiButtonEmpty
iconType='document'
isLoading={action.running}
isDisabled={isDataSourceLoading}
onClick={action.run}
>
Generate report
</EuiButtonEmpty>
);
};
Loading

0 comments on commit 577a524

Please sign in to comment.