diff --git a/plugins/main/common/constants.ts b/plugins/main/common/constants.ts index 35399ea514..e25266536e 100644 --- a/plugins/main/common/constants.ts +++ b/plugins/main/common/constants.ts @@ -54,9 +54,6 @@ export const VULNERABILITY_IMPLICIT_CLUSTER_MODE_FILTER = { disabled: 'wazuh.manager.name', }; -// Wazuh fim -export const WAZUH_FIM_PATTERN = 'wazuh-states-fim'; - // Job - Wazuh initialize export const WAZUH_PLUGIN_PLATFORM_TEMPLATE_NAME = 'wazuh-kibana'; @@ -224,10 +221,12 @@ 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'; // Wazuh links export const WAZUH_LINK_GITHUB = 'https://github.com/wazuh'; diff --git a/plugins/main/public/components/common/modules/modules-defaults.tsx b/plugins/main/public/components/common/modules/modules-defaults.tsx index 27fcc0d0da..009e6a2c15 100644 --- a/plugins/main/public/components/common/modules/modules-defaults.tsx +++ b/plugins/main/public/components/common/modules/modules-defaults.tsx @@ -12,6 +12,7 @@ import { Dashboard } from './dashboard'; import { MainSca } from '../../agents/sca'; import { MainMitre } from './main-mitre'; +import { MainFim } from '../../agents/fim'; import { ModuleMitreAttackIntelligence } from '../../overview/mitre_attack_intelligence'; import { ComplianceTable } from '../../overview/compliance-table'; import ButtonModuleExploreAgent from '../../../controllers/overview/components/overview-actions/overview-actions'; @@ -20,11 +21,12 @@ import { OfficePanel } from '../../overview/office-panel'; import { GitHubPanel } from '../../overview/github-panel'; import { DashboardVuls, InventoryVuls } from '../../overview/vulnerabilities'; import { withModuleNotForAgent } from '../hocs'; -import { WazuhDiscover, WazuhDiscoverProps } from '../wazuh-discover/wz-discover'; +import { + WazuhDiscover, + WazuhDiscoverProps, +} from '../wazuh-discover/wz-discover'; import { threatHuntingColumns } from '../wazuh-discover/config/data-grid-columns'; import { vulnerabilitiesColumns } from '../../overview/vulnerabilities/events/vulnerabilities-columns'; -import { DashboardFim } from '../../overview/fim/dashboard/dashboard'; -import { InventoryFim } from '../../overview/fim/inventory/inventory'; import React from 'react'; import { dockerColumns } from '../../overview/docker/events/docker-columns'; import { googleCloudColumns } from '../../overview/google-cloud/events/google-cloud-columns'; @@ -60,9 +62,7 @@ const renderDiscoverTab = (props: WazuhDiscoverProps) => { id: 'events', name: 'Events', buttons: [ButtonModuleExploreAgent], - component: () => ( - - ), + component: () => , }; }; @@ -89,17 +89,12 @@ export const ModulesDefaults = { fim: { init: 'dashboard', tabs: [ - { - id: 'dashboard', - name: 'Dashboard', - buttons: [ButtonModuleExploreAgent], - component: DashboardFim, - }, + DashboardTab, { id: 'inventory', name: 'Inventory', buttons: [ButtonModuleExploreAgent], - component: InventoryFim, + component: MainFim, }, renderDiscoverTab(DEFAULT_INDEX_PATTERN, fileIntegrityMonitoringColumns), ], @@ -168,9 +163,7 @@ export const ModulesDefaults = { { ...renderDiscoverTab(DEFAULT_INDEX_PATTERN, office365Columns), component: withModuleNotForAgent(() => ( - + )), }, ], @@ -223,8 +216,8 @@ export const ModulesDefaults = { }, renderDiscoverTab({ tableColumns: vulnerabilitiesColumns, - DataSource: AlertsVulnerabilitiesDataSource - }) + DataSource: AlertsVulnerabilitiesDataSource, + }), ], buttons: ['settings'], availableFor: ['manager', 'agent'], diff --git a/plugins/main/public/components/overview/fim/dashboard/dashboard.tsx b/plugins/main/public/components/overview/fim/dashboard/dashboard.tsx deleted file mode 100644 index b13fd11b91..0000000000 --- a/plugins/main/public/components/overview/fim/dashboard/dashboard.tsx +++ /dev/null @@ -1,108 +0,0 @@ -import React from 'react'; -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 { getDashboardFilters } from './dashboard_panels_filters'; -import './fim_filters.scss'; -import { getKPIsPanel } from './dashboard_panels_kpis'; -import { useAppConfig } from '../../../common/hooks'; - -const plugins = getPlugins(); - -const SearchBar = getPlugins().data.ui.SearchBar; - -const DashboardByRenderer = plugins.dashboard.DashboardContainerByValueRenderer; - -export const DashboardFim: React.FC = () => { - const appConfig = useAppConfig(); - const FIM_INDEX_PATTERN_ID = appConfig.data['fim.pattern']; - - const { searchBarProps } = useSearchBar({ - defaultIndexPatternID: FIM_INDEX_PATTERN_ID, - filters: [], - }); - - return ( - <> - - - -
- -
- - - - ); -}; diff --git a/plugins/main/public/components/overview/fim/dashboard/dashboard_panels.ts b/plugins/main/public/components/overview/fim/dashboard/dashboard_panels.ts deleted file mode 100644 index 044622307e..0000000000 --- a/plugins/main/public/components/overview/fim/dashboard/dashboard_panels.ts +++ /dev/null @@ -1,682 +0,0 @@ -import { DashboardPanelState } from '../../../../../../../../src/plugins/dashboard/public/application'; -import { EmbeddableInput } from '../../../../../../../../src/plugins/embeddable/public'; - -const getVisStateTopFim = (indexPatternId: string) => { - return { - id: 'most_detected_fim', - title: 'Most detected fim', - type: 'horizontal_bar', - 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: false, - 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, - lineWidth: 2, - showCircles: true, - }, - ], - addTooltip: true, - addLegend: false, - legendPosition: 'right', - times: [], - addTimeMarker: false, - labels: {}, - thresholdLine: { - show: false, - value: 10, - width: 1, - style: 'full', - color: '#E7664C', - }, - }, - data: { - searchSource: { - query: { - language: 'kuery', - query: '', - }, - filter: [], - index: indexPatternId, - }, - references: [ - { - name: 'kibanaSavedObjectMeta.searchSourceJSON.index', - type: 'index-pattern', - id: indexPatternId, - }, - ], - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - params: {}, - schema: 'metric', - }, - { - id: '2', - enabled: true, - type: 'terms', - params: { - field: 'vulnerability.id', - orderBy: '1', - order: 'desc', - size: 10, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'Vulnerability.ID', - }, - schema: 'segment', - }, - { - id: '3', - enabled: true, - type: 'terms', - params: { - field: 'vulnerability.id', - orderBy: '1', - order: 'desc', - size: 5, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - }, - schema: 'group', - }, - ], - }, - }; -}; - -const getVisStateTopFimEndpoints = (indexPatternId: string) => { - return { - id: 'most_vulnerable_endpoints_fim', - title: 'The most vulnerable endpoints', - type: 'horizontal_bar', - 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: false, - 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, - lineWidth: 2, - showCircles: true, - }, - ], - addTooltip: true, - addLegend: false, - legendPosition: 'right', - times: [], - addTimeMarker: false, - labels: {}, - thresholdLine: { - show: false, - value: 10, - width: 1, - style: 'full', - color: '#E7664C', - }, - }, - 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', - params: { - customLabel: 'Count', - }, - schema: 'metric', - }, - { - id: '2', - enabled: true, - type: 'terms', - params: { - field: 'agent.id', - orderBy: '1', - order: 'desc', - size: 10, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'package.path', - }, - schema: 'segment', - }, - { - id: '3', - enabled: true, - type: 'terms', - params: { - field: 'agent.id', - orderBy: '1', - order: 'desc', - size: 5, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'mm', - }, - schema: 'group', - }, - ], - }, - }; -}; - -const getVisStateAccumulationMostDetectedFim = (indexPatternId: string) => { - return { - id: 'accumulation_most_vulnerable_fim', - title: 'Accumulation of the most detected fim', - type: 'line', - params: { - type: 'line', - 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: 'line', - mode: 'normal', - data: { - label: 'Count', - id: '1', - }, - valueAxis: 'ValueAxis-1', - drawLinesBetweenPoints: false, - lineWidth: 2, - interpolate: 'linear', - showCircles: true, - }, - ], - addTooltip: true, - addLegend: true, - legendPosition: 'right', - times: [], - addTimeMarker: false, - labels: {}, - thresholdLine: { - show: false, - value: 10, - width: 1, - style: 'full', - color: '#E7664C', - }, - radiusRatio: 20, - }, - data: { - searchSource: { - query: { - language: 'kuery', - query: '', - }, - filter: [], - index: indexPatternId, - }, - references: [ - { - name: 'kibanaSavedObjectMeta.searchSourceJSON.index', - type: 'index-pattern', - id: indexPatternId, - }, - ], - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - params: {}, - schema: 'metric', - }, - { - id: '2', - enabled: true, - type: 'count', - params: {}, - schema: 'radius', - }, - { - id: '4', - enabled: true, - type: 'terms', - params: { - field: 'vulnerability.id', - orderBy: '1', - order: 'desc', - size: 5, - otherBucket: false, - otherBucketLabel: 'Others', - missingBucket: false, - missingBucketLabel: 'Missing', - }, - schema: 'group', - }, - { - id: '3', - enabled: true, - type: 'date_histogram', - params: { - field: 'event.created', - timeRange: { - from: 'now-24h', - to: 'now', - }, - useNormalizedOpenSearchInterval: true, - scaleMetricValues: false, - interval: 'w', - // eslint-disable-next-line camelcase - drop_partials: false, - // eslint-disable-next-line camelcase - min_doc_count: 1, - // eslint-disable-next-line camelcase - extended_bounds: {}, - }, - schema: 'segment', - }, - ], - }, - }; -}; - -const getVisStateInventoryTable = (indexPatternId: string) => { - return { - id: 'inventory_table_fim', - title: 'Inventory table', - type: 'table', - params: { - perPage: 5, - showPartialRows: false, - showMetricsAtAllLevels: false, - showTotal: false, - totalFunc: 'sum', - percentageCol: '', - }, - data: { - searchSource: { - query: { - language: 'kuery', - query: '', - }, - filter: [], - index: indexPatternId, - }, - references: [ - { - name: 'kibanaSavedObjectMeta.searchSourceJSON.index', - type: 'index-pattern', - id: indexPatternId, - }, - ], - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - params: { - customLabel: 'Count', - }, - schema: 'metric', - }, - { - id: '2', - enabled: true, - type: 'terms', - params: { - field: 'package.name', - orderBy: '1', - order: 'desc', - size: 5, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'name', - }, - schema: 'bucket', - }, - { - id: '3', - enabled: true, - type: 'terms', - params: { - field: 'package.version', - orderBy: '1', - order: 'desc', - size: 5, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'version', - }, - schema: 'bucket', - }, - { - id: '4', - enabled: true, - type: 'terms', - params: { - field: 'package.architecture', - orderBy: '1', - order: 'desc', - size: 5, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'architecture', - }, - schema: 'bucket', - }, - { - id: '5', - enabled: true, - type: 'terms', - params: { - field: 'vulnerability.severity', - orderBy: '1', - order: 'desc', - size: 5, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'severity', - }, - schema: 'bucket', - }, - { - id: '6', - enabled: true, - type: 'terms', - params: { - field: 'vulnerability.id', - orderBy: '1', - order: 'desc', - size: 5, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'id', - }, - schema: 'bucket', - }, - { - id: '7', - enabled: true, - type: 'terms', - params: { - field: 'vulnerability.score.version', - orderBy: '1', - order: 'desc', - size: 5, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'score version', - }, - schema: 'bucket', - }, - { - id: '8', - enabled: true, - type: 'terms', - params: { - field: 'vulnerability.score.base', - orderBy: '1', - order: 'desc', - size: 5, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: 'score base', - }, - schema: 'bucket', - }, - ], - }, - }; -}; - -export const getDashboardPanels = ( - indexPatternId: string, -): { - [panelId: string]: DashboardPanelState< - EmbeddableInput & { [k: string]: unknown } - >; -} => { - return { - '6': { - gridData: { - w: 16, - h: 12, - x: 0, - y: 0, - i: '6', - }, - type: 'visualization', - explicitInput: { - id: '6', - savedVis: getVisStateTopFim(indexPatternId), - }, - }, - '7': { - gridData: { - w: 16, - h: 12, - x: 16, - y: 0, - i: '7', - }, - type: 'visualization', - explicitInput: { - id: '7', - savedVis: getVisStateTopFimEndpoints(indexPatternId), - }, - }, - '8': { - gridData: { - w: 16, - h: 12, - x: 32, - y: 0, - i: '8', - }, - type: 'visualization', - explicitInput: { - id: '8', - savedVis: getVisStateAccumulationMostDetectedFim(indexPatternId), - }, - }, - '9': { - gridData: { - w: 48, - h: 12, - x: 0, - y: 14, - i: '9', - }, - type: 'visualization', - explicitInput: { - id: '9', - savedVis: getVisStateInventoryTable(indexPatternId), - }, - }, - }; -}; diff --git a/plugins/main/public/components/overview/fim/dashboard/dashboard_panels_filters.ts b/plugins/main/public/components/overview/fim/dashboard/dashboard_panels_filters.ts deleted file mode 100644 index 47a6d63ebb..0000000000 --- a/plugins/main/public/components/overview/fim/dashboard/dashboard_panels_filters.ts +++ /dev/null @@ -1,160 +0,0 @@ -import { DashboardPanelState } from '../../../../../../../../src/plugins/dashboard/public/application'; -import { EmbeddableInput } from '../../../../../../../../src/plugins/embeddable/public'; - -const getVisStateFilter = ( - id: string, - indexPatternId: string, - title: string, - label: string, - fieldName: string, -) => { - return { - id, - title, - type: 'table', - params: { - perPage: 5, - percentageCol: '', - row: true, - showMetricsAtAllLevels: false, - showPartialRows: false, - showTotal: false, - totalFunc: 'sum', - }, - data: { - searchSource: { - query: { - language: 'kuery', - query: '', - }, - index: indexPatternId, - }, - references: [ - { - name: 'kibanaSavedObjectMeta.searchSourceJSON.index', - type: 'index-pattern', - id: indexPatternId, - }, - ], - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - params: { - customLabel: 'Count', - }, - schema: 'metric', - }, - { - id: '2', - enabled: true, - type: 'terms', - params: { - field: fieldName, - orderBy: '1', - order: 'desc', - size: 5, - otherBucket: false, - otherBucketLabel: 'Other', - missingBucket: false, - missingBucketLabel: 'Missing', - customLabel: label, - }, - schema: 'bucket', - }, - ], - }, - }; -}; - -export const getDashboardFilters = ( - indexPatternId: string, -): { - [panelId: string]: DashboardPanelState< - EmbeddableInput & { [k: string]: unknown } - >; -} => { - return { - topPackageSelector: { - gridData: { - w: 12, - h: 12, - x: 0, - y: 0, - i: 'topPackageSelector', - }, - type: 'visualization', - explicitInput: { - id: 'topPackageSelector', - savedVis: getVisStateFilter( - 'topPackageSelector', - indexPatternId, - 'Top Packages fim', - 'Package', - 'package.name', - ), - }, - }, - topOSFim: { - gridData: { - w: 12, - h: 12, - x: 12, - y: 0, - i: 'topOSFim', - }, - type: 'visualization', - explicitInput: { - id: 'topOSFim', - savedVis: getVisStateFilter( - 'topOSFim', - indexPatternId, - 'Top Operating system fim', - 'Operating system', - 'host.os.name', - ), - }, - }, - topAgentFim: { - gridData: { - w: 12, - h: 12, - x: 24, - y: 0, - i: 'topAgentFim', - }, - type: 'visualization', - explicitInput: { - id: 'topAgentFim', - savedVis: getVisStateFilter( - 'topAgentFim', - indexPatternId, - 'Agent filter', - 'Agent', - 'agent.id', - ), - }, - }, - topFim: { - gridData: { - w: 12, - h: 12, - x: 36, - y: 0, - i: 'topFim', - }, - type: 'visualization', - explicitInput: { - id: 'topFim', - savedVis: getVisStateFilter( - 'topFim', - indexPatternId, - 'Top vulnerabilities', - 'Fim', - 'fim.id', - ), - }, - }, - }; -}; diff --git a/plugins/main/public/components/overview/fim/dashboard/dashboard_panels_kpis.ts b/plugins/main/public/components/overview/fim/dashboard/dashboard_panels_kpis.ts deleted file mode 100644 index 99afc7f18f..0000000000 --- a/plugins/main/public/components/overview/fim/dashboard/dashboard_panels_kpis.ts +++ /dev/null @@ -1,416 +0,0 @@ -import { DashboardPanelState } from '../../../../../../../../src/plugins/dashboard/public/application'; -import { EmbeddableInput } from '../../../../../../../../src/plugins/embeddable/public'; - -const getVisStateSeverityCritical = (indexPatternId: string) => { - return { - id: 'severity_critical_fim', - title: 'Critical', - type: 'metric', - params: { - addTooltip: true, - addLegend: false, - type: 'metric', - metric: { - percentageMode: false, - useRanges: false, - colorSchema: 'Reds', - metricColorMode: 'Labels', - colorsRange: [ - { - from: 0, - to: 0, - }, - { - from: 0, - to: 0, - }, - ], - labels: { - show: true, - }, - invertColors: false, - style: { - bgFill: '#000', - bgColor: false, - labelColor: false, - subText: '', - fontSize: 50, - }, - }, - }, - data: { - searchSource: { - query: { - language: 'kuery', - query: '', - }, - filter: [], - index: indexPatternId, - }, - references: [ - { - name: 'kibanaSavedObjectMeta.searchSourceJSON.index', - type: 'index-pattern', - id: indexPatternId, - }, - ], - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - params: { - customLabel: ' ', - }, - schema: 'metric', - }, - { - id: '2', - enabled: true, - type: 'filters', - params: { - filters: [ - { - input: { - query: 'vulnerability.severity:"critical"', - language: 'kuery', - }, - label: '- Critical Severity Alerts', - }, - ], - }, - schema: 'group', - }, - ], - }, - }; -}; - -const getVisStateSeverityHigh = (indexPatternId: string) => { - return { - id: 'severity_high_fim', - title: 'High', - type: 'metric', - params: { - addTooltip: true, - addLegend: false, - type: 'metric', - metric: { - percentageMode: false, - useRanges: false, - colorSchema: 'Blues', - metricColorMode: 'Labels', - colorsRange: [ - { - from: 0, - to: 0, - }, - { - from: 0, - to: 0, - }, - ], - labels: { - show: true, - }, - invertColors: false, - style: { - bgFill: '#000', - bgColor: false, - labelColor: false, - subText: '', - fontSize: 50, - }, - }, - }, - uiState: { - vis: { - colors: { - 'High Severity Alerts - Count': '#38D1BA', - }, - }, - }, - data: { - searchSource: { - query: { - language: 'kuery', - query: '', - }, - filter: [], - index: indexPatternId, - }, - references: [ - { - name: 'kibanaSavedObjectMeta.searchSourceJSON.index', - type: 'index-pattern', - id: indexPatternId, - }, - ], - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - params: { - customLabel: ' ', - }, - schema: 'metric', - }, - { - id: '2', - enabled: true, - type: 'filters', - params: { - filters: [ - { - input: { - query: 'vulnerability.severity:"high"', - language: 'kuery', - }, - label: '- High Severity Alerts', - }, - ], - }, - schema: 'group', - }, - ], - }, - }; -}; - -const getVisStateSeverityMedium = (indexPatternId: string) => { - return { - id: 'severity_medium_fim', - title: 'Medium', - type: 'metric', - params: { - addTooltip: true, - addLegend: false, - type: 'metric', - metric: { - percentageMode: false, - useRanges: false, - colorSchema: 'Yellow to Red', - metricColorMode: 'Labels', - colorsRange: [ - { - from: 0, - to: 0, - }, - { - from: 0, - to: 0, - }, - ], - labels: { - show: true, - }, - invertColors: true, - style: { - bgFill: '#000', - bgColor: false, - labelColor: false, - subText: '', - fontSize: 50, - }, - }, - }, - data: { - searchSource: { - query: { - language: 'kuery', - query: '', - }, - filter: [], - index: indexPatternId, - }, - references: [ - { - name: 'kibanaSavedObjectMeta.searchSourceJSON.index', - type: 'index-pattern', - id: indexPatternId, - }, - ], - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - params: { - customLabel: ' ', - }, - schema: 'metric', - }, - { - id: '2', - enabled: true, - type: 'filters', - params: { - filters: [ - { - input: { - query: 'vulnerability.severity:"medium"', - language: 'kuery', - }, - label: '- Medium Severity Alerts', - }, - ], - }, - schema: 'group', - }, - ], - }, - }; -}; - -const getVisStateSeverityLow = (indexPatternId: string) => { - return { - id: 'severity_low_fim', - title: 'Low', - type: 'metric', - params: { - addTooltip: true, - addLegend: false, - type: 'metric', - metric: { - percentageMode: false, - useRanges: false, - colorSchema: 'Greens', - metricColorMode: 'Labels', - colorsRange: [ - { - from: 0, - to: 0, - }, - { - from: 0, - to: 0, - }, - ], - labels: { - show: true, - }, - invertColors: false, - style: { - bgFill: '#000', - bgColor: false, - labelColor: false, - subText: '', - fontSize: 50, - }, - }, - }, - data: { - searchSource: { - query: { - language: 'kuery', - query: '', - }, - filter: [], - index: indexPatternId, - }, - references: [ - { - name: 'kibanaSavedObjectMeta.searchSourceJSON.index', - type: 'index-pattern', - id: indexPatternId, - }, - ], - aggs: [ - { - id: '1', - enabled: true, - type: 'count', - params: { - customLabel: ' ', - }, - schema: 'metric', - }, - { - id: '2', - enabled: true, - type: 'filters', - params: { - filters: [ - { - input: { - query: 'vulnerability.severity:"low"', - language: 'kuery', - }, - label: '- Low Severity Alerts', - }, - ], - }, - schema: 'group', - }, - ], - }, - }; -}; - -export const getKPIsPanel = ( - indexPatternId: string, -): { - [panelId: string]: DashboardPanelState< - EmbeddableInput & { [k: string]: unknown } - >; -} => { - return { - '1': { - gridData: { - w: 12, - h: 6, - x: 0, - y: 0, - i: '1', - }, - type: 'visualization', - explicitInput: { - id: '1', - savedVis: getVisStateSeverityCritical(indexPatternId), - }, - }, - '2': { - gridData: { - w: 12, - h: 6, - x: 12, - y: 0, - i: '2', - }, - type: 'visualization', - explicitInput: { - id: '2', - savedVis: getVisStateSeverityHigh(indexPatternId), - }, - }, - '3': { - gridData: { - w: 12, - h: 6, - x: 24, - y: 0, - i: '3', - }, - type: 'visualization', - explicitInput: { - id: '3', - savedVis: getVisStateSeverityMedium(indexPatternId), - }, - }, - '4': { - gridData: { - w: 12, - h: 6, - x: 36, - y: 0, - i: '4', - }, - type: 'visualization', - explicitInput: { - id: '4', - savedVis: getVisStateSeverityLow(indexPatternId), - }, - }, - }; -}; diff --git a/plugins/main/public/components/overview/fim/dashboard/fim_filters.scss b/plugins/main/public/components/overview/fim/dashboard/fim_filters.scss deleted file mode 100644 index a836b86e3e..0000000000 --- a/plugins/main/public/components/overview/fim/dashboard/fim_filters.scss +++ /dev/null @@ -1,6 +0,0 @@ -.fim-dashboard-filters-wrapper { - .euiDataGrid__controls, - .euiDataGrid__pagination { - display: none !important; - } -} diff --git a/plugins/main/public/components/overview/fim/dashboard/index.tsx b/plugins/main/public/components/overview/fim/dashboard/index.tsx deleted file mode 100644 index b691822976..0000000000 --- a/plugins/main/public/components/overview/fim/dashboard/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export * from './dashboard'; \ No newline at end of file diff --git a/plugins/main/public/components/overview/fim/inventory/config/index.ts b/plugins/main/public/components/overview/fim/inventory/config/index.ts deleted file mode 100644 index aa5490ffd8..0000000000 --- a/plugins/main/public/components/overview/fim/inventory/config/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { EuiDataGridColumn } from '@elastic/eui'; - -export const MAX_ENTRIES_PER_QUERY = 10000; - -export const inventoryTableDefaultColumns: EuiDataGridColumn[] = [ - { - id: 'package.name', - }, - { - id: 'package.version', - }, - { - id: 'package.architecture', - }, - { - id: 'fim.severity', - }, - { - id: 'fim.id', - }, - { - id: 'fim.score.version', - }, - { - id: 'fim.score.base', - }, - { - id: 'event.created', - }, -]; diff --git a/plugins/main/public/components/overview/fim/inventory/index.tsx b/plugins/main/public/components/overview/fim/inventory/index.tsx deleted file mode 100644 index ddb0742f5e..0000000000 --- a/plugins/main/public/components/overview/fim/inventory/index.tsx +++ /dev/null @@ -1 +0,0 @@ -export * from './inventory'; \ No newline at end of file diff --git a/plugins/main/public/components/overview/fim/inventory/inventory.scss b/plugins/main/public/components/overview/fim/inventory/inventory.scss deleted file mode 100644 index 2303093ed2..0000000000 --- a/plugins/main/public/components/overview/fim/inventory/inventory.scss +++ /dev/null @@ -1,13 +0,0 @@ -.fimInventoryContainer { - height: calc(100vh - 104px); -} - -.headerIsExpanded .fimInventoryContainer { - height: calc(100vh - 153px); -} - -.fimInventoryContainer .euiDataGrid--fullScreen { - height: calc(100vh - 49px); - bottom: 0; - top: auto; -} diff --git a/plugins/main/public/components/overview/fim/inventory/inventory.tsx b/plugins/main/public/components/overview/fim/inventory/inventory.tsx deleted file mode 100644 index e9708c8522..0000000000 --- a/plugins/main/public/components/overview/fim/inventory/inventory.tsx +++ /dev/null @@ -1,244 +0,0 @@ -import React, { useEffect, useMemo, useState } from 'react'; -import { getPlugins } from '../../../../kibana-services'; -import useSearchBar from '../../../common/search-bar/use-search-bar'; -import { IntlProvider } from 'react-intl'; -import { - EuiDataGrid, - EuiPageTemplate, - EuiToolTip, - EuiButtonIcon, - EuiDataGridCellValueElementProps, - EuiFlexGroup, - EuiFlexItem, - EuiFlyout, - EuiFlyoutBody, - EuiFlyoutHeader, - EuiTitle, - EuiButtonEmpty, -} from '@elastic/eui'; -import { IndexPattern } from '../../../../../../../../src/plugins/data/common'; -import { SearchResponse } from '../../../../../../../../src/core/server'; -import DocViewer from '../../../common/doc-viewer/doc-viewer'; -import { DiscoverNoResults } from '../../vulnerabilities/common/components/no_results'; -import { LoadingSpinner } from '../../vulnerabilities/common/components/loading_spinner'; -import { useDataGrid } from '../../../common/data-grid/use-data-grid'; -import { - MAX_ENTRIES_PER_QUERY, - inventoryTableDefaultColumns, -} from '../../vulnerabilities/dashboards/inventory/config'; -import { useDocViewer } from '../../../common/doc-viewer/use-doc-viewer'; -import './inventory.scss'; -import { - search, - exportSearchToCSV, -} from '../../../common/search-bar/search-bar-service'; -import { - ErrorHandler, - ErrorFactory, - HttpError, -} from '../../../../react-services/error-management'; -import { withErrorBoundary } from '../../../common/hocs'; -import { HitsCounter } from '../../../../kibana-integrations/discover/application/components/hits_counter/hits_counter'; -import { formatNumWithCommas } from '../../../../kibana-integrations/discover/application/helpers'; -import { useAppConfig } from '../../../common/hooks'; - -const InventoryFimComponent = () => { - const appConfig = useAppConfig(); - const FIM_INDEX_PATTERN_ID = appConfig.data['fim.pattern']; - const { searchBarProps } = useSearchBar({ - defaultIndexPatternID: FIM_INDEX_PATTERN_ID, - }); - const { isLoading, filters, query, indexPatterns } = searchBarProps; - const SearchBar = getPlugins().data.ui.SearchBar; - const [results, setResults] = useState({} as SearchResponse); - const [inspectedHit, setInspectedHit] = useState(undefined); - const [indexPattern, setIndexPattern] = useState( - undefined, - ); - const [isSearching, setIsSearching] = useState(false); - const [isExporting, setIsExporting] = useState(false); - - const onClickInspectDoc = useMemo( - () => (index: number) => { - const rowClicked = results.hits.hits[index]; - setInspectedHit(rowClicked); - }, - [results], - ); - - const DocViewInspectButton = ({ - rowIndex, - }: EuiDataGridCellValueElementProps) => { - const inspectHintMsg = 'Inspect document details'; - return ( - - onClickInspectDoc(rowIndex)} - iconType='inspect' - aria-label={inspectHintMsg} - /> - - ); - }; - - const dataGridProps = useDataGrid({ - ariaLabelledBy: 'Fim Inventory Table', - defaultColumns: inventoryTableDefaultColumns, - results, - indexPattern: indexPattern as IndexPattern, - DocViewInspectButton, - }); - - const { pagination, sorting, columnVisibility } = dataGridProps; - - const docViewerProps = useDocViewer({ - doc: inspectedHit, - indexPattern: indexPattern as IndexPattern, - }); - - useEffect(() => { - if (!isLoading) { - setIndexPattern(indexPatterns?.[0] as IndexPattern); - search({ - indexPattern: indexPatterns?.[0] as IndexPattern, - filters, - query, - pagination, - sorting, - }) - .then(results => { - setResults(results); - setIsSearching(false); - }) - .catch(error => { - const searchError = ErrorFactory.create(HttpError, { - error, - message: 'Error fetching fim', - }); - ErrorHandler.handleError(searchError); - setIsSearching(false); - }); - } - }, [ - JSON.stringify(searchBarProps), - JSON.stringify(pagination), - JSON.stringify(sorting), - ]); - - const timeField = indexPattern?.timeFieldName - ? indexPattern.timeFieldName - : undefined; - - const onClickExportResults = async () => { - const params = { - indexPattern: indexPatterns?.[0] as IndexPattern, - filters, - query, - fields: columnVisibility.visibleColumns, - pagination: { - pageIndex: 0, - pageSize: results.hits.total, - }, - sorting, - }; - try { - setIsExporting(true); - await exportSearchToCSV(params); - } catch (error) { - const searchError = ErrorFactory.create(HttpError, { - error, - message: 'Error downloading csv report', - }); - ErrorHandler.handleError(searchError); - } finally { - setIsExporting(false); - } - }; - - return ( - - - <> - {isLoading ? ( - - ) : ( - - )} - {isSearching ? : null} - {!isLoading && !isSearching && results?.hits?.total === 0 ? ( - - ) : null} - {!isLoading && !isSearching && results?.hits?.total > 0 ? ( - - {}} - tooltip={ - results?.hits?.total && - results?.hits?.total > MAX_ENTRIES_PER_QUERY - ? { - ariaLabel: 'Warning', - content: `The query results has exceeded the limit of 10,000 hits. To provide a better experience the table only shows the first ${formatNumWithCommas( - MAX_ENTRIES_PER_QUERY, - )} hits.`, - iconType: 'alert', - position: 'top', - } - : undefined - } - /> - - Export Formated - - - ), - }} - /> - ) : null} - {inspectedHit && ( - setInspectedHit(undefined)} size='m'> - - -

