From 0f8dff9ee6db9455c6fefc07fd0a3edf34255b3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Thu, 14 Mar 2024 09:33:56 +0100 Subject: [PATCH 01/14] feat(NIST800-53): replace the dashboard on NIST 800-53 application --- .../common/modules/modules-defaults.js | 17 +- .../common/components/loading_spinner.scss | 4 + .../common/components/loading_spinner.tsx | 21 + .../nist/common/components/no_results.tsx | 60 + .../overview/nist/dashboards/dashboard.tsx | 138 ++ .../nist/dashboards/dashboard_panels.ts | 1468 +++++++++++++++++ .../overview/nist/dashboards/index.tsx | 1 + .../overview/nist/dashboards/styles.scss | 10 + 8 files changed, 1718 insertions(+), 1 deletion(-) create mode 100644 plugins/main/public/components/overview/nist/common/components/loading_spinner.scss create mode 100644 plugins/main/public/components/overview/nist/common/components/loading_spinner.tsx create mode 100644 plugins/main/public/components/overview/nist/common/components/no_results.tsx create mode 100644 plugins/main/public/components/overview/nist/dashboards/dashboard.tsx create mode 100644 plugins/main/public/components/overview/nist/dashboards/dashboard_panels.ts create mode 100644 plugins/main/public/components/overview/nist/dashboards/index.tsx create mode 100644 plugins/main/public/components/overview/nist/dashboards/styles.scss diff --git a/plugins/main/public/components/common/modules/modules-defaults.js b/plugins/main/public/components/common/modules/modules-defaults.js index 7b1705b0e4..f3ebe71767 100644 --- a/plugins/main/public/components/common/modules/modules-defaults.js +++ b/plugins/main/public/components/common/modules/modules-defaults.js @@ -43,6 +43,7 @@ import { virustotalColumns } from '../../overview/virustotal/events/virustotal-c import { malwareDetectionColumns } from '../../overview/malware-detection/events/malware-detection-columns'; import { WAZUH_VULNERABILITIES_PATTERN } from '../../../../common/constants'; import { withVulnerabilitiesStateDataSource } from '../../overview/vulnerabilities/common/hocs/validate-vulnerabilities-states-index-pattern'; +import { DashboardNIST80053 } from '../../overview/nist/dashboards/dashboard'; const DashboardTab = { id: 'dashboard', @@ -280,7 +281,21 @@ export const ModulesDefaults = { }, nist: { init: 'dashboard', - tabs: RegulatoryComplianceTabs(nistColumns), + tabs: [ + { + id: 'dashboard2', + name: 'Dashboard', + buttons: [ButtonModuleExploreAgent, ButtonModuleGenerateReport], + component: DashboardNIST80053 || withPinnedAgent(DashboardNIST80053), // TODO: use withPinnedAgent + }, + { + id: 'inventory', + name: 'Controls', + buttons: [ButtonModuleExploreAgent], + component: ComplianceTable, + }, + renderDiscoverTab(DEFAULT_INDEX_PATTERN, nistColumns), + ], availableFor: ['manager', 'agent'], }, gdpr: { diff --git a/plugins/main/public/components/overview/nist/common/components/loading_spinner.scss b/plugins/main/public/components/overview/nist/common/components/loading_spinner.scss new file mode 100644 index 0000000000..051ab642c1 --- /dev/null +++ b/plugins/main/public/components/overview/nist/common/components/loading_spinner.scss @@ -0,0 +1,4 @@ +.discoverNoResults { + display: flex; + align-items: center; +} diff --git a/plugins/main/public/components/overview/nist/common/components/loading_spinner.tsx b/plugins/main/public/components/overview/nist/common/components/loading_spinner.tsx new file mode 100644 index 0000000000..7f505e6167 --- /dev/null +++ b/plugins/main/public/components/overview/nist/common/components/loading_spinner.tsx @@ -0,0 +1,21 @@ +import './loading_spinner.scss'; +import React from 'react'; +import { EuiTitle, EuiPanel, EuiEmptyPrompt, EuiLoadingSpinner } from '@elastic/eui'; +import { FormattedMessage } from '@osd/i18n/react'; + +export function LoadingSpinner() { + return ( + + } + title={ + +

+ +

