Skip to content

Commit

Permalink
[Remove discover] Implement embeddable dashboard on Virustotal module (
Browse files Browse the repository at this point in the history
…#6525)

* Migrated visualizations, added loadings and messages

* Fixed warning for expected a single ReactElement

* Added new virustotal data source. Changed NoResults and LoadingSpinner to commons components

* Fixed Events tab

* Integrated pinned agent functionality based on data source

* Added timeRange to dashboard useEffect dependencies and changed the way to get pinned agent

* Deleted unused component

* Changed AlertsVirustotalDataSource import in modules-defaults

* Fixed error message

* DashboardByRenderer timeRange params replaced by searchBarProps deconstruction

* Added wz-discover hide-filter-control classes to hide the button that allows you to affect all the filters in the search bar

* Removed unnecessary virus total in Filters tab in common data to remove duplicate filters

* Removed unused getImplicitPinnedAgent in modules-helper

* Added dateRange param to fetchData in dashboard useEffect

* Improved AlertsVirustotalDataSource import in modules-defaults and deleted wz-discover on SearchBar wrapper
  • Loading branch information
jbiset authored and Machi3mfl committed Apr 25, 2024
1 parent e1cc885 commit 693d949
Show file tree
Hide file tree
Showing 11 changed files with 1,520 additions and 10 deletions.
14 changes: 10 additions & 4 deletions plugins/main/common/constants.ts
Expand Up @@ -221,12 +221,18 @@ export enum WAZUH_MENU_SETTINGS_SECTIONS_ID {
}

export const AUTHORIZED_AGENTS = 'hidden-authorized-agents';
export const DATA_SOURCE_FILTER_CONTROLLED_EXCLUDE_SERVER = 'hidden-exclude-server';
export const DATA_SOURCE_FILTER_CONTROLLED_EXCLUDE_SERVER =
'hidden-exclude-server';
export const DATA_SOURCE_FILTER_CONTROLLED_PINNED_AGENT = 'pinned-agent';
export const DATA_SOURCE_FILTER_CONTROLLED_CLUSTER_MANAGER = 'cluster-manager';
export const DATA_SOURCE_FILTER_CONTROLLED_VULNERABILITIES_RULE_GROUP = 'vulnerabilities-rule-group';
export const DATA_SOURCE_FILTER_CONTROLLED_MITRE_ATTACK_RULE = 'mitre-attack-rule';
export const DATA_SOURCE_FILTER_CONTROLLED_MITRE_ATTACK_RULE_ID = 'hidden-mitre-attack-rule-id';
export const DATA_SOURCE_FILTER_CONTROLLED_VULNERABILITIES_RULE_GROUP =
'vulnerabilities-rule-group';
export const DATA_SOURCE_FILTER_CONTROLLED_MITRE_ATTACK_RULE =
'mitre-attack-rule';
export const DATA_SOURCE_FILTER_CONTROLLED_MITRE_ATTACK_RULE_ID =
'hidden-mitre-attack-rule-id';
export const DATA_SOURCE_FILTER_CONTROLLED_VIRUSTOTAL_RULE_GROUP =
'virustotal-rule-group';
// Wazuh links
export const WAZUH_LINK_GITHUB = 'https://github.com/wazuh';
export const WAZUH_LINK_GOOGLE_GROUPS =
Expand Down
@@ -0,0 +1,24 @@
import { tFilter } from '../../../index';
import { DATA_SOURCE_FILTER_CONTROLLED_VIRUSTOTAL_RULE_GROUP } from '../../../../../../../common/constants';
import { AlertsDataSource } from '../alerts-data-source';

const VIRUSTOTAL_GROUP_KEY = 'rule.groups';
const VIRUSTOTAL_GROUP_VALUE = 'virustotal';

export class AlertsVirustotalDataSource extends AlertsDataSource {
constructor(id: string, title: string) {
super(id, title);
}

getRuleGroupsFilter() {
return super.getRuleGroupsFilter(
VIRUSTOTAL_GROUP_KEY,
VIRUSTOTAL_GROUP_VALUE,
DATA_SOURCE_FILTER_CONTROLLED_VIRUSTOTAL_RULE_GROUP,
);
}

getFixedFilters(): tFilter[] {
return [...this.getRuleGroupsFilter(), ...super.getFixedFilters()];
}
}
@@ -0,0 +1 @@
export * from './alerts-virustotal-data-source';
@@ -1,4 +1,5 @@
export * from './alerts-vulnerabilities';
export * from './alerts-data-source-repository';
export * from './alerts-data-source';
export * from './mitre-attack';
export * from './mitre-attack';
export * from './alerts-virustotal';
19 changes: 15 additions & 4 deletions plugins/main/public/components/common/modules/modules-defaults.tsx
Expand Up @@ -28,6 +28,7 @@ import {
} from '../wazuh-discover/wz-discover';
import { threatHuntingColumns } from '../wazuh-discover/config/data-grid-columns';
import { vulnerabilitiesColumns } from '../../overview/vulnerabilities/events/vulnerabilities-columns';
import { DashboardVirustotal } from '../../overview/virustotal/dashboard/dashboard';
import React from 'react';
import { dockerColumns } from '../../overview/docker/events/docker-columns';
import { googleCloudColumns } from '../../overview/google-cloud/events/google-cloud-columns';
Expand All @@ -45,8 +46,11 @@ import { mitreAttackColumns } from '../../overview/mitre/events/mitre-attack-col
import { virustotalColumns } from '../../overview/virustotal/events/virustotal-columns';
import { malwareDetectionColumns } from '../../overview/malware-detection/events/malware-detection-columns';
import { WAZUH_VULNERABILITIES_PATTERN } from '../../../../common/constants';
import { AlertsVulnerabilitiesDataSource } from '../data-source';
import { MitreAttackDataSource } from '../data-source/pattern/alerts/mitre-attack/mitre-attack-data-source';
import {
AlertsVulnerabilitiesDataSource,
AlertsVirustotalDataSource,
} from '../data-source';

const ALERTS_INDEX_PATTERN = 'wazuh-alerts-*';
const DEFAULT_INDEX_PATTERN = ALERTS_INDEX_PATTERN;
Expand Down Expand Up @@ -251,10 +255,17 @@ export const ModulesDefaults = {
availableFor: ['manager', 'agent'],
},
virustotal: {
init: 'dashboard',
tabs: [
DashboardTab,
renderDiscoverTab(DEFAULT_INDEX_PATTERN, virustotalColumns),
{
id: 'dashboard',
name: 'Dashboard',
buttons: [ButtonModuleExploreAgent, ButtonModuleGenerateReport],
component: DashboardVirustotal,
},
renderDiscoverTab({
tableColumns: virustotalColumns,
DataSource: AlertsVirustotalDataSource,
}),
],
availableFor: ['manager', 'agent'],
},
Expand Down
Expand Up @@ -2,6 +2,8 @@ import { getAngularModule, getDataPlugin } from '../../../kibana-services';
import { AppState } from '../../../react-services/app-state';
import { FilterHandler } from '../../../utils/filter-handler';
import { VULNERABILITY_IMPLICIT_CLUSTER_MODE_FILTER } from '../../../../common/constants';
import { useFilterManager } from '../hooks';
import { FilterStateStore } from '../../../../../../src/plugins/data/common';

export class ModulesHelper {
static async getDiscoverScope() {
Expand Down
@@ -0,0 +1,163 @@
import React, { useState, useEffect } from 'react';
import { getPlugins } from '../../../../kibana-services';
import { ViewMode } from '../../../../../../../src/plugins/embeddable/public';
import { SearchResponse } from '../../../../../../../src/core/server';
import { IndexPattern } from '../../../../../../../src/plugins/data/common';
import { getDashboardPanels } from './dashboard_panels';
import { I18nProvider } from '@osd/i18n/react';
import useSearchBar from '../../../common/search-bar/use-search-bar';
import { getKPIsPanel } from './dashboard_panels_kpis';
import {
ErrorFactory,
ErrorHandler,
HttpError,
} from '../../../../react-services/error-management';
import { withErrorBoundary } from '../../../common/hocs/error-boundary/with-error-boundary';
import { SampleDataWarning } from '../../../visualize/components/sample-data-warning';
import {
AlertsDataSourceRepository,
PatternDataSource,
tParsedIndexPattern,
useDataSource,
} from '../../../common/data-source';
import { LoadingSpinner } from '../../../common/loading-spinner/loading-spinner';
import { DiscoverNoResults } from '../../../common/no-results/no-results';
import { AlertsVirustotalDataSource } from '../../../common/data-source/pattern/alerts/alerts-virustotal/alerts-virustotal-data-source';
import './virustotal_dashboard.scss';

const plugins = getPlugins();

const SearchBar = getPlugins().data.ui.SearchBar;

const DashboardByRenderer = plugins.dashboard.DashboardContainerByValueRenderer;
const DashboardVT: React.FC = () => {
const {
filters,
dataSource,
fetchFilters,
isLoading: isDataSourceLoading,
fetchData,
setFilters,
} = useDataSource<tParsedIndexPattern, PatternDataSource>({
DataSource: AlertsVirustotalDataSource,
repository: new AlertsDataSourceRepository(),
});

const [results, setResults] = useState<SearchResponse>({} as SearchResponse);

const { searchBarProps } = useSearchBar({
indexPattern: dataSource?.indexPattern as IndexPattern,
filters,
setFilters,
});
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);
});
}, [
isDataSourceLoading,
JSON.stringify(fetchFilters),
JSON.stringify(query),
dateRangeFrom,
dateRangeTo,
]);