Document Details

-
-
- - - - - - - -
- )} - -
-
- ); -}; - -export const InventoryFim = withErrorBoundary(InventoryFimComponent); diff --git a/plugins/main/public/components/overview/fim/inventory/inventory_service.ts b/plugins/main/public/components/overview/fim/inventory/inventory_service.ts deleted file mode 100644 index 82ef36b007..0000000000 --- a/plugins/main/public/components/overview/fim/inventory/inventory_service.ts +++ /dev/null @@ -1,224 +0,0 @@ -import { SearchResponse } from '../../../../../../../../src/core/server'; -import { getPlugins } from '../../../../kibana-services'; -import { - IndexPattern, - Filter, - OpenSearchQuerySortValue, -} from '../../../../../../../../src/plugins/data/public'; -import * as FileSaver from '../../../../../services/file-saver'; -import { beautifyDate } from '../../../../agents/vuls/inventory/lib'; -import { MAX_ENTRIES_PER_QUERY } from './config'; - -interface SearchParams { - indexPattern: IndexPattern; - filters?: Filter[]; - query?: any; - pagination?: { - pageIndex?: number; - pageSize?: number; - }; - fields?: string[]; - sorting?: { - columns: { - id: string; - direction: 'asc' | 'desc'; - }[]; - }; -} - -export const search = async ( - params: SearchParams, -): Promise => { - const { - indexPattern, - filters = [], - query, - pagination, - sorting, - fields, - } = params; - if (!indexPattern) { - return; - } - const data = getPlugins().data; - const searchSource = await data.search.searchSource.create(); - const fromField = - (pagination?.pageIndex || 0) * (pagination?.pageSize || 100); - const sortOrder: OpenSearchQuerySortValue[] = - sorting?.columns.map(column => { - const sortDirection = column.direction === 'asc' ? 'asc' : 'desc'; - return { [column?.id || '']: sortDirection } as OpenSearchQuerySortValue; - }) || []; - - const searchParams = searchSource - .setParent(undefined) - .setField('filter', filters) - .setField('query', query) - .setField('sort', sortOrder) - .setField('size', pagination?.pageSize) - .setField('from', fromField) - .setField('index', indexPattern); - - // add fields - if (fields && Array.isArray(fields) && fields.length > 0) { - searchParams.setField('fields', fields); - } - try { - return await searchParams.fetch(); - } catch (error) { - if (error.body) { - throw error.body; - } - throw error; - } -}; - -export const parseData = ( - resultsHits: SearchResponse['hits']['hits'], -): any[] => { - const data = resultsHits.map(hit => { - if (!hit) { - return {}; - } - const source = hit._source as object; - const data = { - ...source, - _id: hit._id, - _index: hit._index, - _type: hit._type, - _score: hit._score, - }; - return data; - }); - return data; -}; - -export const getFieldFormatted = ( - rowIndex, - columnId, - indexPattern, - rowsParsed, -) => { - const field = indexPattern.fields.find(field => field.name === columnId); - let fieldValue = null; - if (columnId.includes('.')) { - // when the column is a nested field. The column could have 2 to n levels - // get dinamically the value of the nested field - const nestedFields = columnId.split('.'); - fieldValue = rowsParsed[rowIndex]; - nestedFields.forEach(field => { - if (fieldValue) { - fieldValue = fieldValue[field]; - } - }); - } else { - fieldValue = rowsParsed[rowIndex][columnId].formatted - ? rowsParsed[rowIndex][columnId].formatted - : rowsParsed[rowIndex][columnId]; - } - - // if is date field - if (field?.type === 'date') { - // @ts-ignore - fieldValue = beautifyDate(fieldValue); - } - return fieldValue; -}; - -export const exportSearchToCSV = async ( - params: SearchParams, -): Promise => { - const DEFAULT_MAX_SIZE_PER_CALL = 1000; - const { - indexPattern, - filters = [], - query, - sorting, - fields, - pagination, - } = params; - // when the pageSize is greater than the default max size per call (10000) - // then we need to paginate the search - const mustPaginateSearch = - pagination?.pageSize && pagination?.pageSize > DEFAULT_MAX_SIZE_PER_CALL; - const pageSize = mustPaginateSearch - ? DEFAULT_MAX_SIZE_PER_CALL - : pagination?.pageSize; - const totalHits = pagination?.pageSize || DEFAULT_MAX_SIZE_PER_CALL; - let pageIndex = params.pagination?.pageIndex || 0; - let hitsCount = 0; - let allHits = []; - let searchResults; - if (mustPaginateSearch) { - // paginate the search - while (hitsCount < totalHits && hitsCount < MAX_ENTRIES_PER_QUERY) { - const searchParams = { - indexPattern, - filters, - query, - pagination: { - pageIndex, - pageSize, - }, - sorting, - fields, - }; - searchResults = await search(searchParams); - allHits = allHits.concat(searchResults.hits.hits); - hitsCount = allHits.length; - pageIndex++; - } - } else { - searchResults = await search(params); - allHits = searchResults.hits.hits; - } - - const resultsFields = fields; - const data = allHits.map(hit => { - // check if the field type is a date - const dateFields = indexPattern.fields.getByType('date'); - const dateFieldsNames = dateFields.map(field => field.name); - const flattenHit = indexPattern.flattenHit(hit); - // replace the date fields with the formatted date - dateFieldsNames.forEach(field => { - if (flattenHit[field]) { - flattenHit[field] = beautifyDate(flattenHit[field]); - } - }); - return flattenHit; - }); - - if (!resultsFields || resultsFields.length === 0) { - return; - } - - if (!data || data.length === 0) return; - - const parsedData = data - .map(row => { - const parsedRow = resultsFields?.map(field => { - const value = row[field]; - if (value === undefined || value === null) { - return ''; - } - if (typeof value === 'object') { - return JSON.stringify(value); - } - return `"${value}"`; - }); - return parsedRow?.join(','); - }) - .join('\n'); - - // create a csv file using blob - const blobData = new Blob([`${resultsFields?.join(',')}\n${parsedData}`], { - type: 'text/csv', - }); - - if (blobData) { - FileSaver?.saveAs( - blobData, - `fim_inventory-${new Date().toISOString()}.csv`, - ); - } -}; diff --git a/plugins/main/public/redux/reducers/appConfigReducers.ts b/plugins/main/public/redux/reducers/appConfigReducers.ts index c4306c39b2..742a99f216 100644 --- a/plugins/main/public/redux/reducers/appConfigReducers.ts +++ b/plugins/main/public/redux/reducers/appConfigReducers.ts @@ -20,7 +20,6 @@ const initialState: AppConfigState = { data: { // TODO: this should use the configuration service 'vulnerabilities.pattern': 'wazuh-states-vulnerabilities', - 'fim.pattern': 'wazuh-states-fim', }, }; @@ -51,14 +50,6 @@ const appConfigReducer: Reducer = ( hasError: false, data: { ...state.data, ...action.payload }, }; - case 'UPDATE_FIM_PATTERN': - return { - ...state, - data: { - ...state.data, - 'fim.pattern': action.payload, - }, - }; default: return state; } diff --git a/plugins/main/test/cypress/cypress/fixtures/configuration.panel.text.json b/plugins/main/test/cypress/cypress/fixtures/configuration.panel.text.json index 56beefca4b..5cdd06b52a 100644 --- a/plugins/main/test/cypress/cypress/fixtures/configuration.panel.text.json +++ b/plugins/main/test/cypress/cypress/fixtures/configuration.panel.text.json @@ -218,4 +218,4 @@ ] } ] -} \ No newline at end of file +}