+
+ } + /> +
+ ); +} diff --git a/plugins/main/public/components/overview/nist/common/components/no_results.tsx b/plugins/main/public/components/overview/nist/common/components/no_results.tsx new file mode 100644 index 0000000000..babfd51d32 --- /dev/null +++ b/plugins/main/public/components/overview/nist/common/components/no_results.tsx @@ -0,0 +1,60 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + * + * Any modifications Copyright OpenSearch Contributors. See + * GitHub history for details. + */ + +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React from 'react'; +import { FormattedMessage, I18nProvider } from '@osd/i18n/react'; + +import { EuiCallOut, EuiPanel } from '@elastic/eui'; + +interface Props { + message?: string; +} + +export const DiscoverNoResults = ({ message }: Props) => { + return ( + + + + ) + } + color='warning' + iconType='help' + data-test-subj='discoverNoResults' + /> + + + ); +}; diff --git a/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx b/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx new file mode 100644 index 0000000000..80202f107b --- /dev/null +++ b/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx @@ -0,0 +1,138 @@ +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 { DiscoverNoResults } from '../common/components/no_results'; +import { LoadingSpinner } from '../common/components/loading_spinner'; +import { search } from '../../../common/search-bar/search-bar-service'; +import { IndexPattern } from '../../../../../../../src/plugins/data/common'; +import { + ErrorFactory, + ErrorHandler, + HttpError, +} from '../../../../react-services/error-management'; +import { compose } from 'redux'; +import { DashboardContainerInput } from '../../../../../../../src/plugins/dashboard/public'; +import { SampleDataWarning } from '../../../visualize/components'; + +const plugins = getPlugins(); + +const SearchBar = getPlugins().data.ui.SearchBar; + +const DashboardByRenderer = plugins.dashboard.DashboardContainerByValueRenderer; + +/* The vulnerabilities dashboard is made up of 3 dashboards because the filters need +a wrapper for visual adjustments, while the Kpi, the Open vs Close visualization and +the rest of the visualizations have different configurations at the dashboard level. */ + +const DashboardNIST80053Component: React.FC = ({ pinnedAgent }) => { + const ALERTS_INDEX_PATTERN_ID = 'wazuh-alerts-*'; // TODO: use the data source + const { searchBarProps } = useSearchBar({ + defaultIndexPatternID: ALERTS_INDEX_PATTERN_ID, + onMount: () => {}, // TODO: use data source + onUpdate: () => {}, // TODO: use data source + onUnMount: () => {}, // TODO: use data source + }); + + /* This function is responsible for updating the storage filters so that the + filters between dashboard and inventory added using visualizations call to actions. + Without this feature, filters added using visualizations call to actions are + not maintained between dashboard and inventory tabs */ + const handleFilterByVisualization = (newInput: DashboardContainerInput) => { + return; // TODO: adapt to the data source + updateFiltersStorage(newInput.filters); + }; + + // TODO: add the hidden filters: allowed agents and hideManagerAlerts + const fetchFilters = searchBarProps.filters; + + const { isLoading, query, indexPatterns } = searchBarProps; + + const [isSearching, setIsSearching] = useState(false); + const [results, setResults] = useState({} as SearchResponse); + + useEffect(() => { + if (!isLoading) { + search({ + indexPattern: indexPatterns?.[0] as IndexPattern, + filters: fetchFilters, + query, + }) + .then(results => { + setResults(results); + setIsSearching(false); + }) + .catch(error => { + const searchError = ErrorFactory.create(HttpError, { + error, + message: 'Error fetching vulnerabilities', + }); + ErrorHandler.handleError(searchError); + setIsSearching(false); + }); + } + }, [JSON.stringify(searchBarProps), JSON.stringify(fetchFilters)]); + + return ( + <> + + <> + {isLoading ? : null} + {!isLoading ? ( + + ) : null} + + {isSearching ? : null} + {!isLoading && !isSearching && results?.hits?.total === 0 ? ( + + ) : null} + {!isLoading && !isSearching && results?.hits?.total > 0 ? ( +
+ +
+ ) : null} + +
+ + ); +}; + +export const DashboardNIST80053 = compose(withErrorBoundary)( + DashboardNIST80053Component, +); diff --git a/plugins/main/public/components/overview/nist/dashboards/dashboard_panels.ts b/plugins/main/public/components/overview/nist/dashboards/dashboard_panels.ts new file mode 100644 index 0000000000..fa5e63f20e --- /dev/null +++ b/plugins/main/public/components/overview/nist/dashboards/dashboard_panels.ts @@ -0,0 +1,1468 @@ +import { DashboardPanelState } from '../../../../../../../src/plugins/dashboard/public/application'; +import { EmbeddableInput } from '../../../../../../../src/plugins/embeddable/public'; + +// Visualization ID: Wazuh-App-Overview-NIST-Agents +const getVisStateMostActiveAgents = (indexPatternId: string) => { + return { + title: 'Most active agents', + type: 'pie', + params: { + type: 'pie', + addTooltip: true, + addLegend: true, + legendPosition: 'right', + isDonut: true, + labels: { + show: false, + values: true, + last_level: true, + truncate: 100, + }, + dimensions: { + metric: { + accessor: 1, + format: { id: 'number' }, + params: {}, + aggType: 'count', + }, + buckets: [ + { + accessor: 0, + format: { + id: 'terms', + params: { + id: 'string', + otherBucketLabel: 'Other', + missingBucketLabel: 'Missing', + }, + }, + params: {}, + aggType: 'terms', + }, + ], + }, + }, + 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', + orderBy: '1', + order: 'desc', + size: 10, + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + customLabel: 'Agent', + }, + }, + ], + }, + }; +}; + +// Visualization ID: Wazuh-App-Overview-NIST-Requirements-over-time +const getVisStateRequirementsOverTime = (indexPatternId: string) => { + return { + title: 'Top 10 requirements over time', + type: 'histogram', + params: { + type: 'histogram', + 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: true, + showCircles: true, + interpolate: 'linear', + }, + ], + addTooltip: true, + addLegend: true, + legendPosition: 'right', + times: [], + addTimeMarker: false, + labels: { show: false }, + dimensions: { + x: { + accessor: 0, + format: { id: 'date', params: { pattern: 'YYYY-MM-DD HH:mm' } }, + params: { + date: true, + interval: 'PT1H', + format: 'YYYY-MM-DD HH:mm', + bounds: { + min: '2019-08-20T12:33:23.360Z', + max: '2019-08-22T12:33:23.360Z', + }, + }, + aggType: 'date_histogram', + }, + y: [ + { + accessor: 2, + format: { id: 'number' }, + params: {}, + aggType: 'count', + }, + ], + series: [ + { + accessor: 1, + format: { + id: 'terms', + params: { + id: 'string', + otherBucketLabel: 'Other', + missingBucketLabel: 'Missing', + }, + }, + params: {}, + aggType: 'terms', + }, + ], + }, + }, + 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: '4', + enabled: true, + type: 'terms', + schema: 'group', + params: { + field: 'rule.nist_800_53', + orderBy: '1', + order: 'desc', + size: 8, + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + customLabel: 'Requirement', + }, + }, + { + id: '2', + enabled: true, + type: 'date_histogram', + schema: 'segment', + params: { + field: 'timestamp', + timeRange: { from: 'now-2d', to: 'now' }, + useNormalizedEsInterval: true, + interval: 'auto', + drop_partials: false, + min_doc_count: 1, + extended_bounds: {}, + }, + }, + ], + }, + }; +}; + +// Visualization ID: Wazuh-App-Overview-NIST-requirements-by-agents +const getVisStateRequirementsByAgents = (indexPatternId: string) => { + return { + title: 'Requirements distribution by agent', + type: 'area', + params: { + type: 'area', + grid: { categoryLines: false }, + categoryAxes: [ + { + id: 'CategoryAxis-1', + type: 'category', + position: 'bottom', + show: true, + style: {}, + scale: { type: 'linear' }, + labels: { show: true, filter: true, truncate: 100 }, + title: {}, + }, + ], + valueAxes: [ + { + id: 'ValueAxis-1', + name: 'LeftAxis-1', + type: 'value', + position: 'left', + show: true, + style: {}, + scale: { type: 'linear', mode: 'normal' }, + labels: { show: true, rotate: 0, filter: false, truncate: 100 }, + title: { text: 'Count' }, + }, + ], + seriesParams: [ + { + show: 'true', + type: 'histogram', + mode: 'stacked', + data: { label: 'Count', id: '1' }, + drawLinesBetweenPoints: true, + showCircles: true, + interpolate: 'linear', + valueAxis: 'ValueAxis-1', + }, + ], + addTooltip: true, + addLegend: true, + legendPosition: 'right', + times: [], + addTimeMarker: false, + dimensions: { + x: { + accessor: 0, + format: { + id: 'terms', + params: { + id: 'string', + otherBucketLabel: 'Other', + missingBucketLabel: 'Missing', + }, + }, + params: {}, + aggType: 'terms', + }, + y: [ + { + accessor: 2, + format: { id: 'number' }, + params: {}, + aggType: 'count', + }, + ], + series: [ + { + accessor: 1, + format: { + id: 'terms', + params: { + id: 'string', + otherBucketLabel: 'Other', + missingBucketLabel: 'Missing', + }, + }, + params: {}, + aggType: 'terms', + }, + ], + }, + }, + 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: 'agent.id', + orderBy: '1', + order: 'desc', + size: 5, + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + customLabel: 'Agent', + }, + }, + { + id: '3', + enabled: true, + type: 'terms', + schema: 'group', + params: { + field: 'rule.nist_800_53', + orderBy: '1', + order: 'desc', + size: 9, + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + customLabel: 'Requirement', + }, + }, + ], + }, + }; +}; + +// Visualization ID: Wazuh-App-Overview-NIST-Requirements-Agents-heatmap +const getVisStateRequirementsAgentsHeatmap = (indexPatternId: string) => { + return { + title: 'Alerts volume by agent', + type: 'heatmap', + params: { + addLegend: true, + addTooltip: true, + colorSchema: 'Blues', + colorsNumber: 10, + colorsRange: [], + dimensions: { + series: [ + { + accessor: 0, + aggType: 'terms', + format: { + id: 'terms', + params: { + id: 'string', + missingBucketLabel: 'Missing', + otherBucketLabel: 'Other', + }, + }, + params: {}, + }, + ], + x: { + accessor: 1, + aggType: 'terms', + format: { + id: 'terms', + params: { + id: 'string', + missingBucketLabel: 'Missing', + otherBucketLabel: 'Other', + }, + }, + params: {}, + }, + y: [ + { + accessor: 2, + aggType: 'count', + format: { id: 'number' }, + params: {}, + }, + ], + }, + enableHover: false, + invertColors: false, + legendPosition: 'right', + percentageMode: false, + setColorRange: false, + times: [], + type: 'heatmap', + valueAxes: [ + { + id: 'ValueAxis-1', + labels: { + color: 'black', + overwriteColor: false, + rotate: 0, + show: false, + }, + scale: { defaultYExtents: false, type: 'linear' }, + show: false, + type: 'value', + }, + ], + }, + uiState: { + vis: { + defaultColors: { + '0 - 160': 'rgb(247,251,255)', + '160 - 320': 'rgb(227,238,249)', + '320 - 480': 'rgb(208,225,242)', + '480 - 640': 'rgb(182,212,233)', + '640 - 800': 'rgb(148,196,223)', + '800 - 960': 'rgb(107,174,214)', + '960 - 1,120': 'rgb(74,152,201)', + '1,120 - 1,280': 'rgb(46,126,188)', + '1,280 - 1,440': 'rgb(23,100,171)', + '1,440 - 1,600': 'rgb(8,74,145)', + }, + }, + }, + data: { + searchSource: { + query: { + language: 'kuery', + query: '', + }, + filter: [], + index: indexPatternId, + }, + references: [ + { + name: 'kibanaSavedObjectMeta.searchSourceJSON.index', + type: 'index-pattern', + id: indexPatternId, + }, + ], + aggs: [ + { + enabled: true, + id: '1', + params: {}, + schema: 'metric', + type: 'count', + }, + { + enabled: true, + id: '3', + params: { + customLabel: 'Requirement', + field: 'rule.nist_800_53', + missingBucket: false, + missingBucketLabel: 'Missing', + order: 'desc', + orderBy: '1', + otherBucket: false, + otherBucketLabel: 'Other', + size: 10, + }, + schema: 'group', + type: 'terms', + }, + { + enabled: true, + id: '2', + params: { + customLabel: 'Agent', + field: 'agent.id', + missingBucket: false, + missingBucketLabel: 'Missing', + order: 'desc', + orderBy: '1', + otherBucket: false, + otherBucketLabel: 'Other', + size: 5, + }, + schema: 'segment', + type: 'terms', + }, + ], + }, + }; +}; + +// Visualization ID: Wazuh-App-Overview-NIST-Metrics +const getVisStateMetrics = (indexPatternId: string) => { + return { + title: 'Stats', + type: 'metric', + params: { + metric: { + percentageMode: false, + useRanges: false, + colorSchema: 'Green to Red', + metricColorMode: 'None', + colorsRange: [{ type: 'range', from: 0, to: 10000 }], + labels: { show: true }, + invertColors: false, + style: { + bgFill: '#000', + bgColor: false, + labelColor: false, + subText: '', + fontSize: 20, + }, + }, + dimensions: { + metrics: [ + { + type: 'vis_dimension', + accessor: 0, + format: { id: 'number', params: {} }, + }, + { + type: 'vis_dimension', + accessor: 1, + format: { id: 'number', params: {} }, + }, + ], + }, + addTooltip: true, + addLegend: false, + type: 'metric', + }, + 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: { customLabel: 'Total alerts' }, + }, + { + id: '2', + enabled: true, + type: 'max', + schema: 'metric', + params: { + field: 'rule.level', + customLabel: 'Max rule level detected', + }, + }, + ], + }, + }; +}; + +// Visualization ID: Wazuh-App-Overview-NIST-Top-10-requirements +const getVisStateTopRequirements = (indexPatternId: string) => { + return { + title: 'Top 10 requirements', + type: 'pie', + params: { + type: 'pie', + addTooltip: true, + addLegend: true, + legendPosition: 'right', + isDonut: true, + labels: { + show: false, + values: true, + last_level: true, + truncate: 100, + }, + dimensions: { + metric: { + accessor: 1, + format: { id: 'number' }, + params: {}, + aggType: 'count', + }, + buckets: [ + { + accessor: 0, + format: { + id: 'terms', + params: { + id: 'string', + otherBucketLabel: 'Other', + missingBucketLabel: 'Missing', + }, + }, + params: {}, + aggType: 'terms', + }, + ], + }, + }, + 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.nist_800_53', + orderBy: '1', + order: 'desc', + size: 10, + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + customLabel: 'Requirement', + }, + }, + ], + }, + }; +}; + +// Visualization ID: Wazuh-App-Agents-NIST-Stats +const getVisStateAgentStats = (indexPatternId: string) => { + return { + title: 'Stats', + type: 'metric', + params: { + metric: { + percentageMode: false, + useRanges: false, + colorSchema: 'Green to Red', + metricColorMode: 'None', + colorsRange: [{ type: 'range', from: 0, to: 10000 }], + labels: { show: true }, + invertColors: false, + style: { + bgFill: '#000', + bgColor: false, + labelColor: false, + subText: '', + fontSize: 20, + }, + }, + dimensions: { + metrics: [ + { + type: 'vis_dimension', + accessor: 0, + format: { id: 'number', params: {} }, + }, + { + type: 'vis_dimension', + accessor: 1, + format: { id: 'number', params: {} }, + }, + ], + }, + addTooltip: true, + addLegend: false, + type: 'metric', + }, + 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: { customLabel: 'Total alerts' }, + }, + { + id: '3', + enabled: true, + type: 'max', + schema: 'metric', + params: { field: 'rule.level', customLabel: 'Max rule level' }, + }, + ], + }, + }; + return { + title: 'Requirements distribution by agent', + type: 'histogram', + params: { + type: 'histogram', + 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: 'histogram', + mode: 'stacked', + data: { label: 'Count', id: '1' }, + valueAxis: 'ValueAxis-1', + drawLinesBetweenPoints: true, + showCircles: true, + }, + ], + addTooltip: true, + addLegend: true, + legendPosition: 'right', + times: [], + addTimeMarker: false, + labels: { show: false }, + dimensions: { + x: { + accessor: 0, + format: { id: 'date', params: { pattern: 'YYYY-MM-DD HH:mm' } }, + params: { + date: true, + interval: 'auto', + format: 'YYYY-MM-DD HH:mm', + bounds: { + min: '2019-08-15T12:25:44.851Z', + max: '2019-08-22T12:25:44.851Z', + }, + }, + aggType: 'date_histogram', + }, + y: [ + { + accessor: 2, + format: { id: 'number' }, + params: {}, + aggType: 'count', + }, + ], + series: [ + { + accessor: 1, + format: { + id: 'terms', + params: { + id: 'string', + otherBucketLabel: 'Other', + missingBucketLabel: 'Missing', + }, + }, + params: {}, + aggType: 'terms', + }, + ], + }, + }, + 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', + orderBy: '1', + order: 'desc', + size: 5, + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + }, + }, + { + id: '3', + enabled: true, + type: 'terms', + schema: 'group', + params: { + field: 'rule.hipaa', + orderBy: '1', + order: 'desc', + size: 10, + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + }, + }, + ], + }, + }; +}; + +// Visualization ID: Wazuh-App-Agents-NIST-top-10-requirements +const getVisStateAgentTopRequirements = (indexPatternId: string) => { + return { + title: 'Top 10 requirements', + type: 'pie', + params: { + type: 'pie', + addTooltip: true, + addLegend: true, + legendPosition: 'right', + isDonut: true, + labels: { + show: false, + values: true, + last_level: true, + truncate: 100, + }, + dimensions: { + metric: { + accessor: 0, + format: { id: 'number' }, + params: {}, + aggType: 'count', + }, + }, + }, + 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.nist_800_53', + orderBy: '1', + order: 'desc', + size: 10, + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + customLabel: 'Requirement', + }, + }, + ], + }, + }; +}; + +// Visualization ID: Wazuh-App-Agents-NIST-Requirement-by-level +const getVisStateAgentRuleLevelDistribution = (indexPatternId: string) => { + return { + title: 'Requirements distributed by level', + type: 'histogram', + params: { + type: 'histogram', + grid: { categoryLines: false }, + categoryAxes: [ + { + id: 'CategoryAxis-1', + type: 'category', + position: 'left', + show: true, + style: {}, + scale: { type: 'linear' }, + labels: { show: true, rotate: 0, filter: true, truncate: 200 }, + title: {}, + }, + ], + valueAxes: [ + { + id: 'ValueAxis-1', + name: 'LeftAxis-1', + type: 'value', + position: 'bottom', + show: true, + style: {}, + scale: { type: 'linear', mode: 'normal' }, + labels: { show: true, rotate: 75, filter: true, 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, + dimensions: { + x: { + accessor: 0, + format: { + id: 'terms', + params: { + id: 'string', + otherBucketLabel: 'Other', + missingBucketLabel: 'Missing', + }, + }, + params: {}, + aggType: 'terms', + }, + y: [ + { + accessor: 2, + format: { id: 'number' }, + params: {}, + aggType: 'count', + }, + ], + series: [ + { + accessor: 1, + format: { + id: 'terms', + params: { + id: 'number', + otherBucketLabel: 'Other', + missingBucketLabel: 'Missing', + }, + }, + params: {}, + aggType: 'terms', + }, + ], + }, + labels: { show: 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: '2', + enabled: true, + type: 'terms', + schema: 'segment', + params: { + field: 'rule.nist_800_53', + orderBy: '1', + order: 'desc', + size: 5, + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + customLabel: 'Requirement', + }, + }, + { + id: '3', + enabled: true, + type: 'terms', + schema: 'group', + params: { + field: 'rule.level', + orderBy: '1', + order: 'desc', + size: 5, + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + customLabel: 'Level', + }, + }, + ], + }, + }; +}; + +// Visualization ID: Wazuh-App-Agents-NIST-Requirements-stacked-overtime +const getVisStateAgentRequirementsOverTime = (indexPatternId: string) => { + return { + title: 'Requirements over time', + type: 'histogram', + params: { + type: 'histogram', + 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: 'histogram', + mode: 'stacked', + data: { label: 'Count', id: '1' }, + valueAxis: 'ValueAxis-1', + drawLinesBetweenPoints: true, + showCircles: true, + }, + ], + addTooltip: true, + addLegend: true, + legendPosition: 'right', + times: [], + addTimeMarker: false, + labels: { show: false }, + dimensions: { + x: { + accessor: 0, + format: { id: 'date', params: { pattern: 'YYYY-MM-DD HH:mm' } }, + params: { + date: true, + interval: 'PT1H', + format: 'YYYY-MM-DD HH:mm', + bounds: { + min: '2019-08-19T09:46:35.795Z', + max: '2019-08-23T09:46:35.795Z', + }, + }, + aggType: 'date_histogram', + }, + y: [ + { + accessor: 2, + format: { id: 'number' }, + params: {}, + aggType: 'count', + }, + ], + series: [ + { + accessor: 1, + format: { + id: 'terms', + params: { + id: 'string', + otherBucketLabel: 'Other', + missingBucketLabel: 'Missing', + }, + }, + params: {}, + aggType: 'terms', + }, + ], + }, + }, + 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.hipaa', + orderBy: '1', + order: 'desc', + size: 5, + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + customLabel: 'Requirement', + }, + }, + { + id: '2', + enabled: true, + type: 'date_histogram', + schema: 'segment', + params: { + field: 'timestamp', + timeRange: { from: 'now-4d', to: 'now' }, + useNormalizedEsInterval: true, + interval: 'auto', + drop_partials: false, + min_doc_count: 1, + extended_bounds: {}, + customLabel: 'Timestamp', + }, + }, + ], + }, + }; +}; + +export const getDashboardPanels = ( + indexPatternId: string, + isPinnedAgent: boolean, +): { + [panelId: string]: DashboardPanelState< + EmbeddableInput & { [k: string]: unknown } + >; +} => { + const overviewDashboard = { + '10': { + gridData: { + w: 11, + h: 14, + x: 0, + y: 0, + i: '10', + }, + type: 'visualization', + explicitInput: { + id: '10', + savedVis: getVisStateMostActiveAgents(indexPatternId), + }, + }, + '11': { + gridData: { + w: 24, + h: 14, + x: 11, + y: 0, + i: '11', + }, + type: 'visualization', + explicitInput: { + id: '11', + savedVis: getVisStateRequirementsOverTime(indexPatternId), + }, + }, + '12': { + gridData: { + w: 13, + h: 14, + x: 35, + y: 0, + i: '12', + }, + type: 'visualization', + explicitInput: { + id: '12', + savedVis: getVisStateRequirementsByAgents(indexPatternId), + }, + }, + '20': { + gridData: { + w: 24, + h: 12, + x: 0, + y: 14, + i: '20', + }, + type: 'visualization', + explicitInput: { + id: '20', + savedVis: getVisStateRequirementsAgentsHeatmap(indexPatternId), + }, + }, + '21': { + gridData: { + w: 11, + h: 12, + x: 24, + y: 14, + i: '21', + }, + type: 'visualization', + explicitInput: { + id: '21', + savedVis: getVisStateMetrics(indexPatternId), + }, + }, + '22': { + gridData: { + w: 13, + h: 12, + x: 35, + y: 14, + i: '22', + }, + type: 'visualization', + explicitInput: { + id: '22', + savedVis: getVisStateTopRequirements(indexPatternId), + }, + }, + }; + + const agentDashboard = { + '10': { + gridData: { + w: 12, + h: 11, + x: 0, + y: 0, + i: '10', + }, + type: 'visualization', + explicitInput: { + id: '10', + savedVis: getVisStateAgentStats(indexPatternId), + }, + }, + '11': { + gridData: { + w: 12, + h: 11, + x: 12, + y: 0, + i: '11', + }, + type: 'visualization', + explicitInput: { + id: '11', + savedVis: getVisStateAgentTopRequirements(indexPatternId), + }, + }, + '12': { + gridData: { + w: 24, + h: 11, + x: 24, + y: 0, + i: '12', + }, + type: 'visualization', + explicitInput: { + id: '12', + savedVis: getVisStateAgentRuleLevelDistribution(indexPatternId), + }, + }, + '20': { + gridData: { + w: 48, + h: 11, + x: 0, + y: 11, + i: '20', + }, + type: 'visualization', + explicitInput: { + id: '20', + savedVis: getVisStateAgentRequirementsOverTime(indexPatternId), + }, + }, + }; + return isPinnedAgent ? agentDashboard : overviewDashboard; +}; diff --git a/plugins/main/public/components/overview/nist/dashboards/index.tsx b/plugins/main/public/components/overview/nist/dashboards/index.tsx new file mode 100644 index 0000000000..b691822976 --- /dev/null +++ b/plugins/main/public/components/overview/nist/dashboards/index.tsx @@ -0,0 +1 @@ +export * from './dashboard'; \ No newline at end of file diff --git a/plugins/main/public/components/overview/nist/dashboards/styles.scss b/plugins/main/public/components/overview/nist/dashboards/styles.scss new file mode 100644 index 0000000000..a3b1005567 --- /dev/null +++ b/plugins/main/public/components/overview/nist/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; + } + } +} From affb18b7d9c884356690d20a4dac64725bcee3a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Thu, 14 Mar 2024 12:49:42 +0100 Subject: [PATCH 02/14] fix(NIST800-53): fix ids dashboards panels --- .../nist/dashboards/dashboard_panels.ts | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/plugins/main/public/components/overview/nist/dashboards/dashboard_panels.ts b/plugins/main/public/components/overview/nist/dashboards/dashboard_panels.ts index fa5e63f20e..6a992a6e7d 100644 --- a/plugins/main/public/components/overview/nist/dashboards/dashboard_panels.ts +++ b/plugins/main/public/components/overview/nist/dashboards/dashboard_panels.ts @@ -1320,146 +1320,146 @@ export const getDashboardPanels = ( >; } => { const overviewDashboard = { - '10': { + g1: { gridData: { w: 11, h: 14, x: 0, y: 0, - i: '10', + i: 'g1', }, type: 'visualization', explicitInput: { - id: '10', + id: 'g1', savedVis: getVisStateMostActiveAgents(indexPatternId), }, }, - '11': { + g2: { gridData: { w: 24, h: 14, x: 11, y: 0, - i: '11', + i: 'g2', }, type: 'visualization', explicitInput: { - id: '11', + id: 'g2', savedVis: getVisStateRequirementsOverTime(indexPatternId), }, }, - '12': { + g3: { gridData: { w: 13, h: 14, x: 35, y: 0, - i: '12', + i: 'g3', }, type: 'visualization', explicitInput: { - id: '12', + id: 'g3', savedVis: getVisStateRequirementsByAgents(indexPatternId), }, }, - '20': { + g4: { gridData: { w: 24, h: 12, x: 0, y: 14, - i: '20', + i: 'g4', }, type: 'visualization', explicitInput: { - id: '20', + id: 'g4', savedVis: getVisStateRequirementsAgentsHeatmap(indexPatternId), }, }, - '21': { + g5: { gridData: { w: 11, h: 12, x: 24, y: 14, - i: '21', + i: 'g5', }, type: 'visualization', explicitInput: { - id: '21', + id: 'g5', savedVis: getVisStateMetrics(indexPatternId), }, }, - '22': { + g6: { gridData: { w: 13, h: 12, x: 35, y: 14, - i: '22', + i: 'g6', }, type: 'visualization', explicitInput: { - id: '22', + id: 'g6', savedVis: getVisStateTopRequirements(indexPatternId), }, }, }; const agentDashboard = { - '10': { + a1: { gridData: { w: 12, h: 11, x: 0, y: 0, - i: '10', + i: 'a1', }, type: 'visualization', explicitInput: { - id: '10', + id: 'a1', savedVis: getVisStateAgentStats(indexPatternId), }, }, - '11': { + a2: { gridData: { w: 12, h: 11, x: 12, y: 0, - i: '11', + i: 'a2', }, type: 'visualization', explicitInput: { - id: '11', + id: 'a2', savedVis: getVisStateAgentTopRequirements(indexPatternId), }, }, - '12': { + a3: { gridData: { w: 24, h: 11, x: 24, y: 0, - i: '12', + i: 'a3', }, type: 'visualization', explicitInput: { - id: '12', + id: 'a3', savedVis: getVisStateAgentRuleLevelDistribution(indexPatternId), }, }, - '20': { + a4: { gridData: { w: 48, h: 11, x: 0, y: 11, - i: '20', + i: 'a4', }, type: 'visualization', explicitInput: { - id: '20', + id: 'a4', savedVis: getVisStateAgentRequirementsOverTime(indexPatternId), }, }, From 5120f18cc89fa360a5005ce1bae79120010606ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Thu, 14 Mar 2024 12:50:34 +0100 Subject: [PATCH 03/14] fix: remove unused visualziation definition --- .../nist/dashboards/dashboard_panels.ts | 142 ------------------ 1 file changed, 142 deletions(-) diff --git a/plugins/main/public/components/overview/nist/dashboards/dashboard_panels.ts b/plugins/main/public/components/overview/nist/dashboards/dashboard_panels.ts index 6a992a6e7d..0062c968b2 100644 --- a/plugins/main/public/components/overview/nist/dashboards/dashboard_panels.ts +++ b/plugins/main/public/components/overview/nist/dashboards/dashboard_panels.ts @@ -788,148 +788,6 @@ const getVisStateAgentStats = (indexPatternId: string) => { ], }, }; - return { - title: 'Requirements distribution by agent', - type: 'histogram', - params: { - type: 'histogram', - 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: 'histogram', - mode: 'stacked', - data: { label: 'Count', id: '1' }, - valueAxis: 'ValueAxis-1', - drawLinesBetweenPoints: true, - showCircles: true, - }, - ], - addTooltip: true, - addLegend: true, - legendPosition: 'right', - times: [], - addTimeMarker: false, - labels: { show: false }, - dimensions: { - x: { - accessor: 0, - format: { id: 'date', params: { pattern: 'YYYY-MM-DD HH:mm' } }, - params: { - date: true, - interval: 'auto', - format: 'YYYY-MM-DD HH:mm', - bounds: { - min: '2019-08-15T12:25:44.851Z', - max: '2019-08-22T12:25:44.851Z', - }, - }, - aggType: 'date_histogram', - }, - y: [ - { - accessor: 2, - format: { id: 'number' }, - params: {}, - aggType: 'count', - }, - ], - series: [ - { - accessor: 1, - format: { - id: 'terms', - params: { - id: 'string', - otherBucketLabel: 'Other', - missingBucketLabel: 'Missing', - }, - }, - params: {}, - aggType: 'terms', - }, - ], - }, - }, - 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', - orderBy: '1', - order: 'desc', - size: 5, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - }, - }, - { - id: '3', - enabled: true, - type: 'terms', - schema: 'group', - params: { - field: 'rule.hipaa', - orderBy: '1', - order: 'desc', - size: 10, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - }, - }, - ], - }, - }; }; // Visualization ID: Wazuh-App-Agents-NIST-top-10-requirements From 388411ed62909cf4077c0c8671572a1a6b6f51d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Thu, 14 Mar 2024 15:20:51 +0100 Subject: [PATCH 04/14] rename(nist800-53): rename dashboard files --- ...ding_spinner.scss => loading-spinner.scss} | 0 .../common/components/loading-spinner.tsx | 34 +++++++++++++++++++ .../common/components/loading_spinner.tsx | 21 ------------ .../{no_results.tsx => no-results.tsx} | 0 ...ashboard_panels.ts => dashboard-panels.ts} | 0 .../overview/nist/dashboards/dashboard.tsx | 6 ++-- 6 files changed, 37 insertions(+), 24 deletions(-) rename plugins/main/public/components/overview/nist/common/components/{loading_spinner.scss => loading-spinner.scss} (100%) create mode 100644 plugins/main/public/components/overview/nist/common/components/loading-spinner.tsx delete mode 100644 plugins/main/public/components/overview/nist/common/components/loading_spinner.tsx rename plugins/main/public/components/overview/nist/common/components/{no_results.tsx => no-results.tsx} (100%) rename plugins/main/public/components/overview/nist/dashboards/{dashboard_panels.ts => dashboard-panels.ts} (100%) diff --git a/plugins/main/public/components/overview/nist/common/components/loading_spinner.scss b/plugins/main/public/components/overview/nist/common/components/loading-spinner.scss similarity index 100% rename from plugins/main/public/components/overview/nist/common/components/loading_spinner.scss rename to plugins/main/public/components/overview/nist/common/components/loading-spinner.scss diff --git a/plugins/main/public/components/overview/nist/common/components/loading-spinner.tsx b/plugins/main/public/components/overview/nist/common/components/loading-spinner.tsx new file mode 100644 index 0000000000..2ebbdff8d7 --- /dev/null +++ b/plugins/main/public/components/overview/nist/common/components/loading-spinner.tsx @@ -0,0 +1,34 @@ +import './loading-spinner.scss'; +import React from 'react'; +import { + EuiTitle, + EuiPanel, + EuiEmptyPrompt, + EuiLoadingSpinner, +} from '@elastic/eui'; +import { FormattedMessage } from '@osd/i18n/react'; + +export function LoadingSpinner() { + return ( + + } + title={ + +