return (
<I18nProvider>
<>
{isDataSourceLoading && !dataSource ? (
<LoadingSpinner />
) : (
<div className='wz-search-bar hide-filter-control'>
<SearchBar
appName='virustotal-searchbar'
{...searchBarProps}
showDatePicker={true}
showQueryInput={true}
showQueryBar={true}
showSaveQuery={true}
/>
</div>
)}
{!isDataSourceLoading && dataSource && results?.hits?.total > 0 ? (
<SampleDataWarning />
) : null}
{dataSource && results?.hits?.total === 0 ? (
<DiscoverNoResults />
) : null}
{!isDataSourceLoading && dataSource && results?.hits?.total > 0 ? (
<div className='virustotal-dashboard-responsive'>
<DashboardByRenderer
input={{
viewMode: ViewMode.VIEW,
panels: getKPIsPanel(dataSource?.id),
isFullScreenMode: false,
filters: fetchFilters ?? [],
useMargins: true,
id: 'kpis-virustotal-dashboard-tab',
timeRange: {
from: dateRangeFrom,
to: dateRangeTo,
},
title: 'KPIs Virustotal dashboard',
description: 'KPIs Dashboard of the Virustotal',
query: query,
refreshConfig: {
pause: false,
value: 15,
},
hidePanelTitles: true,
}}
/>
<DashboardByRenderer
input={{
viewMode: ViewMode.VIEW,
panels: getDashboardPanels(
dataSource?.id,
dataSource.getPinnedAgentFilter().length > 0,
),
isFullScreenMode: false,
filters: fetchFilters ?? [],
useMargins: true,
id: 'virustotal-dashboard-tab',
timeRange: {
from: dateRangeFrom,
to: dateRangeTo,
},
title: 'Virustotal dashboard',
description: 'Dashboard of the Virustotal',
query: query,
refreshConfig: {
pause: false,
value: 15,
},
hidePanelTitles: false,
}}
/>
</div>
) : null}
</>
</I18nProvider>
);
};

export const DashboardVirustotal = withErrorBoundary(DashboardVT);

0 comments on commit 693d949

Please sign in to comment.