diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c74eefcfb..3c02ac3418 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,7 @@ 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) [#6287](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6287) [#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) +- 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) [#6287](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6287) [#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) - 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) diff --git a/plugins/main/common/constants.ts b/plugins/main/common/constants.ts index 0a168b4bdf..cba93fc198 100644 --- a/plugins/main/common/constants.ts +++ b/plugins/main/common/constants.ts @@ -225,6 +225,9 @@ 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_REGULATORY_COMPLIANCE_REQUIREMENT = + 'hidden-regulatory-compliance-requirement'; +export const DATA_SOURCE_FILTER_CONTROLLED_PCI_DSS_EXIST = 'pci-dss-exist'; export const DATA_SOURCE_FILTER_CONTROLLED_VULNERABILITIES_RULE_GROUP = 'vulnerabilities-rule-group'; export const DATA_SOURCE_FILTER_CONTROLLED_DOCKER_RULE_GROUP = diff --git a/plugins/main/public/components/common/data-source/pattern/alerts/index.ts b/plugins/main/public/components/common/data-source/pattern/alerts/index.ts index 259f5b3e93..ec2cabfac9 100644 --- a/plugins/main/public/components/common/data-source/pattern/alerts/index.ts +++ b/plugins/main/public/components/common/data-source/pattern/alerts/index.ts @@ -7,6 +7,7 @@ export * from './alerts-malware-detection'; export * from './alerts-aws'; export * from './vulnerabilities'; export * from './mitre-attack'; +export * from './pci-dss'; export * from './virustotal'; export * from './alerts-google-cloud'; diff --git a/plugins/main/public/components/common/data-source/pattern/alerts/pci-dss/alerts-pci-dss-data-source.ts b/plugins/main/public/components/common/data-source/pattern/alerts/pci-dss/alerts-pci-dss-data-source.ts new file mode 100644 index 0000000000..f2eb3ae881 --- /dev/null +++ b/plugins/main/public/components/common/data-source/pattern/alerts/pci-dss/alerts-pci-dss-data-source.ts @@ -0,0 +1,42 @@ +import { tFilter } from '../../../index'; +import { DATA_SOURCE_FILTER_CONTROLLED_PCI_DSS_EXIST } from '../../../../../../../common/constants'; +import { AlertsDataSource } from '../alerts-data-source'; + +const KEY_EXIST = 'rule.pci_dss'; + +export class AlertsPCIDSSDataSource extends AlertsDataSource { + constructor(id: string, title: string) { + super(id, title); + } + + private getFilterExist() { + return [ + { + meta: { + index: this.id, + negate: false, + disabled: false, + alias: null, + type: 'exists', + key: KEY_EXIST, + value: 'exists', + params: { + query: null, + type: 'phrase', + }, + controlledBy: DATA_SOURCE_FILTER_CONTROLLED_PCI_DSS_EXIST, + }, + exists: { + field: KEY_EXIST, + }, + $state: { + store: 'appState', + }, + } as tFilter, + ]; + } + + getFixedFilters(): tFilter[] { + return [...this.getFilterExist(), ...super.getFixedFilters()]; + } +} diff --git a/plugins/main/public/components/common/data-source/pattern/alerts/pci-dss/index.ts b/plugins/main/public/components/common/data-source/pattern/alerts/pci-dss/index.ts new file mode 100644 index 0000000000..351f900790 --- /dev/null +++ b/plugins/main/public/components/common/data-source/pattern/alerts/pci-dss/index.ts @@ -0,0 +1 @@ +export * from './alerts-pci-dss-data-source'; diff --git a/plugins/main/public/components/common/modules/modules-defaults.tsx b/plugins/main/public/components/common/modules/modules-defaults.tsx index 8628c6fb6e..891c03061d 100644 --- a/plugins/main/public/components/common/modules/modules-defaults.tsx +++ b/plugins/main/public/components/common/modules/modules-defaults.tsx @@ -49,6 +49,7 @@ 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 { DashboardPCIDSS } from '../../overview/pci/dashboards/dashboard'; import { DashboardDocker } from '../../overview/docker/dashboards'; import { DashboardMalwareDetection } from '../../overview/malware-detection/dashboard'; import { DashboardFIM } from '../../overview/fim/dashboard/dashboard'; @@ -56,6 +57,7 @@ import { MitreAttackDataSource } from '../data-source/pattern/alerts/mitre-attac import { AlertsDockerDataSource, AlertsDataSource, + AlertsPCIDSSDataSource, AlertsVulnerabilitiesDataSource, AlertsAWSDataSource, VirusTotalDataSource, @@ -339,7 +341,26 @@ export const ModulesDefaults = { }, pci: { init: 'dashboard', - tabs: RegulatoryComplianceTabs(pciColumns), + tabs: [ + { + id: 'dashboard', + name: 'Dashboard', + buttons: [ButtonModuleExploreAgent, ButtonModuleGenerateReport], + component: DashboardPCIDSS, + }, + { + id: 'inventory', + name: 'Controls', + buttons: [ButtonModuleExploreAgent], + component: props => ( + + ), + }, + renderDiscoverTab({ + tableColumns: pciColumns, + DataSource: AlertsPCIDSSDataSource, + }), + ], availableFor: ['manager', 'agent'], }, hipaa: { diff --git a/plugins/main/public/components/overview/compliance-table/compliance-table.tsx b/plugins/main/public/components/overview/compliance-table/compliance-table.tsx index 1837ed8bc9..69668a4874 100644 --- a/plugins/main/public/components/overview/compliance-table/compliance-table.tsx +++ b/plugins/main/public/components/overview/compliance-table/compliance-table.tsx @@ -9,358 +9,336 @@ * * Find more information about this on the LICENSE file. */ -import React, { Component } from 'react'; +import React, { useState, useEffect } from 'react'; import { EuiPanel, EuiFlexGroup, EuiFlexItem } from '@elastic/eui'; -import { FilterManager } from '../../../../../../src/plugins/data/public/'; - //@ts-ignore import { ComplianceRequirements } from './components/requirements'; import { ComplianceSubrequirements } from './components/subrequirements'; -import { - getElasticAlerts, - getIndexPattern, - IFilterParams, -} from '../../../react-services'; import { pciRequirementsFile } from '../../../../common/compliance-requirements/pci-requirements'; import { gdprRequirementsFile } from '../../../../common/compliance-requirements/gdpr-requirements'; import { hipaaRequirementsFile } from '../../../../common/compliance-requirements/hipaa-requirements'; import { nistRequirementsFile } from '../../../../common/compliance-requirements/nist-requirements'; import { tscRequirementsFile } from '../../../../common/compliance-requirements/tsc-requirements'; -import { KbnSearchBar } from '../../kbn-search-bar'; -import { getDataPlugin } from '../../../kibana-services'; -import { UI_LOGGER_LEVELS } from '../../../../common/constants'; +import { getPlugins } from '../../../kibana-services'; +import { + DATA_SOURCE_FILTER_CONTROLLED_REGULATORY_COMPLIANCE_REQUIREMENT, + UI_LOGGER_LEVELS, +} from '../../../../common/constants'; import { UI_ERROR_SEVERITIES } from '../../../react-services/error-orchestrator/types'; import { getErrorOrchestrator } from '../../../react-services/common-services'; import { withAgentSupportModule } from '../../common/hocs'; +import { + AlertsDataSourceRepository, + PatternDataSource, + tFilter, + tParsedIndexPattern, + useDataSource, +} from '../../common/data-source'; +import { IndexPattern } from '../../../../../../src/plugins/data/common'; +import useSearchBar from '../../common/search-bar/use-search-bar'; +import { LoadingSpinner } from '../../common/loading-spinner/loading-spinner'; +import { I18nProvider } from '@osd/i18n/react'; +import { useAsyncAction } from '../../common/hooks'; -export const ComplianceTable = withAgentSupportModule( - class ComplianceTable extends Component { - _isMount = false; - timefilter: { - getTime(): any; - setTime(time: any): void; - _history: { history: { items: { from: string; to: string }[] } }; - }; - - PluginPlatformServices: { [key: string]: any }; - filterManager: FilterManager; - indexPattern: any; - state: { - selectedRequirement: string; - flyoutOn: boolean; - filterParams: IFilterParams; - complianceObject: object; - descriptions: object; - loadingAlerts: boolean; - selectedRequirements: object; - }; - - props: any; - - constructor(props) { - super(props); - this.PluginPlatformServices = getDataPlugin().query; - this.filterManager = this.PluginPlatformServices.filterManager; - this.timefilter = this.PluginPlatformServices.timefilter.timefilter; - this.state = { - selectedRequirement: '', - flyoutOn: true, - complianceObject: {}, - descriptions: {}, - loadingAlerts: true, - selectedRequirements: {}, - filterParams: { - filters: this.filterManager.getFilters() || [], - query: { language: 'kuery', query: '' }, - time: this.timefilter.getTime(), - }, - }; - - this.onChangeSelectedRequirements.bind(this); - this.onQuerySubmit.bind(this); - this.onFiltersUpdated.bind(this); - } - - async componentDidMount() { - this._isMount = true; - this.filtersSubscriber = this.filterManager - .getUpdates$() - .subscribe(() => { - this.onFiltersUpdated(this.filterManager.getFilters()); - }); - this.indexPattern = await getIndexPattern(); - this.buildComplianceObject(); - } - - componentWillUnmount() { - this.filtersSubscriber.unsubscribe(); - } +const SearchBar = getPlugins().data.ui.SearchBar; - buildComplianceObject() { - try { - let complianceRequirements = {}; - let descriptions = {}; - let selectedRequirements = {}; // all enabled by default - if (this.props.section === 'pci') { - descriptions = pciRequirementsFile; - Object.keys(pciRequirementsFile).forEach(item => { - const currentRequirement = item.split('.')[0]; - if (complianceRequirements[currentRequirement]) { - complianceRequirements[currentRequirement].push(item); - } else { - selectedRequirements[currentRequirement] = true; - complianceRequirements[currentRequirement] = []; - complianceRequirements[currentRequirement].push(item); - } - }); //forEach +function buildComplianceObject({ section }) { + try { + let complianceRequirements = {}; + let descriptions = {}; + let selectedRequirements = {}; // all enabled by default + if (section === 'pci') { + descriptions = pciRequirementsFile; + Object.keys(pciRequirementsFile).forEach(item => { + const currentRequirement = item.split('.')[0]; + if (complianceRequirements[currentRequirement]) { + complianceRequirements[currentRequirement].push(item); + } else { + selectedRequirements[currentRequirement] = true; + complianceRequirements[currentRequirement] = []; + complianceRequirements[currentRequirement].push(item); } - if (this.props.section === 'gdpr') { - descriptions = gdprRequirementsFile; - Object.keys(gdprRequirementsFile).forEach(item => { - const currentRequirement = item.split('_')[0]; - if (complianceRequirements[currentRequirement]) { - complianceRequirements[currentRequirement].push(item); - } else { - selectedRequirements[currentRequirement] = true; - complianceRequirements[currentRequirement] = []; - complianceRequirements[currentRequirement].push(item); - } - }); //forEach + }); //forEach + } + if (section === 'gdpr') { + descriptions = gdprRequirementsFile; + Object.keys(gdprRequirementsFile).forEach(item => { + const currentRequirement = item.split('_')[0]; + if (complianceRequirements[currentRequirement]) { + complianceRequirements[currentRequirement].push(item); + } else { + selectedRequirements[currentRequirement] = true; + complianceRequirements[currentRequirement] = []; + complianceRequirements[currentRequirement].push(item); } + }); //forEach + } - if (this.props.section === 'hipaa') { - descriptions = hipaaRequirementsFile; - Object.keys(hipaaRequirementsFile).forEach(item => { - const currentRequirement = - item.split('.')[0] + - '.' + - item.split('.')[1] + - '.' + - item.split('.')[2]; - if (complianceRequirements[currentRequirement]) { - complianceRequirements[currentRequirement].push(item); - } else { - selectedRequirements[currentRequirement] = true; - complianceRequirements[currentRequirement] = []; - complianceRequirements[currentRequirement].push(item); - } - }); //forEach + if (section === 'hipaa') { + descriptions = hipaaRequirementsFile; + Object.keys(hipaaRequirementsFile).forEach(item => { + const currentRequirement = + item.split('.')[0] + + '.' + + item.split('.')[1] + + '.' + + item.split('.')[2]; + if (complianceRequirements[currentRequirement]) { + complianceRequirements[currentRequirement].push(item); + } else { + selectedRequirements[currentRequirement] = true; + complianceRequirements[currentRequirement] = []; + complianceRequirements[currentRequirement].push(item); } + }); //forEach + } - if (this.props.section === 'nist') { - descriptions = nistRequirementsFile; - Object.keys(nistRequirementsFile).forEach(item => { - const currentRequirement = item.split('.')[0]; - if (complianceRequirements[currentRequirement]) { - complianceRequirements[currentRequirement].push(item); - } else { - selectedRequirements[currentRequirement] = true; - complianceRequirements[currentRequirement] = []; - complianceRequirements[currentRequirement].push(item); - } - }); //forEach + if (section === 'nist') { + descriptions = nistRequirementsFile; + Object.keys(nistRequirementsFile).forEach(item => { + const currentRequirement = item.split('.')[0]; + if (complianceRequirements[currentRequirement]) { + complianceRequirements[currentRequirement].push(item); + } else { + selectedRequirements[currentRequirement] = true; + complianceRequirements[currentRequirement] = []; + complianceRequirements[currentRequirement].push(item); } - if (this.props.section === 'tsc') { - descriptions = tscRequirementsFile; - Object.keys(tscRequirementsFile).forEach(item => { - const currentRequirement = item.split('.')[0]; - if (complianceRequirements[currentRequirement]) { - complianceRequirements[currentRequirement].push(item); - } else { - selectedRequirements[currentRequirement] = true; - complianceRequirements[currentRequirement] = []; - complianceRequirements[currentRequirement].push(item); - } - }); //forEach + }); //forEach + } + if (section === 'tsc') { + descriptions = tscRequirementsFile; + Object.keys(tscRequirementsFile).forEach(item => { + const currentRequirement = item.split('.')[0]; + if (complianceRequirements[currentRequirement]) { + complianceRequirements[currentRequirement].push(item); + } else { + selectedRequirements[currentRequirement] = true; + complianceRequirements[currentRequirement] = []; + complianceRequirements[currentRequirement].push(item); } - - this._isMount && - this.setState( - { - complianceObject: complianceRequirements, - selectedRequirements, - descriptions, - }, - () => this.getRequirementsCount(), - ); - } catch (error) { - const options = { - context: `${ComplianceTable.name}.buildComplianceObject`, - level: UI_LOGGER_LEVELS.ERROR, - severity: UI_ERROR_SEVERITIES.BUSINESS, - store: true, - display: true, - error: { - error: error, - message: error.message || error, - title: `Compliance (${this.props.section}) data could not be fetched`, - }, - }; - getErrorOrchestrator().handleError(options); - } + }); //forEach } - onChangeSelectedRequirements = selectedRequirements => { - this.setState({ selectedRequirements }); + return { + complianceObject: complianceRequirements, + selectedRequirements, + descriptions, }; - - onQuerySubmit = (payload: { - dateRange: TimeRange; - query: Query | undefined; - }) => { - const { dateRange, query } = payload; - const { filters } = this.state.filterParams; - const filterParams: IFilterParams = { time: dateRange, filters, query }; - this.setState({ filterParams, loadingAlerts: true }); + } catch (error) { + const options = { + context: 'buildComplianceObject', + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.BUSINESS, + store: true, + display: true, + error: { + error: error, + message: error.message || error, + title: `Compliance (${section}) data could not be fetched`, + }, }; + getErrorOrchestrator().handleError(options); + } +} - onFiltersUpdated = (filters: []) => { - const { time, query } = this.state.filterParams; - const filterParams = { time, query, filters }; - this.setState({ filterParams, loadingAlerts: true }); - }; +export const ComplianceTable = withAgentSupportModule(props => { + const { DataSource, ...rest } = props; - async componentDidUpdate(prevProps) { - const { filterParams, loadingAlerts } = this.state; - if ( - JSON.stringify(prevProps.filterParams) !== - JSON.stringify(filterParams) && - loadingAlerts - ) { - this.getRequirementsCount(); - } - } + const { + filters, + dataSource, + fetchFilters, + isLoading: isDataSourceLoading, + fetchData, + setFilters, + } = useDataSource({ + DataSource, + repository: new AlertsDataSourceRepository(), + }); - async getRequirementsCount() { - try { - const { filterParams } = this.state; - if (!this.indexPattern) { - return; - } - let fieldAgg = ''; - if (this.props.section === 'pci') fieldAgg = 'rule.pci_dss'; - if (this.props.section === 'gdpr') fieldAgg = 'rule.gdpr'; - if (this.props.section === 'hipaa') fieldAgg = 'rule.hipaa'; - if (this.props.section === 'nist') fieldAgg = 'rule.nist_800_53'; - if (this.props.section === 'tsc') fieldAgg = 'rule.tsc'; - const aggs = { - tactics: { - terms: { - field: fieldAgg, - size: 100, + const { searchBarProps } = useSearchBar({ + indexPattern: dataSource?.indexPattern as IndexPattern, + filters, + setFilters, + }); + + const [complianceData, setComplianceData] = useState({ + descriptions: {}, + complianceObject: {}, + selectedRequirements: {}, + }); + + const getRegulatoryComplianceRequirementFilter = ( + key: string, + value: string, + ) => { + if (!value) return []; + return [ + { + meta: { + index: dataSource?.indexPattern.id, + negate: false, + disabled: false, + alias: null, + type: 'phrase', + key: key, + value: value, + params: { + query: value, + type: 'phrase', + }, + controlledBy: + DATA_SOURCE_FILTER_CONTROLLED_REGULATORY_COMPLIANCE_REQUIREMENT, + }, + query: { + match: { + [key]: { + query: value, + type: 'phrase', }, }, - }; - - // TODO: use `status` and `statusText` to show errors - // @ts-ignore - const { data, status, statusText } = await getElasticAlerts( - this.indexPattern, - filterParams, - aggs, - ); + }, + $state: { + store: 'appState', + }, + } as tFilter, + ]; + }; - const buckets = data?.aggregations?.tactics?.buckets || []; - /*if(firstTime){ - this.initTactics(buckets); // top tactics are checked on component mount - }*/ - this._isMount && - this.setState({ - requirementsCount: buckets, - loadingAlerts: false, - firstTime: false, - }); - } catch (error) { - const options = { - context: `${ComplianceTable.name}.buildComplianceObject`, - level: UI_LOGGER_LEVELS.ERROR, - severity: UI_ERROR_SEVERITIES.BUSINESS, - store: true, - display: true, - error: { - error: error, - message: error.message || error, - title: `Mitre alerts could not be fetched:`, + const getRequirementsCount = async ({ section, query, fetchData }) => { + try { + const mapFieldAgg = { + pci: 'rule.pci_dss', + gdpr: 'rule.gdpr', + hippa: 'rule.hipaa', + nist: 'rule.nist_800_53', + tsc: 'rule.tsc', + }; + const aggs = { + tactics: { + terms: { + field: mapFieldAgg[section], + size: 100, }, - }; - getErrorOrchestrator().handleError(options); - this.setState({ loadingAlerts: false }); - } - } + }, + }; - onChangeFlyout = flyoutOn => { - this.setState({ flyoutOn }); - }; + const data = await fetchData({ aggs, query }); - closeFlyout() { - this.setState({ flyoutOn: false }); + return data?.aggregations?.tactics?.buckets || []; + } catch (error) { + const options = { + context: 'buildComplianceObject', + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.BUSINESS, + store: true, + display: true, + error: { + error: error, + message: error.message || error, + title: `Alerts could not be fetched:`, + }, + }; + getErrorOrchestrator().handleError(options); } + }; + + const action = useAsyncAction(getRequirementsCount, [ + props.section, + dataSource, + searchBarProps.query, + ]); + + useEffect(() => { + const { descriptions, complianceObject, selectedRequirements } = + buildComplianceObject({ section: props.section }); + setComplianceData({ descriptions, complianceObject, selectedRequirements }); + }, []); - showFlyout(requirement) { - this.setState({ - selectedRequirement: requirement, - flyoutOn: true, + useEffect(() => { + if (dataSource) { + action.run({ + section: props.section, + fetchData, + query: searchBarProps.query, }); } + }, [ + dataSource, + JSON.stringify(searchBarProps.query), + JSON.stringify(fetchFilters), + ]); - render() { - const { complianceObject, loadingAlerts } = this.state; - return ( -
- - -
- + + + + {isDataSourceLoading && !dataSource ? ( + + ) : ( +
+
-
-
- - - - - {!!Object.keys(complianceObject).length && - this.state.filterParams.time.from !== 'init' && ( - - - - - - - this.props.onSelectedTabChanged(id) - } - {...this.state} - /> - - - )} - - - -
- ); - } - }, -); + )} +
+
+ + + + {!!Object.keys(complianceData.complianceObject).length && ( + + + + setComplianceData(state => ({ + ...state, + selectedRequirements, + })) + } + requirementsCount={action.data || []} + loadingAlerts={action.running} + {...complianceData} + /> + + + + props.onSelectedTabChanged(id) + } + requirementsCount={action.data || []} + loadingAlerts={action.running} + fetchFilters={fetchFilters} + getRegulatoryComplianceRequirementFilter={ + getRegulatoryComplianceRequirementFilter + } + {...complianceData} + /> + + + )} + + + + + + ); +}); diff --git a/plugins/main/public/components/overview/compliance-table/components/requirement-flyout/requirement-flyout.tsx b/plugins/main/public/components/overview/compliance-table/components/requirement-flyout/requirement-flyout.tsx index 8f21e4c505..df55448645 100644 --- a/plugins/main/public/components/overview/compliance-table/components/requirement-flyout/requirement-flyout.tsx +++ b/plugins/main/public/components/overview/compliance-table/components/requirement-flyout/requirement-flyout.tsx @@ -11,7 +11,6 @@ */ import React, { Component } from 'react'; import { - EuiFlyout, EuiFlyoutHeader, EuiLoadingContent, EuiTitle, @@ -23,228 +22,359 @@ import { EuiText, EuiFlexItem, EuiSpacer, + EuiLink, } from '@elastic/eui'; -import { Discover } from '../../../../common/modules/discover'; import { AppState } from '../../../../../react-services/app-state'; import { requirementGoal } from '../../requirement-goal'; -import { getUiSettings } from '../../../../../kibana-services'; -import { FilterManager } from '../../../../../../../../src/plugins/data/public/'; +import { getCore, getUiSettings } from '../../../../../kibana-services'; +import { + FilterManager, + IndexPattern, +} from '../../../../../../../../src/plugins/data/public/'; import { WzFlyout } from '../../../../../components/common/flyouts'; +import { WazuhFlyoutDiscover } from '../../../../common/wazuh-discover/wz-flyout-discover'; +import { PatternDataSource } from '../../../../common/data-source'; +import { formatUIDate } from '../../../../../react-services'; +import TechniqueRowDetails from '../../../mitre/framework/components/techniques/components/flyout-technique/technique-row-details'; +import { buildPhraseFilter } from '../../../../../../../../src/plugins/data/common'; +import { connect } from 'react-redux'; +import { rules } from '../../../../../utils/applications'; +import { endpointSummary } from '../../../../../utils/applications'; + +const renderRequirements = (value: []) => { + return ( + + {value.map(v => { + return {v}; + })} + + ); +}; + +const mapStateToProps = state => ({ + currentAgentData: state.appStateReducers.currentAgentData, +}); + +export const RequirementFlyout = connect(mapStateToProps)( + class RequirementFlyout extends Component { + _isMount = false; + state: {}; + + props!: {}; + + filterManager: FilterManager; + + constructor(props) { + super(props); + this.state = {}; + this.filterManager = new FilterManager(getUiSettings()); + } -export class RequirementFlyout extends Component { - _isMount = false; - state: {}; - - props!: {}; - - filterManager: FilterManager; - - constructor(props) { - super(props); - this.state = {}; - this.filterManager = new FilterManager(getUiSettings()); - } - - componentDidMount() { - this._isMount = true; - } - - renderHeader() { - const { currentRequirement } = this.props; - return ( - - {(!currentRequirement && ( -
- -
- )) || ( - -

Requirement {currentRequirement}

-
- )} -
- ); - } - - updateTotalHits = (total) => { - this.setState({ totalHits: total }); - }; - - renderBody() { - const { currentRequirement } = this.props; - const requirementImplicitFilter = {}; - const isCluster = (AppState.getClusterInfo() || {}).status === 'enabled'; - const clusterFilter = isCluster - ? { 'cluster.name': AppState.getClusterInfo().cluster } - : { 'manager.name': AppState.getClusterInfo().manager }; - this.clusterFilter = clusterFilter; - requirementImplicitFilter[this.props.getRequirementKey()] = currentRequirement; - - const implicitFilters = [requirementImplicitFilter, this.clusterFilter]; - if (this.props.implicitFilters) { - this.props.implicitFilters.forEach((item) => implicitFilters.push(item)); + componentDidMount() { + this._isMount = true; } - //Goal for PCI - const currentReq = this.props.currentRequirement.split('.')[0]; - - return ( - - -

Details

+ + getDiscoverColumns() { + const agentId = this.props.currentAgentData?.id; + return agentId + ? [ + { + id: 'timestamp', + displayAsText: 'Time', + render: value => formatUIDate(value), + }, + { + id: this.props.getRequirementKey(), + displayAsText: 'Requirement(s)', + render: renderRequirements, + }, + { id: 'rule.description', displayAsText: 'Description' }, + { id: 'rule.level', displayAsText: 'Level' }, + { + id: 'rule.id', + displayAsText: 'Rule ID', + render: value => ( + { + getCore().application.navigateToApp(rules.id, { + path: `#/manager/?tab=rules&redirectRule=${value}`, + }); + }} + > + {value} + + ), + }, + ] + : [ + { + id: 'timestamp', + displayAsText: 'Time', + render: value => formatUIDate(value), + }, + { + id: 'agent.id', + displayAsText: 'Agent', + render: value => ( + { + getCore().application.navigateToApp(endpointSummary.id, { + path: `#/agents/?tab=welcome&agent=${value}`, + }); + }} + > + {value} + + ), + }, + { + id: 'agent.name', + displayAsText: 'Agent name', + }, + { + id: this.props.getRequirementKey(), + displayAsText: 'Requirement', + render: renderRequirements, + }, + { id: 'rule.description', displayAsText: 'Description' }, + { id: 'rule.level', displayAsText: 'Level' }, + { + id: 'rule.id', + displayAsText: 'Rule ID', + render: value => ( + { + getCore().application.navigateToApp(rules.id, { + path: `#/manager/?tab=rules&redirectRule=${value}`, + }); + }} + > + {value} + + ), + }, + ]; + } + + renderHeader() { + const { currentRequirement } = this.props; + return ( + + {(!currentRequirement && ( +
+ +
+ )) || ( + +

Requirement {currentRequirement}

- } - paddingSize="xs" - initialIsOpen={true} - > -
- - {requirementGoal[currentReq] && ( - + )} + + ); + } + + renderDiscoverExpandedRow(props: { + doc: any; + item: any; + indexPattern: any; + }) { + return ( + { + // add filters to the filter state + // generate the filter + const key = Object.keys(value)[0]; + const filterValue = value[key]; + const valuesArray = Array.isArray(filterValue) + ? [...filterValue] + : [filterValue]; + const newFilter = valuesArray + .map(item => + buildPhraseFilter( + { name: key, type: 'string' }, + item, + indexPattern, + ), + ) + .filter(Boolean); + + this.filterManager.addFilters(newFilter); + }} + /> + ); + } + + renderBody() { + const { currentRequirement } = this.props; + const requirementImplicitFilter = {}; + const isCluster = (AppState.getClusterInfo() || {}).status === 'enabled'; + const clusterFilter = isCluster + ? { 'cluster.name': AppState.getClusterInfo().cluster } + : { 'manager.name': AppState.getClusterInfo().manager }; + this.clusterFilter = clusterFilter; + requirementImplicitFilter[this.props.getRequirementKey()] = + currentRequirement; + + const implicitFilters = [requirementImplicitFilter, this.clusterFilter]; + if (this.props.implicitFilters) { + this.props.implicitFilters.forEach(item => implicitFilters.push(item)); + } + //Goal for PCI + const currentReq = this.props.currentRequirement.split('.')[0]; + + return ( + + +

Details

+ + } + paddingSize='xs' + initialIsOpen={true} + > +
+ + {requirementGoal[currentReq] && ( + + + + + + +

Goals

+ +

{requirementGoal[currentReq]}

+
+
+
+ )} + + - + -

Goals

+

+ Requirement description +

-

{requirementGoal[currentReq]}

+

{this.props.description}

- )} - - - - - - - -

Requirement description

- -

{this.props.description}

-
-
-
- -
-
- - - - {this.state.totalHits || 0} hits +
- } - buttonContent={ - -

- Recent events - {this.props.view !== 'events' && ( - - - - { - this.props.openDashboard(e, currentRequirement); - e.stopPropagation(); - }} - color="primary" - type="visualizeApp" - style={{ marginRight: '10px' }} - > - - - { - this.props.openDiscover(e, currentRequirement); - e.stopPropagation(); - }} - color="primary" - type="discoverApp" - > - + + + + +

+ Recent events + {this.props.view !== 'events' && ( + + + + { + this.props.openDashboard(e, currentRequirement); + e.stopPropagation(); + }} + color='primary' + type='visualizeApp' + style={{ marginRight: '10px' }} + > + + + { + this.props.openDiscover(e, currentRequirement); + e.stopPropagation(); + }} + color='primary' + type='discoverApp' + > + + - - )} -

- - } - paddingSize="none" - initialIsOpen={true} - > - - - this.updateTotalHits(total)} + )} +