+ +

+
+ } + /> +
+ ); +} diff --git a/plugins/main/public/components/overview/nist/common/components/loading_spinner.tsx b/plugins/main/public/components/overview/nist/common/components/loading_spinner.tsx deleted file mode 100644 index 7f505e6167..0000000000 --- a/plugins/main/public/components/overview/nist/common/components/loading_spinner.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import './loading_spinner.scss'; -import React from 'react'; -import { EuiTitle, EuiPanel, EuiEmptyPrompt, EuiLoadingSpinner } from '@elastic/eui'; -import { FormattedMessage } from '@osd/i18n/react'; - -export function LoadingSpinner() { - return ( - - } - title={ - -

- -

-
- } - /> -
- ); -} diff --git a/plugins/main/public/components/overview/nist/common/components/no_results.tsx b/plugins/main/public/components/overview/nist/common/components/no-results.tsx similarity index 100% rename from plugins/main/public/components/overview/nist/common/components/no_results.tsx rename to plugins/main/public/components/overview/nist/common/components/no-results.tsx diff --git a/plugins/main/public/components/overview/nist/dashboards/dashboard_panels.ts b/plugins/main/public/components/overview/nist/dashboards/dashboard-panels.ts similarity index 100% rename from plugins/main/public/components/overview/nist/dashboards/dashboard_panels.ts rename to plugins/main/public/components/overview/nist/dashboards/dashboard-panels.ts diff --git a/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx b/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx index 80202f107b..9a986e1935 100644 --- a/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx @@ -2,13 +2,13 @@ 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 { 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 { DiscoverNoResults } from '../common/components/no_results'; -import { LoadingSpinner } from '../common/components/loading_spinner'; +import { DiscoverNoResults } from '../common/components/no-results'; +import { LoadingSpinner } from '../common/components/loading-spinner'; import { search } from '../../../common/search-bar/search-bar-service'; import { IndexPattern } from '../../../../../../../src/plugins/data/common'; import { From d8b402a8a9cb028b64bfa194731be3ed473c29b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Thu, 14 Mar 2024 15:23:01 +0100 Subject: [PATCH 05/14] fix(nist800-53): add id to visualizations --- .../nist/dashboards/dashboard-panels.ts | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/plugins/main/public/components/overview/nist/dashboards/dashboard-panels.ts b/plugins/main/public/components/overview/nist/dashboards/dashboard-panels.ts index 0062c968b2..34d5069697 100644 --- a/plugins/main/public/components/overview/nist/dashboards/dashboard-panels.ts +++ b/plugins/main/public/components/overview/nist/dashboards/dashboard-panels.ts @@ -1,9 +1,9 @@ import { DashboardPanelState } from '../../../../../../../src/plugins/dashboard/public/application'; import { EmbeddableInput } from '../../../../../../../src/plugins/embeddable/public'; -// Visualization ID: Wazuh-App-Overview-NIST-Agents const getVisStateMostActiveAgents = (indexPatternId: string) => { return { + id: 'Wazuh-App-Overview-NIST-Agents', title: 'Most active agents', type: 'pie', params: { @@ -89,9 +89,9 @@ const getVisStateMostActiveAgents = (indexPatternId: string) => { }; }; -// Visualization ID: Wazuh-App-Overview-NIST-Requirements-over-time const getVisStateRequirementsOverTime = (indexPatternId: string) => { return { + id: 'Wazuh-App-Overview-NIST-Requirements-over-time', title: 'Top 10 requirements over time', type: 'histogram', params: { @@ -242,9 +242,9 @@ const getVisStateRequirementsOverTime = (indexPatternId: string) => { }; }; -// Visualization ID: Wazuh-App-Overview-NIST-requirements-by-agents const getVisStateRequirementsByAgents = (indexPatternId: string) => { return { + id: 'Wazuh-App-Overview-NIST-requirements-by-agents', title: 'Requirements distribution by agent', type: 'area', params: { @@ -395,9 +395,9 @@ const getVisStateRequirementsByAgents = (indexPatternId: string) => { }; }; -// Visualization ID: Wazuh-App-Overview-NIST-Requirements-Agents-heatmap const getVisStateRequirementsAgentsHeatmap = (indexPatternId: string) => { return { + id: 'Wazuh-App-Overview-NIST-Requirements-Agents-heatmap', title: 'Alerts volume by agent', type: 'heatmap', params: { @@ -545,9 +545,9 @@ const getVisStateRequirementsAgentsHeatmap = (indexPatternId: string) => { }; }; -// Visualization ID: Wazuh-App-Overview-NIST-Metrics const getVisStateMetrics = (indexPatternId: string) => { return { + id: 'Wazuh-App-Overview-NIST-Metrics', title: 'Stats', type: 'metric', params: { @@ -625,9 +625,9 @@ const getVisStateMetrics = (indexPatternId: string) => { }; }; -// Visualization ID: Wazuh-App-Overview-NIST-Top-10-requirements const getVisStateTopRequirements = (indexPatternId: string) => { return { + id: 'Wazuh-App-Overview-NIST-Top-10-requirements', title: 'Top 10 requirements', type: 'pie', params: { @@ -713,9 +713,9 @@ const getVisStateTopRequirements = (indexPatternId: string) => { }; }; -// Visualization ID: Wazuh-App-Agents-NIST-Stats const getVisStateAgentStats = (indexPatternId: string) => { return { + id: 'Wazuh-App-Agents-NIST-Stats', title: 'Stats', type: 'metric', params: { @@ -790,9 +790,9 @@ const getVisStateAgentStats = (indexPatternId: string) => { }; }; -// Visualization ID: Wazuh-App-Agents-NIST-top-10-requirements const getVisStateAgentTopRequirements = (indexPatternId: string) => { return { + id: 'Wazuh-App-Agents-NIST-top-10-requirements', title: 'Top 10 requirements', type: 'pie', params: { @@ -863,9 +863,9 @@ const getVisStateAgentTopRequirements = (indexPatternId: string) => { }; }; -// Visualization ID: Wazuh-App-Agents-NIST-Requirement-by-level const getVisStateAgentRuleLevelDistribution = (indexPatternId: string) => { return { + id: 'Wazuh-App-Agents-NIST-Requirement-by-level', title: 'Requirements distributed by level', type: 'histogram', params: { @@ -1016,9 +1016,9 @@ const getVisStateAgentRuleLevelDistribution = (indexPatternId: string) => { }; }; -// Visualization ID: Wazuh-App-Agents-NIST-Requirements-stacked-overtime const getVisStateAgentRequirementsOverTime = (indexPatternId: string) => { return { + id: 'Wazuh-App-Agents-NIST-Requirements-stacked-overtime', title: 'Requirements over time', type: 'histogram', params: { From 1eb8b13aa6d574d6fc5b1479c05675565e1be9a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Fri, 15 Mar 2024 14:17:18 +0100 Subject: [PATCH 06/14] fix(nist): fix dashboard --- .../components/common/modules/modules-defaults.js | 2 +- .../overview/nist/dashboards/dashboard.tsx | 12 ++++++------ .../components/overview/nist/dashboards/styles.scss | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/plugins/main/public/components/common/modules/modules-defaults.js b/plugins/main/public/components/common/modules/modules-defaults.js index f3ebe71767..2803aaafd7 100644 --- a/plugins/main/public/components/common/modules/modules-defaults.js +++ b/plugins/main/public/components/common/modules/modules-defaults.js @@ -283,7 +283,7 @@ export const ModulesDefaults = { init: 'dashboard', tabs: [ { - id: 'dashboard2', + id: 'dashboard', name: 'Dashboard', buttons: [ButtonModuleExploreAgent, ButtonModuleGenerateReport], component: DashboardNIST80053 || withPinnedAgent(DashboardNIST80053), // TODO: use withPinnedAgent diff --git a/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx b/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx index 9a986e1935..5a1fc9da48 100644 --- a/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx @@ -70,7 +70,7 @@ const DashboardNIST80053Component: React.FC = ({ pinnedAgent }) => { .catch(error => { const searchError = ErrorFactory.create(HttpError, { error, - message: 'Error fetching vulnerabilities', + message: 'Error fetching alerts', }); ErrorHandler.handleError(searchError); setIsSearching(false); @@ -85,7 +85,7 @@ const DashboardNIST80053Component: React.FC = ({ pinnedAgent }) => { {isLoading ? : null} {!isLoading ? ( { ) : null} {!isLoading && !isSearching && results?.hits?.total > 0 ? ( -
+
{ isFullScreenMode: false, filters: fetchFilters ?? [], useMargins: true, - id: 'vulnerability-detector-dashboard-tab', + id: 'nist-dashboard-tab', timeRange: { from: searchBarProps.dateRangeFrom, to: searchBarProps.dateRangeTo, }, - title: 'Vulnerability detector dashboard', - description: 'Dashboard of the Vulnerability detector', + title: 'NIST 800-53 dashboard', + description: 'Dashboard of the NIST 800-53', query: searchBarProps.query, refreshConfig: { pause: false, diff --git a/plugins/main/public/components/overview/nist/dashboards/styles.scss b/plugins/main/public/components/overview/nist/dashboards/styles.scss index a3b1005567..6630bbc35b 100644 --- a/plugins/main/public/components/overview/nist/dashboards/styles.scss +++ b/plugins/main/public/components/overview/nist/dashboards/styles.scss @@ -1,4 +1,4 @@ -.pci-dss-dashboard-responsive { +.nist-dashboard-responsive { @media (max-width: 767px) { .react-grid-layout { height: auto !important; From e1ecc6ca2191f54376d4ce99f740203d409551c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Fri, 15 Mar 2024 14:33:41 +0100 Subject: [PATCH 07/14] fix: fix dashboards --- .../public/components/overview/nist/dashboards/dashboard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx b/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx index 5a1fc9da48..d6d90d3f6c 100644 --- a/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx @@ -87,7 +87,7 @@ const DashboardNIST80053Component: React.FC = ({ pinnedAgent }) => { From 06410b3235f450bb20de699e3ebba6ada9acd403 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Thu, 11 Apr 2024 10:32:44 +0200 Subject: [PATCH 08/14] feat(nist-800-53): use data source on Dashboard and Events tabs --- plugins/main/common/constants.ts | 7 +- .../alerts-nist-800-53-data-source.ts | 42 +++++++ .../common/modules/modules-defaults.tsx | 12 +- .../common/components/loading-spinner.scss | 4 - .../common/components/loading-spinner.tsx | 34 ----- .../nist/common/components/no-results.tsx | 60 --------- .../overview/nist/dashboards/dashboard.tsx | 119 +++++++++--------- 7 files changed, 115 insertions(+), 163 deletions(-) create mode 100644 plugins/main/public/components/common/data-source/pattern/alerts/alerts-nist-800-53/alerts-nist-800-53-data-source.ts delete mode 100644 plugins/main/public/components/overview/nist/common/components/loading-spinner.scss delete mode 100644 plugins/main/public/components/overview/nist/common/components/loading-spinner.tsx delete mode 100644 plugins/main/public/components/overview/nist/common/components/no-results.tsx diff --git a/plugins/main/common/constants.ts b/plugins/main/common/constants.ts index 35399ea514..151ec17dc6 100644 --- a/plugins/main/common/constants.ts +++ b/plugins/main/common/constants.ts @@ -224,10 +224,13 @@ 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_VULNERABILITIES_RULE_GROUP = + 'vulnerabilities-rule-group'; +export const DATA_SOURCE_FILTER_CONTROLLED_NIST_800_53_EXIST = 'tsc-rule-exist'; // Wazuh links export const WAZUH_LINK_GITHUB = 'https://github.com/wazuh'; diff --git a/plugins/main/public/components/common/data-source/pattern/alerts/alerts-nist-800-53/alerts-nist-800-53-data-source.ts b/plugins/main/public/components/common/data-source/pattern/alerts/alerts-nist-800-53/alerts-nist-800-53-data-source.ts new file mode 100644 index 0000000000..105c96f9cd --- /dev/null +++ b/plugins/main/public/components/common/data-source/pattern/alerts/alerts-nist-800-53/alerts-nist-800-53-data-source.ts @@ -0,0 +1,42 @@ +import { tFilter } from '../../../index'; +import { DATA_SOURCE_FILTER_CONTROLLED_NIST_800_53_EXIST } from '../../../../../../../common/constants'; +import { AlertsDataSource } from '../alerts-data-source'; + +const KEY_EXIST = 'rule.nist_800_53'; + +export class AlertsNIST80053DataSource 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_NIST_800_53_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/modules/modules-defaults.tsx b/plugins/main/public/components/common/modules/modules-defaults.tsx index 07dc78ecca..064ede3a98 100644 --- a/plugins/main/public/components/common/modules/modules-defaults.tsx +++ b/plugins/main/public/components/common/modules/modules-defaults.tsx @@ -47,6 +47,7 @@ import { malwareDetectionColumns } from '../../overview/malware-detection/events import { WAZUH_VULNERABILITIES_PATTERN } from '../../../../common/constants'; import { DashboardNIST80053 } from '../../overview/nist/dashboards/dashboard'; import { AlertsVulnerabilitiesDataSource } from '../data-source'; +import { AlertsNIST80053DataSource } from '../data-source/pattern/alerts/alerts-nist-800-53/alerts-nist-800-53-data-source'; const ALERTS_INDEX_PATTERN = 'wazuh-alerts-*'; const DEFAULT_INDEX_PATTERN = ALERTS_INDEX_PATTERN; @@ -281,15 +282,20 @@ export const ModulesDefaults = { id: 'dashboard', name: 'Dashboard', buttons: [ButtonModuleExploreAgent, ButtonModuleGenerateReport], - component: DashboardNIST80053 || withPinnedAgent(DashboardNIST80053), // TODO: use withPinnedAgent + component: DashboardNIST80053, }, { id: 'inventory', name: 'Controls', buttons: [ButtonModuleExploreAgent], - component: ComplianceTable, + component: props => ( + + ), }, - renderDiscoverTab(DEFAULT_INDEX_PATTERN, nistColumns), + renderDiscoverTab({ + tableColumns: nistColumns, + DataSource: AlertsNIST80053DataSource, + }), ], availableFor: ['manager', 'agent'], }, diff --git a/plugins/main/public/components/overview/nist/common/components/loading-spinner.scss b/plugins/main/public/components/overview/nist/common/components/loading-spinner.scss deleted file mode 100644 index 051ab642c1..0000000000 --- a/plugins/main/public/components/overview/nist/common/components/loading-spinner.scss +++ /dev/null @@ -1,4 +0,0 @@ -.discoverNoResults { - display: flex; - align-items: center; -} diff --git a/plugins/main/public/components/overview/nist/common/components/loading-spinner.tsx b/plugins/main/public/components/overview/nist/common/components/loading-spinner.tsx deleted file mode 100644 index 2ebbdff8d7..0000000000 --- a/plugins/main/public/components/overview/nist/common/components/loading-spinner.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import './loading-spinner.scss'; -import React from 'react'; -import { - EuiTitle, - EuiPanel, - EuiEmptyPrompt, - EuiLoadingSpinner, -} from '@elastic/eui'; -import { FormattedMessage } from '@osd/i18n/react'; - -export function LoadingSpinner() { - return ( - - } - title={ - -

- -

-
- } - /> -
- ); -} diff --git a/plugins/main/public/components/overview/nist/common/components/no-results.tsx b/plugins/main/public/components/overview/nist/common/components/no-results.tsx deleted file mode 100644 index babfd51d32..0000000000 --- a/plugins/main/public/components/overview/nist/common/components/no-results.tsx +++ /dev/null @@ -1,60 +0,0 @@ -/* - * SPDX-License-Identifier: Apache-2.0 - * - * The OpenSearch Contributors require contributions made to - * this file be licensed under the Apache-2.0 license or a - * compatible open source license. - * - * Any modifications Copyright OpenSearch Contributors. See - * GitHub history for details. - */ - -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import React from 'react'; -import { FormattedMessage, I18nProvider } from '@osd/i18n/react'; - -import { EuiCallOut, EuiPanel } from '@elastic/eui'; - -interface Props { - message?: string; -} - -export const DiscoverNoResults = ({ message }: Props) => { - return ( - - - - ) - } - color='warning' - iconType='help' - data-test-subj='discoverNoResults' - /> - - - ); -}; diff --git a/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx b/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx index d6d90d3f6c..09942eccd1 100644 --- a/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx @@ -7,9 +7,8 @@ import { I18nProvider } from '@osd/i18n/react'; import useSearchBar from '../../../common/search-bar/use-search-bar'; import './styles.scss'; import { withErrorBoundary } from '../../../common/hocs'; -import { DiscoverNoResults } from '../common/components/no-results'; -import { LoadingSpinner } from '../common/components/loading-spinner'; -import { search } from '../../../common/search-bar/search-bar-service'; +import { DiscoverNoResults } from '../../../common/no-results/no-results'; +import { LoadingSpinner } from '../../../common/loading-spinner/loading-spinner'; import { IndexPattern } from '../../../../../../../src/plugins/data/common'; import { ErrorFactory, @@ -17,8 +16,14 @@ import { HttpError, } from '../../../../react-services/error-management'; import { compose } from 'redux'; -import { DashboardContainerInput } from '../../../../../../../src/plugins/dashboard/public'; import { SampleDataWarning } from '../../../visualize/components'; +import { AlertsNIST80053DataSource } from '../../../common/data-source/pattern/alerts/alerts-nist-800-53/alerts-nist-800-53-data-source'; +import { + AlertsDataSourceRepository, + PatternDataSource, + tParsedIndexPattern, + useDataSource, +} from '../../../common/data-source'; const plugins = getPlugins(); @@ -30,81 +35,76 @@ const DashboardByRenderer = plugins.dashboard.DashboardContainerByValueRenderer; a wrapper for visual adjustments, while the Kpi, the Open vs Close visualization and the rest of the visualizations have different configurations at the dashboard level. */ -const DashboardNIST80053Component: React.FC = ({ pinnedAgent }) => { - const ALERTS_INDEX_PATTERN_ID = 'wazuh-alerts-*'; // TODO: use the data source - const { searchBarProps } = useSearchBar({ - defaultIndexPatternID: ALERTS_INDEX_PATTERN_ID, - onMount: () => {}, // TODO: use data source - onUpdate: () => {}, // TODO: use data source - onUnMount: () => {}, // TODO: use data source +const DashboardNIST80053Component: React.FC = () => { + const { + filters, + dataSource, + fetchFilters, + isLoading: isDataSourceLoading, + fetchData, + setFilters, + } = useDataSource({ + DataSource: AlertsNIST80053DataSource, + repository: new AlertsDataSourceRepository(), }); + const [results, setResults] = useState({} as SearchResponse); - /* This function is responsible for updating the storage filters so that the - filters between dashboard and inventory added using visualizations call to actions. - Without this feature, filters added using visualizations call to actions are - not maintained between dashboard and inventory tabs */ - const handleFilterByVisualization = (newInput: DashboardContainerInput) => { - return; // TODO: adapt to the data source - updateFiltersStorage(newInput.filters); - }; - - // TODO: add the hidden filters: allowed agents and hideManagerAlerts - const fetchFilters = searchBarProps.filters; + const { searchBarProps } = useSearchBar({ + indexPattern: dataSource?.indexPattern as IndexPattern, + filters, + setFilters, + }); - const { isLoading, query, indexPatterns } = searchBarProps; - - const [isSearching, setIsSearching] = useState(false); - const [results, setResults] = useState({} as SearchResponse); + const { query } = searchBarProps; useEffect(() => { - if (!isLoading) { - search({ - indexPattern: indexPatterns?.[0] as IndexPattern, - filters: fetchFilters, - query, + if (isDataSourceLoading) { + return; + } + fetchData({ + query, + }) + .then(results => { + setResults(results); }) - .then(results => { - setResults(results); - setIsSearching(false); - }) - .catch(error => { - const searchError = ErrorFactory.create(HttpError, { - error, - message: 'Error fetching alerts', - }); - ErrorHandler.handleError(searchError); - setIsSearching(false); + .catch(error => { + const searchError = ErrorFactory.create(HttpError, { + error, + message: 'Error fetching alerts', }); - } - }, [JSON.stringify(searchBarProps), JSON.stringify(fetchFilters)]); + ErrorHandler.handleError(searchError); + }); + }, [JSON.stringify(fetchFilters), JSON.stringify(query)]); return ( <> <> - {isLoading ? : null} - {!isLoading ? ( - - ) : null} + {isDataSourceLoading && !dataSource ? ( + + ) : ( +
+ +
+ )} - {isSearching ? : null} - {!isLoading && !isSearching && results?.hits?.total === 0 ? ( + {dataSource && results?.hits?.total === 0 ? ( ) : null} - {!isLoading && !isSearching && results?.hits?.total > 0 ? ( + {dataSource && results?.hits?.total > 0 ? (
{ }, hidePanelTitles: false, }} - onInputUpdated={handleFilterByVisualization} />
) : null} From 629cd7da6f40908b3b92c46f66a2d54c0ddecb36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Mon, 15 Apr 2024 09:43:27 +0200 Subject: [PATCH 09/14] fix(nist): remove comment --- .../public/components/overview/nist/dashboards/dashboard.tsx | 4 ---- 1 file changed, 4 deletions(-) diff --git a/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx b/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx index 09942eccd1..2884f57e48 100644 --- a/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx @@ -31,10 +31,6 @@ const SearchBar = getPlugins().data.ui.SearchBar; const DashboardByRenderer = plugins.dashboard.DashboardContainerByValueRenderer; -/* The vulnerabilities dashboard is made up of 3 dashboards because the filters need -a wrapper for visual adjustments, while the Kpi, the Open vs Close visualization and -the rest of the visualizations have different configurations at the dashboard level. */ - const DashboardNIST80053Component: React.FC = () => { const { filters, From 3b8e49bbe956e90e6c2c643d0e444e7866cbb266 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Mon, 15 Apr 2024 09:44:56 +0200 Subject: [PATCH 10/14] fix(nist): add date range to Dashboard query --- .../overview/nist/dashboards/dashboard.tsx | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx b/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx index 2884f57e48..13f03ac096 100644 --- a/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx @@ -51,7 +51,7 @@ const DashboardNIST80053Component: React.FC = () => { setFilters, }); - const { query } = searchBarProps; + const { query, dateRangeFrom, dateRangeTo } = searchBarProps; useEffect(() => { if (isDataSourceLoading) { @@ -59,6 +59,10 @@ const DashboardNIST80053Component: React.FC = () => { } fetchData({ query, + dateRange: { + from: dateRangeFrom, + to: dateRangeTo, + }, }) .then(results => { setResults(results); @@ -70,7 +74,12 @@ const DashboardNIST80053Component: React.FC = () => { }); ErrorHandler.handleError(searchError); }); - }, [JSON.stringify(fetchFilters), JSON.stringify(query)]); + }, [ + JSON.stringify(fetchFilters), + JSON.stringify(query), + JSON.stringify(dateRangeFrom), + JSON.stringify(dateRangeTo), + ]); return ( <> From 1330a7b5e5505184648135be089dee248a9239e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Mon, 15 Apr 2024 09:46:47 +0200 Subject: [PATCH 11/14] remove(nist): visualizations on server side --- .../visualizations/agents/agents-nist.ts | 646 -------------- .../visualizations/agents/index.ts | 4 +- .../visualizations/overview/index.ts | 4 +- .../visualizations/overview/overview-nist.ts | 838 ------------------ 4 files changed, 2 insertions(+), 1490 deletions(-) delete mode 100644 plugins/main/server/integration-files/visualizations/agents/agents-nist.ts delete mode 100644 plugins/main/server/integration-files/visualizations/overview/overview-nist.ts diff --git a/plugins/main/server/integration-files/visualizations/agents/agents-nist.ts b/plugins/main/server/integration-files/visualizations/agents/agents-nist.ts deleted file mode 100644 index 4f0247f6e1..0000000000 --- a/plugins/main/server/integration-files/visualizations/agents/agents-nist.ts +++ /dev/null @@ -1,646 +0,0 @@ -/* - * Wazuh app - Module for Agents/NIST-800-53 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-NIST-Stats', - _source: { - title: 'Stats', - visState: JSON.stringify({ - title: 'Stats', - type: 'metric', - params: { - metric: { - percentageMode: false, - useRanges: false, - colorSchema: 'Green to Red', - metricColorMode: 'None', - colorsRange: [{ type: 'range', from: 0, to: 10000 }], - labels: { show: true }, - invertColors: false, - style: { - bgFill: '#000', - bgColor: false, - labelColor: false, - subText: '', - fontSize: 20, - }, - }, - dimensions: { - metrics: [ - { - type: 'vis_dimension', - accessor: 0, - format: { id: 'number', params: {} }, - }, - { - type: 'vis_dimension', - accessor: 1, - format: { id: 'number', params: {} }, - }, - ], - }, - addTooltip: true, - addLegend: false, - type: 'metric', - }, - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: { customLabel: 'Total alerts' }, - }, - { - id: '3', - enabled: true, - type: 'max', - schema: 'metric', - params: { field: 'rule.level', customLabel: 'Max rule level' }, - }, - ], - }), - uiStateJSON: '{}', - description: '', - version: 1, - kibanaSavedObjectMeta: { - searchSourceJSON: JSON.stringify({ - index: 'wazuh-alerts', - filter: [], - query: { query: '', language: 'lucene' }, - }), - }, - }, - _type: 'visualization', - }, - { - _id: 'Wazuh-App-Agents-NIST-top-10-requirements', - _source: { - title: 'Top 10 requirements', - visState: JSON.stringify({ - title: 'Top 10 requirements', - type: 'pie', - params: { - type: 'pie', - addTooltip: true, - addLegend: true, - legendPosition: 'right', - isDonut: true, - labels: { - show: false, - values: true, - last_level: true, - truncate: 100, - }, - dimensions: { - metric: { - accessor: 0, - format: { id: 'number' }, - params: {}, - aggType: 'count', - }, - }, - }, - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: {}, - }, - { - id: '2', - enabled: true, - type: 'terms', - schema: 'segment', - params: { - field: 'rule.nist_800_53', - orderBy: '1', - order: 'desc', - size: 10, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'Requirement', - }, - }, - ], - }), - uiStateJSON: '{}', - description: '', - version: 1, - kibanaSavedObjectMeta: { - searchSourceJSON: JSON.stringify({ - index: 'wazuh-alerts', - filter: [], - query: { query: '', language: 'lucene' }, - }), - }, - }, - _type: 'visualization', - }, - { - _id: 'Wazuh-App-Agents-NIST-Requirement-by-level', - _source: { - title: 'Requirements distributed by level', - visState: JSON.stringify({ - title: 'Requirements distributed by level', - type: 'histogram', - params: { - type: 'histogram', - grid: { categoryLines: false }, - categoryAxes: [ - { - id: 'CategoryAxis-1', - type: 'category', - position: 'left', - show: true, - style: {}, - scale: { type: 'linear' }, - labels: { show: true, rotate: 0, filter: true, truncate: 200 }, - title: {}, - }, - ], - valueAxes: [ - { - id: 'ValueAxis-1', - name: 'LeftAxis-1', - type: 'value', - position: 'bottom', - show: true, - style: {}, - scale: { type: 'linear', mode: 'normal' }, - labels: { show: true, rotate: 75, filter: true, 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, - dimensions: { - x: { - accessor: 0, - format: { - id: 'terms', - params: { - id: 'string', - otherBucketLabel: 'Other', - missingBucketLabel: 'Missing', - }, - }, - params: {}, - aggType: 'terms', - }, - y: [ - { - accessor: 2, - format: { id: 'number' }, - params: {}, - aggType: 'count', - }, - ], - series: [ - { - accessor: 1, - format: { - id: 'terms', - params: { - id: 'number', - otherBucketLabel: 'Other', - missingBucketLabel: 'Missing', - }, - }, - params: {}, - aggType: 'terms', - }, - ], - }, - labels: { show: false }, - }, - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: {}, - }, - { - id: '2', - enabled: true, - type: 'terms', - schema: 'segment', - params: { - field: 'rule.nist_800_53', - orderBy: '1', - order: 'desc', - size: 5, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'Requirement', - }, - }, - { - id: '3', - enabled: true, - type: 'terms', - schema: 'group', - params: { - field: 'rule.level', - orderBy: '1', - order: 'desc', - size: 5, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'Level', - }, - }, - ], - }), - uiStateJSON: '{}', - description: '', - version: 1, - kibanaSavedObjectMeta: { - searchSourceJSON: JSON.stringify({ - index: 'wazuh-alerts', - filter: [], - query: { query: '', language: 'lucene' }, - }), - }, - }, - _type: 'visualization', - }, - { - _id: 'Wazuh-App-Agents-NIST-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-NIST-Requirements-stacked-overtime', - _source: { - title: 'Requirements over time', - visState: JSON.stringify({ - title: 'Requirements over time', - type: 'histogram', - params: { - type: 'histogram', - 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: 'histogram', - mode: 'stacked', - data: { label: 'Count', id: '1' }, - valueAxis: 'ValueAxis-1', - drawLinesBetweenPoints: true, - showCircles: true, - }, - ], - addTooltip: true, - addLegend: true, - legendPosition: 'right', - times: [], - addTimeMarker: false, - labels: { show: false }, - dimensions: { - x: { - accessor: 0, - format: { id: 'date', params: { pattern: 'YYYY-MM-DD HH:mm' } }, - params: { - date: true, - interval: 'PT1H', - format: 'YYYY-MM-DD HH:mm', - bounds: { - min: '2019-08-19T09:46:35.795Z', - max: '2019-08-23T09:46:35.795Z', - }, - }, - aggType: 'date_histogram', - }, - y: [ - { - accessor: 2, - format: { id: 'number' }, - params: {}, - aggType: 'count', - }, - ], - series: [ - { - accessor: 1, - format: { - id: 'terms', - params: { - id: 'string', - otherBucketLabel: 'Other', - missingBucketLabel: 'Missing', - }, - }, - params: {}, - aggType: 'terms', - }, - ], - }, - }, - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: {}, - }, - { - id: '3', - enabled: true, - type: 'terms', - schema: 'group', - params: { - field: 'rule.hipaa', - orderBy: '1', - order: 'desc', - size: 5, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'Requirement', - }, - }, - { - id: '2', - enabled: true, - type: 'date_histogram', - schema: 'segment', - params: { - field: 'timestamp', - timeRange: { from: 'now-4d', to: 'now' }, - useNormalizedEsInterval: true, - interval: 'auto', - drop_partials: false, - min_doc_count: 1, - extended_bounds: {}, - customLabel: 'Timestamp', - }, - }, - ], - }), - uiStateJSON: '{}', - description: '', - version: 1, - kibanaSavedObjectMeta: { - searchSourceJSON: JSON.stringify({ - index: 'wazuh-alerts', - filter: [], - query: { query: '', language: 'lucene' }, - }), - }, - }, - _type: 'visualization', - }, - { - _id: 'Wazuh-App-Agents-NIST-Last-alerts', - _type: 'visualization', - _source: { - title: 'Alerts summary', - visState: JSON.stringify({ - title: 'Alerts summary', - type: 'table', - params: { - perPage: 10, - showPartialRows: false, - showMetricsAtAllLevels: false, - sort: { columnIndex: 3, direction: 'desc' }, - showTotal: false, - showToolbar: true, - totalFunc: 'sum', - dimensions: { - metrics: [ - { - accessor: 3, - format: { id: 'number' }, - params: {}, - aggType: 'count', - }, - ], - buckets: [ - { - accessor: 0, - format: { - id: 'terms', - params: { - id: 'string', - otherBucketLabel: 'Other', - missingBucketLabel: 'Missing', - }, - }, - params: {}, - aggType: 'terms', - }, - { - accessor: 1, - format: { - id: 'terms', - params: { - id: 'number', - otherBucketLabel: 'Other', - missingBucketLabel: 'Missing', - }, - }, - params: {}, - aggType: 'terms', - }, - { - accessor: 2, - format: { - id: 'terms', - params: { - id: 'string', - otherBucketLabel: 'Other', - missingBucketLabel: 'Missing', - }, - }, - params: {}, - aggType: 'terms', - }, - ], - }, - }, - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: {}, - }, - { - id: '3', - enabled: true, - type: 'terms', - schema: 'bucket', - params: { - field: 'rule.nist_800_53', - orderBy: '1', - order: 'desc', - size: 20, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'Requirement', - }, - }, - { - id: '4', - enabled: true, - type: 'terms', - schema: 'bucket', - params: { - field: 'rule.level', - orderBy: '1', - order: 'desc', - size: 5, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'Rule level', - }, - }, - { - id: '5', - enabled: true, - type: 'terms', - schema: 'bucket', - params: { - field: 'rule.description', - orderBy: '1', - order: 'desc', - size: 200, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: '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' }, - }), - }, - }, - }, -]; diff --git a/plugins/main/server/integration-files/visualizations/agents/index.ts b/plugins/main/server/integration-files/visualizations/agents/index.ts index 71a0dd7438..3811f57beb 100644 --- a/plugins/main/server/integration-files/visualizations/agents/index.ts +++ b/plugins/main/server/integration-files/visualizations/agents/index.ts @@ -19,7 +19,6 @@ import pci from './agents-pci'; import gdpr from './agents-gdpr'; import hipaa from './agents-hipaa'; import mitre from './agents-mitre'; -import nist from './agents-nist'; import tsc from './agents-tsc'; import pm from './agents-pm'; import virustotal from './agents-virustotal'; @@ -39,7 +38,6 @@ export { pci, gdpr, hipaa, - nist, tsc, pm, virustotal, @@ -48,5 +46,5 @@ export { docker, welcome, aws, - github + github, }; diff --git a/plugins/main/server/integration-files/visualizations/overview/index.ts b/plugins/main/server/integration-files/visualizations/overview/index.ts index 8f8711b75f..2aaaff8eaf 100644 --- a/plugins/main/server/integration-files/visualizations/overview/index.ts +++ b/plugins/main/server/integration-files/visualizations/overview/index.ts @@ -19,7 +19,6 @@ 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'; import tsc from './overview-tsc'; import pm from './overview-pm'; import virustotal from './overview-virustotal'; @@ -40,7 +39,6 @@ export { pci, gdpr, hipaa, - nist, tsc, pm, virustotal, @@ -48,5 +46,5 @@ export { office, osquery, docker, - github + github, }; diff --git a/plugins/main/server/integration-files/visualizations/overview/overview-nist.ts b/plugins/main/server/integration-files/visualizations/overview/overview-nist.ts deleted file mode 100644 index 481e4d1c90..0000000000 --- a/plugins/main/server/integration-files/visualizations/overview/overview-nist.ts +++ /dev/null @@ -1,838 +0,0 @@ -/* - * Wazuh app - Module for Overview/NIST 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-NIST-Requirements-over-time', - _source: { - title: 'Requirements over time', - visState: JSON.stringify({ - title: 'NIST-Requirements-over-time', - type: 'histogram', - params: { - type: 'histogram', - 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: true, - showCircles: true, - interpolate: 'linear', - }, - ], - addTooltip: true, - addLegend: true, - legendPosition: 'right', - times: [], - addTimeMarker: false, - labels: { show: false }, - dimensions: { - x: { - accessor: 0, - format: { id: 'date', params: { pattern: 'YYYY-MM-DD HH:mm' } }, - params: { - date: true, - interval: 'PT1H', - format: 'YYYY-MM-DD HH:mm', - bounds: { - min: '2019-08-20T12:33:23.360Z', - max: '2019-08-22T12:33:23.360Z', - }, - }, - aggType: 'date_histogram', - }, - y: [ - { - accessor: 2, - format: { id: 'number' }, - params: {}, - aggType: 'count', - }, - ], - series: [ - { - accessor: 1, - format: { - id: 'terms', - params: { - id: 'string', - otherBucketLabel: 'Other', - missingBucketLabel: 'Missing', - }, - }, - params: {}, - aggType: 'terms', - }, - ], - }, - }, - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: {}, - }, - { - id: '4', - enabled: true, - type: 'terms', - schema: 'group', - params: { - field: 'rule.nist_800_53', - orderBy: '1', - order: 'desc', - size: 8, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'Requirement', - }, - }, - { - id: '2', - enabled: true, - type: 'date_histogram', - schema: 'segment', - params: { - field: 'timestamp', - timeRange: { from: 'now-2d', to: 'now' }, - useNormalizedEsInterval: true, - interval: 'auto', - drop_partials: false, - 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-NIST-Requirements-Agents-heatmap', - _type: 'visualization', - _source: { - title: 'Alerts volume by agent', - visState: JSON.stringify({ - aggs: [ - { - enabled: true, - id: '1', - params: {}, - schema: 'metric', - type: 'count', - }, - { - enabled: true, - id: '3', - params: { - customLabel: 'Requirement', - field: 'rule.nist_800_53', - missingBucket: false, - missingBucketLabel: 'Missing', - order: 'desc', - orderBy: '1', - otherBucket: false, - otherBucketLabel: 'Other', - size: 10, - }, - schema: 'group', - type: 'terms', - }, - { - enabled: true, - id: '2', - params: { - customLabel: 'Agent', - field: 'agent.id', - missingBucket: false, - missingBucketLabel: 'Missing', - order: 'desc', - orderBy: '1', - otherBucket: false, - otherBucketLabel: 'Other', - size: 5, - }, - schema: 'segment', - type: 'terms', - }, - ], - params: { - addLegend: true, - addTooltip: true, - colorSchema: 'Blues', - colorsNumber: 10, - colorsRange: [], - dimensions: { - series: [ - { - accessor: 0, - aggType: 'terms', - format: { - id: 'terms', - params: { - id: 'string', - missingBucketLabel: 'Missing', - otherBucketLabel: 'Other', - }, - }, - params: {}, - }, - ], - x: { - accessor: 1, - aggType: 'terms', - format: { - id: 'terms', - params: { - id: 'string', - missingBucketLabel: 'Missing', - otherBucketLabel: 'Other', - }, - }, - params: {}, - }, - y: [ - { - accessor: 2, - aggType: 'count', - format: { id: 'number' }, - params: {}, - }, - ], - }, - enableHover: false, - invertColors: false, - legendPosition: 'right', - percentageMode: false, - setColorRange: false, - times: [], - type: 'heatmap', - valueAxes: [ - { - id: 'ValueAxis-1', - labels: { - color: 'black', - overwriteColor: false, - rotate: 0, - show: false, - }, - scale: { defaultYExtents: false, type: 'linear' }, - show: false, - type: 'value', - }, - ], - }, - title: 'NIST-Last-alerts', - type: 'heatmap', - }), - uiStateJSON: JSON.stringify({ - vis: { - defaultColors: { - '0 - 160': 'rgb(247,251,255)', - '160 - 320': 'rgb(227,238,249)', - '320 - 480': 'rgb(208,225,242)', - '480 - 640': 'rgb(182,212,233)', - '640 - 800': 'rgb(148,196,223)', - '800 - 960': 'rgb(107,174,214)', - '960 - 1,120': 'rgb(74,152,201)', - '1,120 - 1,280': 'rgb(46,126,188)', - '1,280 - 1,440': 'rgb(23,100,171)', - '1,440 - 1,600': 'rgb(8,74,145)', - }, - }, - }), - description: '', - version: 1, - kibanaSavedObjectMeta: { - searchSourceJSON: JSON.stringify({ - index: 'wazuh-alerts', - query: { query: '', language: 'lucene' }, - filter: [], - }), - }, - }, - }, - { - _id: 'Wazuh-App-Overview-NIST-requirements-by-agents', - _source: { - title: 'Requirements distribution by agent', - visState: JSON.stringify({ - title: 'NIST-Top-requirements-by-agent', - type: 'area', - params: { - type: 'area', - grid: { categoryLines: false }, - categoryAxes: [ - { - id: 'CategoryAxis-1', - type: 'category', - position: 'bottom', - show: true, - style: {}, - scale: { type: 'linear' }, - labels: { show: true, filter: true, truncate: 100 }, - title: {}, - }, - ], - valueAxes: [ - { - id: 'ValueAxis-1', - name: 'LeftAxis-1', - type: 'value', - position: 'left', - show: true, - style: {}, - scale: { type: 'linear', mode: 'normal' }, - labels: { show: true, rotate: 0, filter: false, truncate: 100 }, - title: { text: 'Count' }, - }, - ], - seriesParams: [ - { - show: 'true', - type: 'histogram', - mode: 'stacked', - data: { label: 'Count', id: '1' }, - drawLinesBetweenPoints: true, - showCircles: true, - interpolate: 'linear', - valueAxis: 'ValueAxis-1', - }, - ], - addTooltip: true, - addLegend: true, - legendPosition: 'right', - times: [], - addTimeMarker: false, - dimensions: { - x: { - accessor: 0, - format: { - id: 'terms', - params: { - id: 'string', - otherBucketLabel: 'Other', - missingBucketLabel: 'Missing', - }, - }, - params: {}, - aggType: 'terms', - }, - y: [ - { - accessor: 2, - format: { id: 'number' }, - params: {}, - aggType: 'count', - }, - ], - series: [ - { - accessor: 1, - format: { - id: 'terms', - params: { - id: 'string', - otherBucketLabel: 'Other', - missingBucketLabel: 'Missing', - }, - }, - params: {}, - aggType: 'terms', - }, - ], - }, - }, - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: {}, - }, - { - id: '2', - enabled: true, - type: 'terms', - schema: 'segment', - params: { - field: 'agent.id', - orderBy: '1', - order: 'desc', - size: 5, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'Agent', - }, - }, - { - id: '3', - enabled: true, - type: 'terms', - schema: 'group', - params: { - field: 'rule.nist_800_53', - orderBy: '1', - order: 'desc', - size: 9, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'Requirement', - }, - }, - ], - }), - 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-Overview-NIST-Metrics', - _source: { - title: 'Stats', - visState: JSON.stringify({ - title: 'nist-metrics', - type: 'metric', - params: { - metric: { - percentageMode: false, - useRanges: false, - colorSchema: 'Green to Red', - metricColorMode: 'None', - colorsRange: [{ type: 'range', from: 0, to: 10000 }], - labels: { show: true }, - invertColors: false, - style: { - bgFill: '#000', - bgColor: false, - labelColor: false, - subText: '', - fontSize: 20, - }, - }, - dimensions: { - metrics: [ - { - type: 'vis_dimension', - accessor: 0, - format: { id: 'number', params: {} }, - }, - { - type: 'vis_dimension', - accessor: 1, - format: { id: 'number', params: {} }, - }, - ], - }, - addTooltip: true, - addLegend: false, - type: 'metric', - }, - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: { customLabel: 'Total alerts' }, - }, - { - id: '2', - enabled: true, - type: 'max', - schema: 'metric', - params: { - field: 'rule.level', - customLabel: 'Max rule level detected', - }, - }, - ], - }), - uiStateJSON: '{}', - description: '', - version: 1, - kibanaSavedObjectMeta: { - searchSourceJSON: JSON.stringify({ - index: 'wazuh-alerts', - filter: [], - query: { query: '', language: 'lucene' }, - }), - }, - }, - _type: 'visualization', - }, - { - _id: 'Wazuh-App-Overview-NIST-Top-10-requirements', - _source: { - title: 'Top 10 requirements', - visState: JSON.stringify({ - title: 'NIST-Top-10-requirements', - type: 'pie', - params: { - type: 'pie', - addTooltip: true, - addLegend: true, - legendPosition: 'right', - isDonut: true, - labels: { - show: false, - values: true, - last_level: true, - truncate: 100, - }, - dimensions: { - metric: { - accessor: 1, - format: { id: 'number' }, - params: {}, - aggType: 'count', - }, - buckets: [ - { - accessor: 0, - format: { - id: 'terms', - params: { - id: 'string', - otherBucketLabel: 'Other', - missingBucketLabel: 'Missing', - }, - }, - params: {}, - aggType: 'terms', - }, - ], - }, - }, - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: {}, - }, - { - id: '2', - enabled: true, - type: 'terms', - schema: 'segment', - params: { - field: 'rule.nist_800_53', - orderBy: '1', - order: 'desc', - size: 10, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'Requirement', - }, - }, - ], - }), - uiStateJSON: '{}', - description: '', - version: 1, - kibanaSavedObjectMeta: { - searchSourceJSON: JSON.stringify({ - index: 'wazuh-alerts', - filter: [], - query: { query: '', language: 'lucene' }, - }), - }, - }, - _type: 'visualization', - }, - { - _id: 'Wazuh-App-Overview-NIST-Agents', - _source: { - title: 'Most active agents', - visState: JSON.stringify({ - title: 'NIST-Top-10-agents', - type: 'pie', - params: { - type: 'pie', - addTooltip: true, - addLegend: true, - legendPosition: 'right', - isDonut: true, - labels: { - show: false, - values: true, - last_level: true, - truncate: 100, - }, - dimensions: { - metric: { - accessor: 1, - format: { id: 'number' }, - params: {}, - aggType: 'count', - }, - buckets: [ - { - accessor: 0, - format: { - id: 'terms', - params: { - id: 'string', - otherBucketLabel: 'Other', - missingBucketLabel: 'Missing', - }, - }, - params: {}, - aggType: 'terms', - }, - ], - }, - }, - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: {}, - }, - { - id: '2', - enabled: true, - type: 'terms', - schema: 'segment', - params: { - field: 'agent.name', - orderBy: '1', - order: 'desc', - size: 10, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'Agent', - }, - }, - ], - }), - uiStateJSON: '{}', - description: '', - version: 1, - kibanaSavedObjectMeta: { - searchSourceJSON: JSON.stringify({ - index: 'wazuh-alerts', - filter: [], - query: { query: '', language: 'lucene' }, - }), - }, - }, - _type: 'visualization', - }, - { - _id: 'Wazuh-App-Overview-NIST-Alerts-summary', - _type: 'visualization', - _source: { - title: 'Alerts summary', - visState: JSON.stringify({ - title: 'NIST-Alerts-summary', - type: 'table', - params: { - perPage: 10, - showPartialRows: false, - showMetricsAtAllLevels: false, - sort: { columnIndex: 3, direction: 'desc' }, - showTotal: false, - showToolbar: true, - totalFunc: 'sum', - dimensions: { - metrics: [ - { - accessor: 3, - format: { id: 'number' }, - params: {}, - aggType: 'count', - }, - ], - buckets: [ - { - accessor: 0, - format: { - id: 'terms', - params: { - id: 'string', - otherBucketLabel: 'Other', - missingBucketLabel: 'Missing', - }, - }, - params: {}, - aggType: 'terms', - }, - { - accessor: 1, - format: { - id: 'terms', - params: { - id: 'string', - otherBucketLabel: 'Other', - missingBucketLabel: 'Missing', - }, - }, - params: {}, - aggType: 'terms', - }, - { - accessor: 2, - format: { - id: 'terms', - params: { - id: 'number', - otherBucketLabel: 'Other', - missingBucketLabel: 'Missing', - }, - }, - params: {}, - aggType: 'terms', - }, - ], - }, - }, - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - schema: 'metric', - params: {}, - }, - { - id: '2', - enabled: true, - type: 'terms', - schema: 'bucket', - params: { - field: 'agent.name', - orderBy: '1', - order: 'desc', - size: 50, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'Agent', - }, - }, - { - id: '3', - enabled: true, - type: 'terms', - schema: 'bucket', - params: { - field: 'rule.nist_800_53', - orderBy: '1', - order: 'desc', - size: 20, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'Requirement', - }, - }, - { - id: '4', - enabled: true, - type: 'terms', - schema: 'bucket', - params: { - field: 'rule.level', - orderBy: '1', - order: 'desc', - size: 5, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'Rule level', - }, - }, - ], - }), - 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' }, - }), - }, - }, - }, -]; From 4260d18f5602d2ee94a733c0a04bfd5c5de0cfed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Fri, 3 May 2024 10:59:30 +0200 Subject: [PATCH 12/14] feat(nist-800-53): hide filter control on the search bar of dashboard --- .../public/components/overview/nist/dashboards/dashboard.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx b/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx index 13f03ac096..6a41ec60ea 100644 --- a/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx @@ -88,9 +88,9 @@ const DashboardNIST80053Component: React.FC = () => { {isDataSourceLoading && !dataSource ? ( ) : ( -
+
Date: Fri, 3 May 2024 13:21:32 +0200 Subject: [PATCH 13/14] feat(nist): move sample data warning on the dashboard --- .../overview/nist/dashboards/dashboard.tsx | 58 ++++++++++--------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx b/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx index 6a41ec60ea..727a1f47c2 100644 --- a/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx +++ b/plugins/main/public/components/overview/nist/dashboards/dashboard.tsx @@ -98,38 +98,40 @@ const DashboardNIST80053Component: React.FC = () => { />
)} - {dataSource && results?.hits?.total === 0 ? ( ) : null} {dataSource && results?.hits?.total > 0 ? ( -
- -
+ <> + +
+ +
+ ) : null} From 5b21e32794998ac9ea6c686dc53a1e0a6a86a6b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Fri, 10 May 2024 13:24:17 +0200 Subject: [PATCH 14/14] fix: import dashboard --- .../main/public/components/common/modules/modules-defaults.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/main/public/components/common/modules/modules-defaults.tsx b/plugins/main/public/components/common/modules/modules-defaults.tsx index 75778e5a6c..5bf8e58e40 100644 --- a/plugins/main/public/components/common/modules/modules-defaults.tsx +++ b/plugins/main/public/components/common/modules/modules-defaults.tsx @@ -53,6 +53,7 @@ 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'; +import { DashboardNIST80053 } from '../../overview/nist/dashboards/dashboard'; import { MitreAttackDataSource } from '../data-source/pattern/alerts/mitre-attack/mitre-attack-data-source'; import { AlertsDockerDataSource,