+
+ } + paddingSize='none' + initialIsOpen={true} + > +
+ + this.renderDiscoverExpandedRow(...args) + } /> - - - - - ); - } - - renderLoading() { - return ( - - - - - ); - } - - render() { - const { currentRequirement } = this.props; - const { onChangeFlyout } = this.props; - return ( - onChangeFlyout(false)} - flyoutProps={{ - maxWidth: '60%', - size: 'l', - className: 'flyout-no-overlap wz-inventory wzApp', - 'aria-labelledby': 'flyoutSmallTitle', - }} - > - {currentRequirement && this.renderHeader()} - {this.renderBody()} - {this.state.loading && this.renderLoading()} - - ); - } -} +
+
+
+ ); + } + + renderLoading() { + return ( + + + + + ); + } + + render() { + const { currentRequirement } = this.props; + const { onChangeFlyout } = this.props; + return ( + onChangeFlyout(false)} + flyoutProps={{ + maxWidth: '60%', + size: 'l', + className: 'flyout-no-overlap wz-inventory wzApp', + 'aria-labelledby': 'flyoutSmallTitle', + }} + > + {currentRequirement && this.renderHeader()} + {this.renderBody()} + {this.state.loading && this.renderLoading()} + + ); + } + }, +); diff --git a/plugins/main/public/components/overview/compliance-table/components/subrequirements/subrequirements.tsx b/plugins/main/public/components/overview/compliance-table/components/subrequirements/subrequirements.tsx index b9fef190f6..55b71ad380 100644 --- a/plugins/main/public/components/overview/compliance-table/components/subrequirements/subrequirements.tsx +++ b/plugins/main/public/components/overview/compliance-table/components/subrequirements/subrequirements.tsx @@ -26,7 +26,6 @@ import { EuiIcon, EuiLoadingSpinner, } from '@elastic/eui'; -import { AppNavigate } from '../../../../../react-services/app-navigate'; import { AppState } from '../../../../../react-services/app-state'; import { RequirementFlyout } from '../requirement-flyout/requirement-flyout'; import { @@ -82,62 +81,32 @@ export class ComplianceSubrequirements extends Component { } getRequirementKey() { - if (this.props.section === 'pci') { - return 'rule.pci_dss'; - } - if (this.props.section === 'gdpr') { - return 'rule.gdpr'; - } - if (this.props.section === 'nist') { - return 'rule.nist_800_53'; - } - if (this.props.section === 'hipaa') { - return 'rule.hipaa'; - } - if (this.props.section === 'tsc') { - return 'rule.tsc'; - } - return 'pci_dss'; + const mapKeys = { + pci: 'rule.pci_dss', + gdpr: 'rule.gdpr', + nist: 'rule.nist_800_53', + hipaa: 'rule.hipaa', + tsc: 'rule.tsc', + }; + return mapKeys[this.props.section]; } - openDashboardCurrentWindow(requirementId) { + openDiscover(e, requirementId) { this.addFilter({ key: this.getRequirementKey(), value: requirementId, negate: false, }); - this.props.onSelectedTabChanged('dashboard'); + this.props.onSelectedTabChanged('events'); } - openDiscoverCurrentWindow(requirementId) { + openDashboard(e, requirementId) { this.addFilter({ key: this.getRequirementKey(), value: requirementId, negate: false, }); - this.props.onSelectedTabChanged('events'); - } - - openDiscover(e, requirementId) { - const filters = {}; - filters[this.getRequirementKey()] = requirementId; - AppNavigate.navigateToModule( - e, - 'overview', - { tab: this.props.section, tabView: 'discover', filters }, - () => this.openDiscoverCurrentWindow(requirementId), - ); - } - - openDashboard(e, requirementId) { - const filters = {}; - filters[this.getRequirementKey()] = requirementId; - AppNavigate.navigateToModule( - e, - 'overview', - { tab: this.props.section, tabView: 'panels', filters }, - () => this.openDashboardCurrentWindow(requirementId), - ); + this.props.onSelectedTabChanged('dashboard'); } renderFacet() { @@ -234,7 +203,7 @@ export class ComplianceSubrequirements extends Component { { @@ -383,6 +352,13 @@ export class ComplianceSubrequirements extends Component { getRequirementKey={() => { return this.getRequirementKey(); }} + fetchFilters={[ + ...this.props.fetchFilters, + ...this.props.getRegulatoryComplianceRequirementFilter( + this.getRequirementKey(), + this.state.selectedRequirement, + ), + ]} openDashboard={(e, itemId) => this.openDashboard(e, itemId)} openDiscover={(e, itemId) => this.openDiscover(e, itemId)} /> diff --git a/plugins/main/public/components/overview/pci/dashboards/dashboard-panels.ts b/plugins/main/public/components/overview/pci/dashboards/dashboard-panels.ts new file mode 100644 index 0000000000..3157ffc199 --- /dev/null +++ b/plugins/main/public/components/overview/pci/dashboards/dashboard-panels.ts @@ -0,0 +1,1045 @@ +import { DashboardPanelState } from '../../../../../../../src/plugins/dashboard/public/application'; +import { EmbeddableInput } from '../../../../../../../src/plugins/embeddable/public'; + +const getVisStateTopRequirements = (indexPatternId: string) => { + return { + id: 'Wazuh-App-Overview-PCI-DSS-requirements', + title: 'Top 10 PCI DSS requirements', + type: 'line', + params: { + type: 'line', + grid: { categoryLines: true, valueAxis: 'ValueAxis-1' }, + categoryAxes: [ + { + id: 'CategoryAxis-1', + type: 'category', + position: 'bottom', + show: true, + style: {}, + scale: { type: 'linear' }, + labels: { show: true, filter: true, truncate: 100 }, + title: {}, + }, + ], + valueAxes: [ + { + id: 'ValueAxis-1', + name: 'LeftAxis-1', + type: 'value', + position: 'left', + show: true, + style: {}, + scale: { type: 'linear', mode: 'normal' }, + labels: { show: true, rotate: 0, filter: false, truncate: 100 }, + title: { text: 'Count' }, + }, + ], + seriesParams: [ + { + show: 'true', + type: 'line', + mode: 'normal', + data: { label: 'Count', id: '1' }, + valueAxis: 'ValueAxis-1', + drawLinesBetweenPoints: false, + showCircles: true, + }, + ], + addTooltip: true, + addLegend: true, + legendPosition: 'right', + times: [], + addTimeMarker: false, + dimensions: { + x: { + accessor: 0, + format: { id: 'date', params: { pattern: 'YYYY-MM-DD' } }, + params: { date: true, interval: 'P1D', format: 'YYYY-MM-DD' }, + aggType: 'date_histogram', + }, + y: [ + { + accessor: 2, + format: { id: 'number' }, + params: {}, + aggType: 'count', + }, + ], + z: [ + { + accessor: 3, + format: { id: 'number' }, + params: {}, + aggType: 'count', + }, + ], + series: [ + { + accessor: 1, + format: { + id: 'terms', + params: { + id: 'string', + otherBucketLabel: 'Other', + missingBucketLabel: 'Missing', + }, + }, + params: {}, + aggType: 'terms', + }, + ], + }, + radiusRatio: 50, + }, + uiState: {}, + data: { + searchSource: { + query: { + language: 'kuery', + query: '', + }, + filter: [], + index: indexPatternId, + }, + references: [ + { + name: 'kibanaSavedObjectMeta.searchSourceJSON.index', + type: 'index-pattern', + id: indexPatternId, + }, + ], + aggs: [ + { + id: '1', + enabled: true, + type: 'count', + schema: 'metric', + params: {}, + }, + { + id: '2', + enabled: true, + type: 'date_histogram', + schema: 'segment', + params: { + field: 'timestamp', + timeRange: { from: 'now-1h', to: 'now' }, + useNormalizedEsInterval: true, + interval: 'auto', + drop_partials: false, + min_doc_count: 1, + extended_bounds: {}, + }, + }, + { + id: '4', + enabled: true, + type: 'count', + schema: 'radius', + params: {}, + }, + { + id: '4', + enabled: true, + type: 'count', + schema: 'radius', + params: {}, + }, + ], + }, + }; +}; + +const getVisStateTopAgentsByCount = (indexPatternId: string) => { + return { + id: 'Wazuh-App-Overview-PCI-DSS-Agents', + title: 'Top 10 agents by alerts count', + type: 'pie', + params: { + type: 'pie', + addTooltip: true, + addLegend: true, + legendPosition: 'right', + isDonut: true, + }, + uiState: {}, + data: { + searchSource: { + query: { + language: 'kuery', + query: '', + }, + filter: [], + index: indexPatternId, + }, + references: [ + { + name: 'kibanaSavedObjectMeta.searchSourceJSON.index', + type: 'index-pattern', + id: indexPatternId, + }, + ], + aggs: [ + { + id: '1', + enabled: true, + type: 'count', + schema: 'metric', + params: {}, + }, + { + id: '2', + enabled: true, + type: 'terms', + schema: 'segment', + params: { + field: 'agent.name', + size: 10, + order: 'desc', + orderBy: '1', + }, + }, + ], + }, + }; +}; + +const getVisStateRequirementsOverTime = (indexPatternId: string) => { + return { + id: 'Wazuh-App-Overview-PCI-DSS-Requirements-over-time', + title: 'Top requirements over time', + type: 'area', + params: { + type: 'area', + grid: { + categoryLines: true, + style: { color: '#eee' }, + valueAxis: 'ValueAxis-1', + }, + categoryAxes: [ + { + id: 'CategoryAxis-1', + type: 'category', + position: 'bottom', + show: true, + style: {}, + scale: { type: 'linear' }, + labels: { show: true, filter: true, truncate: 100 }, + title: {}, + }, + ], + valueAxes: [ + { + id: 'ValueAxis-1', + name: 'LeftAxis-1', + type: 'value', + position: 'left', + show: true, + style: {}, + scale: { type: 'linear', mode: 'normal' }, + labels: { show: true, rotate: 0, filter: false, truncate: 100 }, + title: { text: 'Count' }, + }, + ], + seriesParams: [ + { + show: 'true', + type: 'area', + mode: 'stacked', + data: { label: 'Count', id: '1' }, + drawLinesBetweenPoints: true, + showCircles: true, + interpolate: 'cardinal', + valueAxis: 'ValueAxis-1', + }, + ], + addTooltip: true, + addLegend: true, + legendPosition: 'right', + times: [], + addTimeMarker: false, + }, + uiState: {}, + data: { + searchSource: { + query: { + language: 'kuery', + query: '', + }, + filter: [], + index: indexPatternId, + }, + references: [ + { + name: 'kibanaSavedObjectMeta.searchSourceJSON.index', + type: 'index-pattern', + id: indexPatternId, + }, + ], + aggs: [ + { + id: '1', + enabled: true, + type: 'count', + schema: 'metric', + params: {}, + }, + { + id: '1', + enabled: true, + type: 'count', + schema: 'metric', + params: {}, + }, + { + id: '3', + enabled: true, + type: 'terms', + schema: 'group', + params: { + field: 'rule.pci_dss', + size: '5', + order: 'desc', + orderBy: '1', + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + }, + }, + { + id: '2', + enabled: true, + type: 'date_histogram', + schema: 'segment', + params: { + field: 'timestamp', + timeRange: { from: 'now-24h', to: 'now', mode: 'quick' }, + useNormalizedEsInterval: true, + interval: 'auto', + time_zone: 'Europe/Berlin', + drop_partials: false, + customInterval: '2h', + min_doc_count: 1, + extended_bounds: {}, + }, + }, + ], + }, + }; +}; + +const getVisStateRequirementsHeatmap = (indexPatternId: string) => { + return { + id: 'Wazuh-App-Overview-PCI-DSS-Requirements-Agents-heatmap', + title: 'Last alerts', + type: 'heatmap', + params: { + type: 'heatmap', + addTooltip: true, + addLegend: true, + enableHover: false, + legendPosition: 'right', + times: [], + colorsNumber: 10, + colorSchema: 'Greens', + setColorRange: false, + colorsRange: [], + invertColors: false, + percentageMode: false, + valueAxes: [ + { + show: false, + id: 'ValueAxis-1', + type: 'value', + scale: { type: 'linear', defaultYExtents: false }, + labels: { + show: false, + rotate: 0, + overwriteColor: false, + color: '#555', + }, + }, + ], + }, + uiState: { + vis: { + defaultColors: { + '0 - 13': 'rgb(247,252,245)', + '13 - 26': 'rgb(233,247,228)', + '26 - 39': 'rgb(211,238,205)', + '39 - 52': 'rgb(184,227,177)', + '52 - 65': 'rgb(152,213,148)', + '65 - 78': 'rgb(116,196,118)', + '78 - 91': 'rgb(75,176,98)', + '91 - 104': 'rgb(47,152,79)', + '104 - 117': 'rgb(21,127,59)', + '117 - 130': 'rgb(0,100,40)', + }, + }, + }, + data: { + searchSource: { + query: { + language: 'kuery', + query: '', + }, + filter: [], + index: indexPatternId, + }, + references: [ + { + name: 'kibanaSavedObjectMeta.searchSourceJSON.index', + type: 'index-pattern', + id: indexPatternId, + }, + ], + aggs: [ + { + id: '1', + enabled: true, + type: 'count', + schema: 'metric', + params: {}, + }, + { + id: '2', + enabled: true, + type: 'terms', + schema: 'segment', + params: { + field: 'rule.pci_dss', + size: 5, + order: 'desc', + orderBy: '1', + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + customLabel: 'Requirements', + }, + }, + { + id: '3', + enabled: true, + type: 'terms', + schema: 'group', + params: { + field: 'agent.name', + size: 5, + order: 'desc', + orderBy: '1', + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + customLabel: 'Agents', + }, + }, + ], + }, + }; +}; + +const getVisStateRequirementsByAgent = (indexPatternId: string) => { + return { + id: 'Wazuh-App-Overview-PCI-DSS-Requirements-by-agent', + title: 'Requirements by agent', + type: 'histogram', + params: { + type: 'histogram', + grid: { + categoryLines: false, + style: { + color: '#eee', + }, + }, + categoryAxes: [ + { + id: 'CategoryAxis-1', + type: 'category', + position: 'bottom', + show: true, + style: {}, + scale: { + type: 'linear', + }, + labels: { + show: true, + filter: true, + truncate: 100, + rotate: 0, + }, + title: {}, + }, + ], + valueAxes: [ + { + id: 'ValueAxis-1', + name: 'LeftAxis-1', + type: 'value', + position: 'left', + show: true, + style: {}, + scale: { + type: 'linear', + mode: 'normal', + }, + labels: { + show: true, + rotate: 0, + filter: false, + truncate: 100, + }, + title: { + text: 'Count', + }, + }, + ], + seriesParams: [ + { + show: 'true', + type: 'histogram', + mode: 'stacked', + data: { + label: 'Count', + id: '1', + }, + valueAxis: 'ValueAxis-1', + drawLinesBetweenPoints: true, + showCircles: true, + }, + ], + addTooltip: true, + addLegend: true, + legendPosition: 'right', + times: [], + addTimeMarker: false, + radiusRatio: 51, + labels: { + show: false, + }, + thresholdLine: { + show: false, + value: 10, + width: 1, + style: 'full', + color: '#E7664C', + }, + }, + uiState: {}, + data: { + searchSource: { + query: { + language: 'kuery', + query: '', + }, + filter: [], + index: indexPatternId, + }, + references: [ + { + name: 'kibanaSavedObjectMeta.searchSourceJSON.index', + type: 'index-pattern', + id: indexPatternId, + }, + ], + aggs: [ + { + id: '1', + enabled: true, + type: 'count', + params: {}, + schema: 'metric', + }, + { + id: '3', + enabled: true, + type: 'terms', + params: { + field: 'agent.name', + orderBy: '1', + order: 'desc', + size: 5, + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + }, + schema: 'group', + }, + { + id: '2', + enabled: true, + type: 'terms', + params: { + field: 'rule.pci_dss', + orderBy: '1', + order: 'desc', + size: 5, + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + customLabel: 'Requirements', + }, + schema: 'segment', + }, + ], + }, + }; +}; + +const getVisStateAgentTopRuleGroups = (indexPatternId: string) => { + return { + id: 'Wazuh-App-Agents-PCI-Groups', + title: 'Top 5 rule groups', + type: 'pie', + params: { + type: 'pie', + addTooltip: true, + addLegend: true, + legendPosition: 'right', + isDonut: true, + }, + uiState: {}, + data: { + searchSource: { + query: { + language: 'kuery', + query: '', + }, + filter: [], + index: indexPatternId, + }, + references: [ + { + name: 'kibanaSavedObjectMeta.searchSourceJSON.index', + type: 'index-pattern', + id: indexPatternId, + }, + ], + aggs: [ + { id: '1', enabled: true, type: 'count', schema: 'metric', params: {} }, + { + id: '2', + enabled: true, + type: 'terms', + schema: 'segment', + params: { + field: 'rule.groups', + size: 5, + order: 'desc', + orderBy: '1', + }, + }, + ], + }, + }; +}; + +const getVisStateAgentTopRules = (indexPatternId: string) => { + return { + id: 'Wazuh-App-Agents-PCI-Rule', + title: 'Top 5 rules', + type: 'pie', + params: { + type: 'pie', + addTooltip: true, + addLegend: true, + legendPosition: 'right', + isDonut: true, + }, + uiState: {}, + data: { + searchSource: { + query: { + language: 'kuery', + query: '', + }, + filter: [], + index: indexPatternId, + }, + references: [ + { + name: 'kibanaSavedObjectMeta.searchSourceJSON.index', + type: 'index-pattern', + id: indexPatternId, + }, + ], + aggs: [ + { id: '1', enabled: true, type: 'count', schema: 'metric', params: {} }, + { + id: '2', + enabled: true, + type: 'terms', + schema: 'segment', + params: { + field: 'rule.description', + size: 5, + order: 'desc', + orderBy: '1', + }, + }, + ], + }, + }; +}; + +const getVisStateAgentTopRequirements = (indexPatternId: string) => { + return { + id: 'Wazuh-App-Agents-PCI-Requirement', + title: 'Top 5 PCI DSS requirements', + type: 'pie', + params: { + type: 'pie', + addTooltip: true, + addLegend: true, + legendPosition: 'right', + isDonut: true, + }, + uiState: {}, + data: { + searchSource: { + query: { + language: 'kuery', + query: '', + }, + filter: [], + index: indexPatternId, + }, + references: [ + { + name: 'kibanaSavedObjectMeta.searchSourceJSON.index', + type: 'index-pattern', + id: indexPatternId, + }, + ], + aggs: [ + { id: '1', enabled: true, type: 'count', schema: 'metric', params: {} }, + { + id: '2', + enabled: true, + type: 'terms', + schema: 'segment', + params: { + field: 'rule.pci_dss', + size: 5, + order: 'desc', + orderBy: '1', + }, + }, + ], + }, + }; +}; + +const getVisStateAgentTopRequirementsCount = (indexPatternId: string) => { + return { + id: 'Wazuh-App-Agents-PCI-Requirements', + title: 'PCI DSS requirements', + type: 'histogram', + params: { + type: 'histogram', + grid: { categoryLines: false, style: { color: '#eee' } }, + categoryAxes: [ + { + id: 'CategoryAxis-1', + type: 'category', + position: 'bottom', + show: true, + style: {}, + scale: { type: 'linear' }, + labels: { show: true, filter: true, truncate: 100, rotate: 0 }, + title: {}, + }, + ], + valueAxes: [ + { + id: 'ValueAxis-1', + name: 'LeftAxis-1', + type: 'value', + position: 'left', + show: true, + style: {}, + scale: { type: 'linear', mode: 'normal' }, + labels: { show: true, rotate: 0, filter: false, truncate: 100 }, + title: { text: 'Count' }, + }, + ], + seriesParams: [ + { + show: 'true', + type: 'histogram', + mode: 'stacked', + data: { label: 'Count', id: '1' }, + valueAxis: 'ValueAxis-1', + drawLinesBetweenPoints: true, + showCircles: true, + }, + ], + addTooltip: true, + addLegend: true, + legendPosition: 'right', + times: [], + addTimeMarker: false, + }, + uiState: {}, + data: { + searchSource: { + query: { + language: 'kuery', + query: '', + }, + filter: [], + index: indexPatternId, + }, + references: [ + { + name: 'kibanaSavedObjectMeta.searchSourceJSON.index', + type: 'index-pattern', + id: indexPatternId, + }, + ], + aggs: [ + { id: '1', enabled: true, type: 'count', schema: 'metric', params: {} }, + { + id: '3', + enabled: true, + type: 'terms', + schema: 'group', + params: { + field: 'rule.pci_dss', + size: 5, + order: 'desc', + orderBy: '1', + customLabel: '', + }, + }, + { + id: '2', + enabled: true, + type: 'terms', + schema: 'segment', + params: { + field: 'rule.pci_dss', + size: 10, + order: 'desc', + orderBy: '1', + customLabel: 'PCI DSS Requirements', + }, + }, + ], + }, + }; +}; + +const getVisStateAgentRuleLevelDistribution = (indexPatternId: string) => { + return { + id: 'Wazuh-App-Agents-PCI-Rule-level-distribution', + title: 'Rule level distribution', + type: 'pie', + params: { + type: 'pie', + addTooltip: true, + addLegend: false, + legendPosition: 'right', + isDonut: true, + labels: { show: true, values: true, last_level: true, truncate: 100 }, + }, + uiState: { vis: { legendOpen: false } }, + data: { + searchSource: { + query: { + language: 'kuery', + query: '', + }, + filter: [], + index: indexPatternId, + }, + references: [ + { + name: 'kibanaSavedObjectMeta.searchSourceJSON.index', + type: 'index-pattern', + id: indexPatternId, + }, + ], + aggs: [ + { id: '1', enabled: true, type: 'count', schema: 'metric', params: {} }, + { + id: '2', + enabled: true, + type: 'terms', + schema: 'segment', + params: { + field: 'rule.level', + size: 15, + order: 'desc', + orderBy: '1', + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + }, + }, + ], + }, + }; +}; + +export const getDashboardPanels = ( + indexPatternId: string, + isPinnedAgent: boolean, +): { + [panelId: string]: DashboardPanelState< + EmbeddableInput & { [k: string]: unknown } + >; +} => { + const overviewDashboard = { + g1: { + gridData: { + w: 24, + h: 14, + x: 0, + y: 0, + i: 'g1', + }, + type: 'visualization', + explicitInput: { + id: 'g1', + savedVis: getVisStateTopRequirements(indexPatternId), + }, + }, + g2: { + gridData: { + w: 24, + h: 14, + x: 24, + y: 0, + i: 'g2', + }, + type: 'visualization', + explicitInput: { + id: 'g2', + savedVis: getVisStateTopAgentsByCount(indexPatternId), + }, + }, + g3: { + gridData: { + w: 48, + h: 11, + x: 0, + y: 14, + i: 'g3', + }, + type: 'visualization', + explicitInput: { + id: 'g3', + savedVis: getVisStateRequirementsOverTime(indexPatternId), + }, + }, + g4: { + gridData: { + w: 48, + h: 19, + x: 0, + y: 25, + i: 'g4', + }, + type: 'visualization', + explicitInput: { + id: 'g4', + savedVis: getVisStateRequirementsHeatmap(indexPatternId), + }, + }, + g5: { + gridData: { + w: 48, + h: 9, + x: 0, + y: 43, + i: 'g5', + }, + type: 'visualization', + explicitInput: { + id: 'g5', + savedVis: getVisStateRequirementsByAgent(indexPatternId), + }, + }, + }; + + const agentDashboard = { + a1: { + gridData: { + w: 16, + h: 11, + x: 0, + y: 0, + i: 'a1', + }, + type: 'visualization', + explicitInput: { + id: 'a1', + savedVis: getVisStateAgentTopRuleGroups(indexPatternId), + }, + }, + a2: { + gridData: { + w: 16, + h: 11, + x: 16, + y: 0, + i: 'a2', + }, + type: 'visualization', + explicitInput: { + id: 'a2', + savedVis: getVisStateAgentTopRules(indexPatternId), + }, + }, + a3: { + gridData: { + w: 16, + h: 11, + x: 32, + y: 0, + i: 'a3', + }, + type: 'visualization', + explicitInput: { + id: 'a3', + savedVis: getVisStateAgentTopRequirements(indexPatternId), + }, + }, + a4: { + gridData: { + w: 35, + h: 11, + x: 0, + y: 11, + i: 'a4', + }, + type: 'visualization', + explicitInput: { + id: 'a4', + savedVis: getVisStateAgentTopRequirementsCount(indexPatternId), + }, + }, + a5: { + gridData: { + w: 13, + h: 11, + x: 35, + y: 11, + i: 'a5', + }, + type: 'visualization', + explicitInput: { + id: 'a5', + savedVis: getVisStateAgentRuleLevelDistribution(indexPatternId), + }, + }, + }; + + return isPinnedAgent ? agentDashboard : overviewDashboard; +}; diff --git a/plugins/main/public/components/overview/pci/dashboards/dashboard.tsx b/plugins/main/public/components/overview/pci/dashboards/dashboard.tsx new file mode 100644 index 0000000000..f847211351 --- /dev/null +++ b/plugins/main/public/components/overview/pci/dashboards/dashboard.tsx @@ -0,0 +1,145 @@ +import React, { useState, useEffect } from 'react'; +import { SearchResponse } from '../../../../../../../src/core/server'; +import { getPlugins } from '../../../../kibana-services'; +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 './styles.scss'; +import { withErrorBoundary } from '../../../common/hocs'; +import { IndexPattern } from '../../../../../../../src/plugins/data/common'; +import { + ErrorFactory, + ErrorHandler, + HttpError, +} from '../../../../react-services/error-management'; +import { compose } from 'redux'; +import { SampleDataWarning } from '../../../visualize/components'; +import { + AlertsDataSourceRepository, + PatternDataSource, + tParsedIndexPattern, + useDataSource, +} from '../../../common/data-source'; +import { AlertsPCIDSSDataSource } from '../../../common/data-source/pattern/alerts/pci-dss/alerts-pci-dss-data-source'; +import { DiscoverNoResults } from '../../../common/no-results/no-results'; +import { LoadingSpinner } from '../../../common/loading-spinner/loading-spinner'; + +const plugins = getPlugins(); + +const SearchBar = getPlugins().data.ui.SearchBar; + +const DashboardByRenderer = plugins.dashboard.DashboardContainerByValueRenderer; + +const DashboardPCIDSSComponent: React.FC = () => { + const { + filters, + dataSource, + fetchFilters, + isLoading: isDataSourceLoading, + fetchData, + setFilters, + } = useDataSource({ + DataSource: AlertsPCIDSSDataSource, + repository: new AlertsDataSourceRepository(), + }); + + const [results, setResults] = useState({} 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); + }); + }, [ + 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} + +
+ + ); +}; + +export const DashboardPCIDSS = compose(withErrorBoundary)( + DashboardPCIDSSComponent, +); diff --git a/plugins/main/public/components/overview/pci/dashboards/index.tsx b/plugins/main/public/components/overview/pci/dashboards/index.tsx new file mode 100644 index 0000000000..b691822976 --- /dev/null +++ b/plugins/main/public/components/overview/pci/dashboards/index.tsx @@ -0,0 +1 @@ +export * from './dashboard'; \ No newline at end of file diff --git a/plugins/main/public/components/overview/pci/dashboards/styles.scss b/plugins/main/public/components/overview/pci/dashboards/styles.scss new file mode 100644 index 0000000000..a3b1005567 --- /dev/null +++ b/plugins/main/public/components/overview/pci/dashboards/styles.scss @@ -0,0 +1,10 @@ +.pci-dss-dashboard-responsive { + @media (max-width: 767px) { + .react-grid-layout { + height: auto !important; + } + .dshLayout-isMaximizedPanel { + height: 100% !important; + } + } +} diff --git a/plugins/main/public/components/visualize/components/sample-data-warning.js b/plugins/main/public/components/visualize/components/sample-data-warning.js index 7b5b115cbb..28e939b1fe 100644 --- a/plugins/main/public/components/visualize/components/sample-data-warning.js +++ b/plugins/main/public/components/visualize/components/sample-data-warning.js @@ -22,35 +22,31 @@ import { RedirectAppLinks } from '../../../../../../src/plugins/opensearch_dashb export const SampleDataWarning = ({ ...props }) => { const [isSampleData, setIsSampleData] = useState(false); + const request = async () => { + try { + const result = ( + await WzRequest.genericReq('GET', '/elastic/samplealerts') + ).data.sampleAlertsInstalled; + setIsSampleData(result); + } catch (error) { + const options = { + context: `${SampleDataWarning.name}.usesSampleData`, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.UI, + error: { + error: error, + message: error.message || error, + title: error.name || error, + }, + }; + getErrorOrchestrator().handleError(options); + } + }; + useEffect(() => { - (async () => { - try { - const result = ( - await WzRequest.genericReq('GET', '/elastic/samplealerts') - ).data.sampleAlertsInstalled; - setIsSampleData(result); - } catch (error) { - const options = { - context: `${SampleDataWarning.name}.usesSampleData`, - level: UI_LOGGER_LEVELS.ERROR, - severity: UI_ERROR_SEVERITIES.UI, - error: { - error: error, - message: error.message || error, - title: error.name || error, - }, - }; - getErrorOrchestrator().handleError(options); - } - })(); - }, [ - SampleDataWarning, - setIsSampleData, - UI_ERROR_SEVERITIES, - UI_LOGGER_LEVELS, - getErrorOrchestrator, - WzRequest, - ]); + request(); + }, []); + if (isSampleData) { return ( { href={getCore().application.getUrlForApp(sampleData.id)} aria-label='go to configure sample data' > - {'here '} + {'here'} - {'to configure the sample data.'} + {' to configure the sample data.'}

diff --git a/plugins/main/server/integration-files/visualizations/agents/agents-pci.ts b/plugins/main/server/integration-files/visualizations/agents/agents-pci.ts deleted file mode 100644 index e4be9be4fc..0000000000 --- a/plugins/main/server/integration-files/visualizations/agents/agents-pci.ts +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Wazuh app - Module for Agents/PCI visualizations - * 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. - */ -export default [ - { - _id: 'Wazuh-App-Agents-PCI-Groups', - _source: { - title: 'Top 5 rule groups', - visState: JSON.stringify({ - title: 'Top 5 rule groups', - type: 'pie', - params: { - type: 'pie', - addTooltip: true, - addLegend: true, - legendPosition: 'right', - isDonut: true, - }, - aggs: [ - { id: '1', enabled: true, type: 'count', schema: 'metric', params: {} }, - { - id: '2', - enabled: true, - type: 'terms', - schema: 'segment', - params: { field: 'rule.groups', size: 5, order: 'desc', orderBy: '1' }, - }, - ], - }), - uiStateJSON: '{}', - description: '', - version: 1, - kibanaSavedObjectMeta: { - searchSourceJSON: JSON.stringify({ - index: 'wazuh-alerts', - filter: [], - query: { query: '', language: 'lucene' }, - }), - }, - }, - _type: 'visualization', - }, - { - _id: 'Wazuh-App-Agents-PCI-Rule', - _source: { - title: 'Top 5 rules', - visState: JSON.stringify({ - title: 'Top 5 rules', - type: 'pie', - params: { - type: 'pie', - addTooltip: true, - addLegend: true, - legendPosition: 'right', - isDonut: true, - }, - aggs: [ - { id: '1', enabled: true, type: 'count', schema: 'metric', params: {} }, - { - id: '2', - enabled: true, - type: 'terms', - schema: 'segment', - params: { field: 'rule.description', size: 5, order: 'desc', orderBy: '1' }, - }, - ], - }), - uiStateJSON: '{}', - description: '', - version: 1, - kibanaSavedObjectMeta: { - searchSourceJSON: JSON.stringify({ - index: 'wazuh-alerts', - filter: [], - query: { query: '', language: 'lucene' }, - }), - }, - }, - _type: 'visualization', - }, - { - _id: 'Wazuh-App-Agents-PCI-Requirement', - _source: { - title: 'Top 5 requirements', - visState: JSON.stringify({ - title: 'Top 5 requirements', - type: 'pie', - params: { - type: 'pie', - addTooltip: true, - addLegend: true, - legendPosition: 'right', - isDonut: true, - }, - aggs: [ - { id: '1', enabled: true, type: 'count', schema: 'metric', params: {} }, - { - id: '2', - enabled: true, - type: 'terms', - schema: 'segment', - params: { field: 'rule.pci_dss', size: 5, order: 'desc', orderBy: '1' }, - }, - ], - }), - uiStateJSON: '{}', - description: '', - version: 1, - kibanaSavedObjectMeta: { - searchSourceJSON: JSON.stringify({ - index: 'wazuh-alerts', - filter: [], - query: { query: '', language: 'lucene' }, - }), - }, - }, - _type: 'visualization', - }, - { - _id: 'Wazuh-App-Agents-PCI-Rule-level-distribution', - _source: { - title: 'Rule level distribution', - visState: JSON.stringify({ - title: 'Rule level distribution', - type: 'pie', - params: { - type: 'pie', - addTooltip: true, - addLegend: false, - legendPosition: 'right', - isDonut: true, - labels: { show: true, values: true, last_level: true, truncate: 100 }, - }, - aggs: [ - { id: '1', enabled: true, type: 'count', schema: 'metric', params: {} }, - { - id: '2', - enabled: true, - type: 'terms', - schema: 'segment', - params: { - field: 'rule.level', - size: 15, - order: 'desc', - orderBy: '1', - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - }, - }, - ], - }), - uiStateJSON: JSON.stringify({ vis: { legendOpen: false } }), - description: '', - version: 1, - kibanaSavedObjectMeta: { - searchSourceJSON: JSON.stringify({ - index: 'wazuh-alerts', - filter: [], - query: { query: '', language: 'lucene' }, - }), - }, - }, - _type: 'visualization', - }, - { - _id: 'Wazuh-App-Agents-PCI-Requirements', - _source: { - title: 'Requirements', - visState: JSON.stringify({ - title: 'Requirements', - type: 'histogram', - params: { - type: 'histogram', - grid: { categoryLines: false, style: { color: '#eee' } }, - categoryAxes: [ - { - id: 'CategoryAxis-1', - type: 'category', - position: 'bottom', - show: true, - style: {}, - scale: { type: 'linear' }, - labels: { show: true, filter: true, truncate: 100, rotate: 0 }, - title: {}, - }, - ], - valueAxes: [ - { - id: 'ValueAxis-1', - name: 'LeftAxis-1', - type: 'value', - position: 'left', - show: true, - style: {}, - scale: { type: 'linear', mode: 'normal' }, - labels: { show: true, rotate: 0, filter: false, truncate: 100 }, - title: { text: 'Count' }, - }, - ], - seriesParams: [ - { - show: 'true', - type: 'histogram', - mode: 'stacked', - data: { label: 'Count', id: '1' }, - valueAxis: 'ValueAxis-1', - drawLinesBetweenPoints: true, - showCircles: true, - }, - ], - addTooltip: true, - addLegend: true, - legendPosition: 'right', - times: [], - addTimeMarker: false, - }, - aggs: [ - { id: '1', enabled: true, type: 'count', schema: 'metric', params: {} }, - { - id: '3', - enabled: true, - type: 'terms', - schema: 'group', - params: { - field: 'rule.pci_dss', - size: 5, - order: 'desc', - orderBy: '1', - customLabel: '', - }, - }, - { - id: '2', - enabled: true, - type: 'terms', - schema: 'segment', - params: { - field: 'rule.pci_dss', - size: 10, - order: 'desc', - orderBy: '1', - customLabel: 'PCI DSS Requirements', - }, - }, - ], - }), - uiStateJSON: '{}', - description: '', - version: 1, - kibanaSavedObjectMeta: { - searchSourceJSON: JSON.stringify({ - index: 'wazuh-alerts', - filter: [], - query: { query: '', language: 'lucene' }, - }), - }, - }, - _type: 'visualization', - }, - { - _id: 'Wazuh-App-Agents-PCI-Last-alerts', - _type: 'visualization', - _source: { - title: 'Last alerts', - visState: JSON.stringify({ - title: 'Last alerts', - type: 'table', - params: { - perPage: 10, - showPartialRows: false, - showMeticsAtAllLevels: false, - sort: { columnIndex: 2, direction: 'desc' }, - showTotal: false, - showToolbar: true, - totalFunc: 'sum', - }, - aggs: [ - { id: '1', enabled: true, type: 'count', schema: 'metric', params: {} }, - { - id: '3', - enabled: true, - type: 'terms', - schema: 'bucket', - params: { - field: 'rule.pci_dss', - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - size: 50, - order: 'desc', - orderBy: '1', - customLabel: 'Requirement', - }, - }, - { - id: '4', - enabled: true, - type: 'terms', - schema: 'bucket', - params: { - field: 'rule.description', - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - size: 10, - order: 'desc', - orderBy: '1', - customLabel: 'Rule description', - }, - }, - ], - }), - uiStateJSON: JSON.stringify({ - vis: { params: { sort: { columnIndex: 2, direction: 'desc' } } }, - }), - description: '', - version: 1, - kibanaSavedObjectMeta: { - searchSourceJSON: JSON.stringify({ - index: 'wazuh-alerts', - filter: [], - query: { query: '', language: 'lucene' }, - }), - }, - }, - }, -]; diff --git a/plugins/main/server/integration-files/visualizations/agents/index.ts b/plugins/main/server/integration-files/visualizations/agents/index.ts index a61f4da239..3325360a69 100644 --- a/plugins/main/server/integration-files/visualizations/agents/index.ts +++ b/plugins/main/server/integration-files/visualizations/agents/index.ts @@ -15,7 +15,6 @@ import general from './agents-general'; import gcp from './agents-gcp'; import oscap from './agents-oscap'; import ciscat from './agents-ciscat'; -import pci from './agents-pci'; import gdpr from './agents-gdpr'; import hipaa from './agents-hipaa'; import mitre from './agents-mitre'; @@ -36,7 +35,6 @@ export { gcp, oscap, ciscat, - pci, gdpr, hipaa, nist, diff --git a/plugins/main/server/integration-files/visualizations/overview/index.ts b/plugins/main/server/integration-files/visualizations/overview/index.ts index 8f8711b75f..078f03e29f 100644 --- a/plugins/main/server/integration-files/visualizations/overview/index.ts +++ b/plugins/main/server/integration-files/visualizations/overview/index.ts @@ -16,7 +16,6 @@ import fim from './overview-fim'; import general from './overview-general'; import oscap from './overview-oscap'; import ciscat from './overview-ciscat'; -import pci from './overview-pci'; import gdpr from './overview-gdpr'; import hipaa from './overview-hipaa'; import nist from './overview-nist'; @@ -37,7 +36,6 @@ export { general, oscap, ciscat, - pci, gdpr, hipaa, nist, @@ -48,5 +46,5 @@ export { office, osquery, docker, - github + github, }; diff --git a/plugins/main/server/integration-files/visualizations/overview/overview-pci.ts b/plugins/main/server/integration-files/visualizations/overview/overview-pci.ts deleted file mode 100644 index 620d2c81bf..0000000000 --- a/plugins/main/server/integration-files/visualizations/overview/overview-pci.ts +++ /dev/null @@ -1,761 +0,0 @@ -/* - * Wazuh app - Module for Overview/PCI visualizations - * 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. - */ -export default [ - { - _id: 'Wazuh-App-Overview-PCI-DSS-Requirements-over-time', - _source: { - title: 'Requirements over time', - visState: JSON.stringify({ - title: 'Alerts by action over time', - type: 'area', - params: { - type: 'area', - grid: { - categoryLines: true, - style: { color: '#eee' }, - valueAxis: 'ValueAxis-1', - }, - categoryAxes: [ - { - id: 'CategoryAxis-1', - type: 'category', - position: 'bottom', - show: true, - style: {}, - scale: { type: 'linear' }, - labels: { show: true, filter: true, truncate: 100 }, - title: {}, - }, - ], - valueAxes: [ - { - id: 'ValueAxis-1', - name: 'LeftAxis-1', - type: 'value', - position: 'left', - show: true, - style: {}, - scale: { type: 'linear', mode: 'normal' }, - labels: { show: true, rotate: 0, filter: false, truncate: 100 }, - title: { text: 'Count' }, - }, - ], - seriesParams: [ - { - show: 'true', - type: 'area', - mode: 'stacked', - data: { label: 'Count', id: '1' }, - drawLinesBetweenPoints: true, - showCircles: true, - interpolate: 'cardinal', - valueAxis: 'ValueAxis-1', - }, - ], - addTooltip: true, - addLegend: true, - legendPosition: 'right', - times: [], - addTimeMarker: false, - }, - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: {}, - }, - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: {}, - }, - { - id: '3', - enabled: true, - type: 'terms', - schema: 'group', - params: { - field: 'rule.pci_dss', - size: '5', - order: 'desc', - orderBy: '1', - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - }, - }, - { - id: '2', - enabled: true, - type: 'date_histogram', - schema: 'segment', - params: { - field: 'timestamp', - timeRange: { from: 'now-24h', to: 'now', mode: 'quick' }, - useNormalizedEsInterval: true, - interval: 'auto', - time_zone: 'Europe/Berlin', - drop_partials: false, - customInterval: '2h', - min_doc_count: 1, - extended_bounds: {}, - }, - }, - ], - }), - uiStateJSON: '{}', - description: '', - version: 1, - kibanaSavedObjectMeta: { - searchSourceJSON: JSON.stringify({ - index: 'wazuh-alerts', - filter: [], - query: { language: 'lucene', query: '' }, - }), - }, - }, - _type: 'visualization', - }, - { - _id: 'Wazuh-App-Overview-PCI-DSS-Requirements-Agents-heatmap', - _type: 'visualization', - _source: { - title: 'PCI requirements heatmap', - visState: JSON.stringify({ - title: 'PCI requirements heatmap', - type: 'heatmap', - params: { - type: 'heatmap', - addTooltip: true, - addLegend: true, - enableHover: false, - legendPosition: 'right', - times: [], - colorsNumber: 10, - colorSchema: 'Greens', - setColorRange: false, - colorsRange: [], - invertColors: false, - percentageMode: false, - valueAxes: [ - { - show: false, - id: 'ValueAxis-1', - type: 'value', - scale: { type: 'linear', defaultYExtents: false }, - labels: { - show: false, - rotate: 0, - overwriteColor: false, - color: '#555', - }, - }, - ], - }, - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: {}, - }, - { - id: '2', - enabled: true, - type: 'terms', - schema: 'segment', - params: { - field: 'rule.pci_dss', - size: 5, - order: 'desc', - orderBy: '1', - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'Requirements', - }, - }, - { - id: '3', - enabled: true, - type: 'terms', - schema: 'group', - params: { - field: 'agent.name', - size: 5, - order: 'desc', - orderBy: '1', - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'Agents', - }, - }, - ], - }), - uiStateJSON: JSON.stringify({ - vis: { - defaultColors: { - '0 - 13': 'rgb(247,252,245)', - '13 - 26': 'rgb(233,247,228)', - '26 - 39': 'rgb(211,238,205)', - '39 - 52': 'rgb(184,227,177)', - '52 - 65': 'rgb(152,213,148)', - '65 - 78': 'rgb(116,196,118)', - '78 - 91': 'rgb(75,176,98)', - '91 - 104': 'rgb(47,152,79)', - '104 - 117': 'rgb(21,127,59)', - '117 - 130': 'rgb(0,100,40)', - }, - }, - }), - description: '', - version: 1, - kibanaSavedObjectMeta: { - searchSourceJSON: JSON.stringify({ - index: 'wazuh-alerts', - query: { query: '', language: 'lucene' }, - filter: [], - }), - }, - }, - }, - { - _id: 'Wazuh-App-Overview-PCI-DSS-requirements', - _source: { - title: 'PCI DSS requirements', - visState: JSON.stringify({ - title: 'PCI DSS requirements', - type: 'line', - params: { - type: 'line', - grid: { categoryLines: true, valueAxis: 'ValueAxis-1' }, - categoryAxes: [ - { - id: 'CategoryAxis-1', - type: 'category', - position: 'bottom', - show: true, - style: {}, - scale: { type: 'linear' }, - labels: { show: true, filter: true, truncate: 100 }, - title: {}, - }, - ], - valueAxes: [ - { - id: 'ValueAxis-1', - name: 'LeftAxis-1', - type: 'value', - position: 'left', - show: true, - style: {}, - scale: { type: 'linear', mode: 'normal' }, - labels: { show: true, rotate: 0, filter: false, truncate: 100 }, - title: { text: 'Count' }, - }, - ], - seriesParams: [ - { - show: 'true', - type: 'line', - mode: 'normal', - data: { label: 'Count', id: '1' }, - valueAxis: 'ValueAxis-1', - drawLinesBetweenPoints: false, - showCircles: true, - }, - ], - addTooltip: true, - addLegend: true, - legendPosition: 'right', - times: [], - addTimeMarker: false, - dimensions: { - x: { - accessor: 0, - format: { id: 'date', params: { pattern: 'YYYY-MM-DD' } }, - params: { date: true, interval: 'P1D', format: 'YYYY-MM-DD' }, - aggType: 'date_histogram', - }, - y: [ - { - accessor: 2, - format: { id: 'number' }, - params: {}, - aggType: 'count', - }, - ], - z: [ - { - accessor: 3, - format: { id: 'number' }, - params: {}, - aggType: 'count', - }, - ], - series: [ - { - accessor: 1, - format: { - id: 'terms', - params: { - id: 'string', - otherBucketLabel: 'Other', - missingBucketLabel: 'Missing', - }, - }, - params: {}, - aggType: 'terms', - }, - ], - }, - radiusRatio: 50, - }, - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: {}, - }, - { - id: '2', - enabled: true, - type: 'date_histogram', - schema: 'segment', - params: { - field: 'timestamp', - timeRange: { from: 'now-1h', to: 'now' }, - useNormalizedEsInterval: true, - interval: 'auto', - drop_partials: false, - min_doc_count: 1, - extended_bounds: {}, - }, - }, - { - id: '4', - enabled: true, - type: 'count', - schema: 'radius', - params: {}, - }, - { - id: '4', - enabled: true, - type: 'count', - schema: 'radius', - params: {}, - }, - ], - }), - uiStateJSON: '{}', - description: '', - version: 1, - kibanaSavedObjectMeta: { - searchSourceJSON: JSON.stringify({ - index: 'wazuh-alerts', - filter: [], - query: { query: '', language: 'lucene' }, - }), - }, - }, - _type: 'visualization', - }, - { - _id: 'Wazuh-App-Overview-PCI-DSS-Agents', - _source: { - title: 'Agents', - visState: JSON.stringify({ - title: 'Agents', - type: 'pie', - params: { - type: 'pie', - addTooltip: true, - addLegend: true, - legendPosition: 'right', - isDonut: false, - }, - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: {}, - }, - { - id: '2', - enabled: true, - type: 'terms', - schema: 'segment', - params: { - field: 'agent.name', - size: 10, - order: 'desc', - orderBy: '1', - }, - }, - ], - }), - uiStateJSON: '{}', - description: '', - version: 1, - kibanaSavedObjectMeta: { - searchSourceJSON: JSON.stringify({ - index: 'wazuh-alerts', - filter: [], - query: { query: '', language: 'lucene' }, - }), - }, - }, - _type: 'visualization', - }, - { - _id: 'Wazuh-App-Overview-PCI-DSS-Requirements-by-agent', - _source: { - title: 'Requirements by agent', - visState: JSON.stringify({ - title: 'Requirements by agent', - type: 'histogram', - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - params: {}, - schema: 'metric', - }, - { - id: '3', - enabled: true, - type: 'terms', - params: { - field: 'agent.name', - orderBy: '1', - order: 'desc', - size: 5, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - }, - schema: 'group', - }, - { - id: '2', - enabled: true, - type: 'terms', - params: { - field: 'rule.pci_dss', - orderBy: '1', - order: 'desc', - size: 5, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'Requirements', - }, - schema: 'segment', - }, - ], - params: { - type: 'histogram', - grid: { - categoryLines: false, - style: { - color: '#eee', - }, - }, - categoryAxes: [ - { - id: 'CategoryAxis-1', - type: 'category', - position: 'bottom', - show: true, - style: {}, - scale: { - type: 'linear', - }, - labels: { - show: true, - filter: true, - truncate: 100, - rotate: 0, - }, - title: {}, - }, - ], - valueAxes: [ - { - id: 'ValueAxis-1', - name: 'LeftAxis-1', - type: 'value', - position: 'left', - show: true, - style: {}, - scale: { - type: 'linear', - mode: 'normal', - }, - labels: { - show: true, - rotate: 0, - filter: false, - truncate: 100, - }, - title: { - text: 'Count', - }, - }, - ], - seriesParams: [ - { - show: 'true', - type: 'histogram', - mode: 'stacked', - data: { - label: 'Count', - id: '1', - }, - valueAxis: 'ValueAxis-1', - drawLinesBetweenPoints: true, - showCircles: true, - }, - ], - addTooltip: true, - addLegend: true, - legendPosition: 'right', - times: [], - addTimeMarker: false, - radiusRatio: 51, - labels: { - show: false, - }, - thresholdLine: { - show: false, - value: 10, - width: 1, - style: 'full', - color: '#E7664C', - }, - }, - }), - uiStateJSON: '{}', - description: '', - version: 1, - kibanaSavedObjectMeta: { - searchSourceJSON: JSON.stringify({ - index: 'wazuh-alerts', - filter: [], - query: { query: '', language: 'lucene' }, - }), - }, - }, - _type: 'visualization', - }, - { - _id: 'Wazuh-App-Overview-PCI-DSS-Last-alerts', - _type: 'visualization', - _source: { - title: 'Last alerts', - visState: JSON.stringify({ - title: 'Last alerts', - type: 'table', - params: { - perPage: 10, - showPartialRows: false, - showMeticsAtAllLevels: false, - sort: { columnIndex: null, direction: null }, - showTotal: false, - showToolbar: true, - totalFunc: 'sum', - }, - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: {}, - }, - { - id: '2', - enabled: true, - type: 'terms', - schema: 'bucket', - params: { - field: 'agent.name', - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - size: 50, - order: 'desc', - orderBy: '1', - customLabel: 'Agent name', - }, - }, - { - id: '3', - enabled: true, - type: 'terms', - schema: 'bucket', - params: { - field: 'rule.pci_dss', - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - size: 10, - order: 'desc', - orderBy: '1', - customLabel: 'Requirement', - }, - }, - { - id: '4', - enabled: true, - type: 'terms', - schema: 'bucket', - params: { - field: 'rule.description', - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - size: 10, - order: 'desc', - orderBy: '1', - customLabel: 'Rule description', - }, - }, - ], - }), - uiStateJSON: JSON.stringify({ - vis: { params: { sort: { columnIndex: 3, direction: 'desc' } } }, - }), - description: '', - version: 1, - kibanaSavedObjectMeta: { - searchSourceJSON: JSON.stringify({ - index: 'wazuh-alerts', - filter: [], - query: { query: '', language: 'lucene' }, - }), - }, - }, - }, - { - _id: 'Wazuh-App-Overview-PCI-DSS-Alerts-summary', - _type: 'visualization', - _source: { - title: 'Alerts summary', - visState: JSON.stringify({ - title: 'Alerts summary', - type: 'table', - params: { - perPage: 10, - showPartialRows: false, - showMeticsAtAllLevels: false, - sort: { columnIndex: 3, direction: 'desc' }, - showTotal: false, - showToolbar: true, - totalFunc: 'sum', - }, - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: {}, - }, - { - id: '2', - enabled: true, - type: 'terms', - schema: 'bucket', - params: { - field: 'agent.name', - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - size: 50, - order: 'desc', - orderBy: '1', - customLabel: 'Agent name', - }, - }, - { - id: '3', - enabled: true, - type: 'terms', - schema: 'bucket', - params: { - field: 'rule.pci_dss', - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - size: 10, - order: 'desc', - orderBy: '1', - customLabel: 'Requirement', - }, - }, - { - id: '4', - enabled: true, - type: 'terms', - schema: 'bucket', - params: { - field: 'rule.description', - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - size: 10, - order: 'desc', - orderBy: '1', - customLabel: 'Rule description', - }, - }, - ], - }), - uiStateJSON: JSON.stringify({ - vis: { params: { sort: { columnIndex: 3, direction: 'desc' } } }, - }), - description: '', - version: 1, - kibanaSavedObjectMeta: { - searchSourceJSON: JSON.stringify({ - index: 'wazuh-alerts', - filter: [], - query: { query: '', language: 'lucene' }, - }), - }, - }, - }, -];