From a9ff8512f0c756ae1d4bdb2de21e14ffcf6cf4cf Mon Sep 17 00:00:00 2001 From: Ian Yenien Serrano <63758389+yenienserrano@users.noreply.github.com> Date: Fri, 26 Apr 2024 14:12:57 -0300 Subject: [PATCH] Remove discover implement embeddable dashboard on aws module (#6494) * Migrated visualization to embeddables * Remove old visualizations aws * Remove overview-aws imports * Add Date Picker * Add aws agent dashboard * Remove old aws agent dashboard * revert * Revert "Remove overview-aws imports" This reverts commit fd0a62c2b5fcf20abe056287136a2e997b2d0a70. * Revert "Remove old aws agent dashboard" This reverts commit 357bae12564b7ca2b5c8efa2c9febdf1e6d73f0b. * Remove prop unnecessary * Change legend position * Add loading spinner, no result, sample data warning * feat(aws): use data source on Dashboard and Events tabs * render of overview or agent dashboard * Add unsubscribe use-data-source * Fix DiscoverNoResults render with date change * Change imports * Update dashboard.tsx * Removed unnecessary aws in tabFilters in common-data.js * Conditional rendering sampledatawarning * Conditional rendering sampledatawarning * Update styles.scss --- plugins/main/common/constants.ts | 1 + .../data-source/hooks/use-data-source.ts | 11 +- .../alerts-aws/alerts-aws-data-source.ts | 24 + .../pattern/alerts/alerts-aws/index.ts | 1 + .../data-source/pattern/alerts/index.ts | 1 + .../common/modules/modules-defaults.tsx | 14 +- .../dashboards/dashboard.tsx | 140 ++ .../dashboards/dashboard_panels.ts | 1357 +++++++++++++++++ .../amazon-web-services/dashboards/index.tsx | 1 + .../dashboards/styles.scss | 10 + plugins/main/public/services/common-data.js | 1 - 11 files changed, 1553 insertions(+), 8 deletions(-) create mode 100644 plugins/main/public/components/common/data-source/pattern/alerts/alerts-aws/alerts-aws-data-source.ts create mode 100644 plugins/main/public/components/common/data-source/pattern/alerts/alerts-aws/index.ts create mode 100644 plugins/main/public/components/overview/amazon-web-services/dashboards/dashboard.tsx create mode 100644 plugins/main/public/components/overview/amazon-web-services/dashboards/dashboard_panels.ts create mode 100644 plugins/main/public/components/overview/amazon-web-services/dashboards/index.tsx create mode 100644 plugins/main/public/components/overview/amazon-web-services/dashboards/styles.scss diff --git a/plugins/main/common/constants.ts b/plugins/main/common/constants.ts index 5f42dc9f66..a4b0f151bb 100644 --- a/plugins/main/common/constants.ts +++ b/plugins/main/common/constants.ts @@ -233,6 +233,7 @@ export const DATA_SOURCE_FILTER_CONTROLLED_MITRE_ATTACK_RULE_ID = 'hidden-mitre-attack-rule-id'; export const DATA_SOURCE_FILTER_CONTROLLED_VIRUSTOTAL_RULE_GROUP = 'virustotal-rule-group'; +export const DATA_SOURCE_FILTER_CONTROLLED_AWS_RULE_GROUP = 'aws-rule-group'; export const DATA_SOURCE_FILTER_CONTROLLED_FIM_RULE_GROUP = 'fim-rule-group'; diff --git a/plugins/main/public/components/common/data-source/hooks/use-data-source.ts b/plugins/main/public/components/common/data-source/hooks/use-data-source.ts index 86070bfcc0..e6a794aa66 100644 --- a/plugins/main/public/components/common/data-source/hooks/use-data-source.ts +++ b/plugins/main/public/components/common/data-source/hooks/use-data-source.ts @@ -83,10 +83,9 @@ export function useDataSource { - init(); - }, []); - const init = async () => { + let subscription; + (async () => { setIsLoading(true); const factory = injectedFactory || new PatternDataSourceFactory(); const patternsData = await repository.getAll(); @@ -104,7 +103,7 @@ export function useDataSource { // this is necessary to remove the hidden filters from the filter manager and not show them in the search bar dataSourceFilterManager.setFilters(dataSourceFilterManager.getFilters()); @@ -116,7 +115,9 @@ export function useDataSource subscription.unsubscribe(); + }, []); if (isLoading) { return { diff --git a/plugins/main/public/components/common/data-source/pattern/alerts/alerts-aws/alerts-aws-data-source.ts b/plugins/main/public/components/common/data-source/pattern/alerts/alerts-aws/alerts-aws-data-source.ts new file mode 100644 index 0000000000..49973c101e --- /dev/null +++ b/plugins/main/public/components/common/data-source/pattern/alerts/alerts-aws/alerts-aws-data-source.ts @@ -0,0 +1,24 @@ +import { tFilter } from '../../../index'; +import { DATA_SOURCE_FILTER_CONTROLLED_AWS_RULE_GROUP } from '../../../../../../../common/constants'; +import { AlertsDataSource } from '../alerts-data-source'; + +const AWS_GROUP_KEY = 'rule.groups'; +const AWS_GROUP_VALUE = 'amazon'; + +export class AlertsAWSDataSource extends AlertsDataSource { + constructor(id: string, title: string) { + super(id, title); + } + + getRuleGroupsFilter() { + return super.getRuleGroupsFilter( + AWS_GROUP_KEY, + AWS_GROUP_VALUE, + DATA_SOURCE_FILTER_CONTROLLED_AWS_RULE_GROUP, + ); + } + + getFixedFilters(): tFilter[] { + return [...this.getRuleGroupsFilter(), ...super.getFixedFilters()]; + } +} diff --git a/plugins/main/public/components/common/data-source/pattern/alerts/alerts-aws/index.ts b/plugins/main/public/components/common/data-source/pattern/alerts/alerts-aws/index.ts new file mode 100644 index 0000000000..1cfbf7114c --- /dev/null +++ b/plugins/main/public/components/common/data-source/pattern/alerts/alerts-aws/index.ts @@ -0,0 +1 @@ +export * from './alerts-aws-data-source'; diff --git a/plugins/main/public/components/common/data-source/pattern/alerts/index.ts b/plugins/main/public/components/common/data-source/pattern/alerts/index.ts index 643879e873..3208daf2cc 100644 --- a/plugins/main/public/components/common/data-source/pattern/alerts/index.ts +++ b/plugins/main/public/components/common/data-source/pattern/alerts/index.ts @@ -1,6 +1,7 @@ export * from './alerts-fim'; export * from './alerts-data-source-repository'; export * from './alerts-data-source'; +export * from './alerts-aws'; export * from './vulnerabilities'; export * from './mitre-attack'; export * from './virustotal'; diff --git a/plugins/main/public/components/common/modules/modules-defaults.tsx b/plugins/main/public/components/common/modules/modules-defaults.tsx index 2eb2ba619f..2a033f7e90 100644 --- a/plugins/main/public/components/common/modules/modules-defaults.tsx +++ b/plugins/main/public/components/common/modules/modules-defaults.tsx @@ -11,6 +11,7 @@ */ import { Dashboard } from './dashboard'; import { MainSca } from '../../agents/sca'; +import { DashboardAWS } from '../../overview/amazon-web-services/dashboards'; import { MainMitre } from './main-mitre'; import { ModuleMitreAttackIntelligence } from '../../overview/mitre/intelligence'; import { MainFim } from '../../agents/fim'; @@ -52,6 +53,7 @@ import { MitreAttackDataSource } from '../data-source/pattern/alerts/mitre-attac import { AlertsDataSource, AlertsVulnerabilitiesDataSource, + AlertsAWSDataSource, VirusTotalDataSource, AlertsFIMDataSource, } from '../data-source'; @@ -128,8 +130,16 @@ export const ModulesDefaults = { aws: { init: 'dashboard', tabs: [ - DashboardTab, - renderDiscoverTab(DEFAULT_INDEX_PATTERN, amazonWebServicesColumns), + { + id: 'dashboard', + name: 'Dashboard', + buttons: [ButtonModuleExploreAgent, ButtonModuleGenerateReport], + component: DashboardAWS, + }, + renderDiscoverTab({ + tableColumns: amazonWebServicesColumns, + DataSource: AlertsAWSDataSource, + }), ], availableFor: ['manager', 'agent'], }, diff --git a/plugins/main/public/components/overview/amazon-web-services/dashboards/dashboard.tsx b/plugins/main/public/components/overview/amazon-web-services/dashboards/dashboard.tsx new file mode 100644 index 0000000000..e29d7609f5 --- /dev/null +++ b/plugins/main/public/components/overview/amazon-web-services/dashboards/dashboard.tsx @@ -0,0 +1,140 @@ +import React, { useEffect, useState } from 'react'; +import useSearchBar from '../../../common/search-bar/use-search-bar'; +import { compose } from 'redux'; +import { getPlugins } from '../../../../kibana-services'; +import { ViewMode } from '../../../../../../../src/plugins/embeddable/public'; +import { getDashboardPanels } from './dashboard_panels'; +import { I18nProvider } from '@osd/i18n/react'; +import { SearchResponse } from '../../../../../../../src/core/server'; +import './styles.scss'; +import { withErrorBoundary } from '../../../common/hocs'; +import { IndexPattern } from '../../../../../../../src/plugins/data/common'; +import { SampleDataWarning } from '../../../visualize/components'; +import { + ErrorFactory, + ErrorHandler, + HttpError, +} from '../../../../react-services/error-management'; +import { + AlertsDataSourceRepository, + PatternDataSource, + tParsedIndexPattern, + useDataSource, + AlertsAWSDataSource, +} from '../../../common/data-source'; +import { DiscoverNoResults } from '../../../common/no-results/no-results'; +import { LoadingSpinner } from '../../../common/loading-spinner/loading-spinner'; + +const plugins = getPlugins(); + +const SearchBar = getPlugins().data.ui.SearchBar; + +const DashboardByRenderer = plugins.dashboard.DashboardContainerByValueRenderer; + +const DashboardAWSComponents: React.FC = ({}) => { + const { + filters, + dataSource, + fetchFilters, + isLoading: isDataSourceLoading, + fetchData, + setFilters, + } = useDataSource({ + DataSource: AlertsAWSDataSource, + repository: new AlertsDataSourceRepository(), + }); + + const [results, setResults] = useState({} as SearchResponse); + + const { searchBarProps } = useSearchBar({ + indexPattern: dataSource?.indexPattern as IndexPattern, + filters, + setFilters, + }); + + const { query, dateRangeFrom, dateRangeTo } = searchBarProps; + + useEffect(() => { + if (isDataSourceLoading) { + return; + } + fetchData({ + query, + dateRange: { + from: dateRangeFrom, + to: dateRangeTo, + }, + }) + .then(results => setResults(results)) + .catch(error => { + const searchError = ErrorFactory.create(HttpError, { + error, + message: 'Error fetching data', + }); + ErrorHandler.handleError(searchError); + }); + }, [ + JSON.stringify(fetchFilters), + JSON.stringify(query), + JSON.stringify(dateRangeFrom), + JSON.stringify(dateRangeTo), + ]); + return ( + <> + + <> + {isDataSourceLoading && !dataSource ? ( + + ) : ( +
+ +
+ )} + {dataSource && results?.hits?.total === 0 ? ( + + ) : null} + {!isDataSourceLoading && dataSource && results?.hits?.total > 0 ? ( + <> + +
+ +
+ + ) : null} + +
+ + ); +}; + +export const DashboardAWS = compose(withErrorBoundary)(DashboardAWSComponents); diff --git a/plugins/main/public/components/overview/amazon-web-services/dashboards/dashboard_panels.ts b/plugins/main/public/components/overview/amazon-web-services/dashboards/dashboard_panels.ts new file mode 100644 index 0000000000..c0336021ce --- /dev/null +++ b/plugins/main/public/components/overview/amazon-web-services/dashboards/dashboard_panels.ts @@ -0,0 +1,1357 @@ +import { DashboardPanelState } from '../../../../../../../../src/plugins/dashboard/public/application'; +import { EmbeddableInput } from '../../../../../../../../src/plugins/embeddable/public'; + +// Overview + +const getVisStateTopSources = (indexPatternId: string) => { + return { + id: 'aws_overview_top_sources', + title: 'Sources', + type: 'pie', + params: { + type: 'pie', + addTooltip: true, + addLegend: true, + legendPosition: 'right', + isDonut: true, + labels: { + show: false, + values: true, + last_level: true, + truncate: 100, + }, + }, + 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: 'data.aws.source', + size: 5, + order: 'desc', + orderBy: '1', + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + }, + }, + ], + }, + }; +}; + +const getVisStateTopAccounts = (indexPatternId: string) => { + return { + id: 'aws_overview_top_accounts', + title: 'Accounts', + type: 'pie', + params: { + type: 'pie', + addTooltip: true, + addLegend: true, + legendPosition: 'right', + isDonut: true, + labels: { + show: false, + values: true, + last_level: true, + truncate: 100, + }, + }, + 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: 'data.aws.accountId', + size: 5, + order: 'desc', + orderBy: '1', + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + }, + }, + ], + }, + }; +}; + +const getVisStateTopBuckets = (indexPatternId: string) => { + return { + id: 'aws_overview_top_buckets', + title: 'Buckets', + type: 'pie', + params: { + type: 'pie', + addTooltip: true, + addLegend: true, + legendPosition: 'right', + isDonut: true, + labels: { + show: false, + values: true, + last_level: true, + truncate: 100, + }, + }, + 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: 'data.aws.log_info.s3bucket', + size: 5, + order: 'desc', + orderBy: '1', + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + }, + }, + ], + }, + }; +}; + +const getVisStateRegions = (indexPatternId: string) => { + return { + id: 'aws_overview_regions', + title: 'Regions', + type: 'pie', + params: { + type: 'pie', + addTooltip: true, + addLegend: true, + legendPosition: 'right', + isDonut: true, + labels: { + show: false, + values: true, + last_level: true, + truncate: 100, + }, + }, + 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: 'data.aws.region', + size: 5, + order: 'desc', + orderBy: '1', + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + }, + }, + ], + }, + }; +}; + +const getVisStateEventsBySource = (indexPatternId: string) => { + return { + id: 'aws_overview_events_by_source', + title: 'Events by source over time', + type: 'area', + params: { + type: 'area', + grid: { + categoryLines: true, + style: { color: '#eee' }, + valueAxis: 'ValueAxis-1', + }, + categoryAxes: [ + { + id: 'CategoryAxis-1', + type: 'category', + position: 'bottom', + show: true, + style: {}, + scale: { type: 'linear' }, + labels: { show: true, filter: true, truncate: 100 }, + title: {}, + }, + ], + valueAxes: [ + { + id: 'ValueAxis-1', + name: 'LeftAxis-1', + type: 'value', + position: 'left', + show: true, + style: {}, + scale: { type: 'linear', mode: 'normal' }, + labels: { show: true, rotate: 0, filter: false, truncate: 100 }, + title: { text: 'Count' }, + }, + ], + seriesParams: [ + { + show: 'true', + type: 'area', + mode: 'stacked', + data: { label: 'Count', id: '1' }, + drawLinesBetweenPoints: true, + showCircles: true, + interpolate: 'cardinal', + valueAxis: 'ValueAxis-1', + }, + ], + addTooltip: true, + addLegend: true, + legendPosition: 'right', + times: [], + addTimeMarker: false, + }, + 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: 'data.aws.source', + size: 5, + order: 'desc', + orderBy: '1', + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + }, + }, + { + id: '2', + enabled: true, + type: 'date_histogram', + schema: 'segment', + params: { + field: 'timestamp', + timeRange: { from: 'now-24h', to: 'now', mode: 'quick' }, + useNormalizedEsInterval: true, + interval: 'auto', + time_zone: 'Europe/Berlin', + drop_partials: false, + customInterval: '2h', + min_doc_count: 1, + extended_bounds: {}, + }, + }, + ], + }, + }; +}; + +const getVisStateEventsByBucket = (indexPatternId: string) => { + return { + id: 'aws_overview_events_by_bucket', + title: 'Events by S3 bucket over time', + type: 'area', + params: { + type: 'area', + grid: { + categoryLines: true, + style: { color: '#eee' }, + valueAxis: 'ValueAxis-1', + }, + categoryAxes: [ + { + id: 'CategoryAxis-1', + type: 'category', + position: 'bottom', + show: true, + style: {}, + scale: { type: 'linear' }, + labels: { show: true, filter: true, truncate: 100 }, + title: {}, + }, + ], + valueAxes: [ + { + id: 'ValueAxis-1', + name: 'LeftAxis-1', + type: 'value', + position: 'left', + show: true, + style: {}, + scale: { type: 'linear', mode: 'normal' }, + labels: { show: true, rotate: 0, filter: false, truncate: 100 }, + title: { text: 'Count' }, + }, + ], + seriesParams: [ + { + show: 'true', + type: 'area', + mode: 'stacked', + data: { label: 'Count', id: '1' }, + drawLinesBetweenPoints: true, + showCircles: true, + interpolate: 'cardinal', + valueAxis: 'ValueAxis-1', + }, + ], + addTooltip: true, + addLegend: true, + legendPosition: 'right', + times: [], + addTimeMarker: false, + }, + 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: 'data.aws.log_info.s3bucket', + size: 5, + order: 'desc', + orderBy: '1', + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + }, + }, + { + id: '2', + enabled: true, + type: 'date_histogram', + schema: 'segment', + params: { + field: 'timestamp', + timeRange: { from: 'now-24h', to: 'now', mode: 'quick' }, + useNormalizedEsInterval: true, + interval: 'auto', + time_zone: 'Europe/Berlin', + drop_partials: false, + customInterval: '2h', + min_doc_count: 1, + extended_bounds: {}, + }, + }, + ], + }, + }; +}; + +const getVisStateGeolocationMap = (indexPatternId: string) => { + return { + id: 'aws_overview_geolocation_map', + title: 'Geolocation map', + type: 'tile_map', + params: { + colorSchema: 'Green to Red', + mapType: 'Scaled Circle Markers', + isDesaturated: false, + addTooltip: true, + heatClusterSize: 1.5, + legendPosition: 'bottomright', + mapZoom: 1, + mapCenter: [0, 0], + wms: { + enabled: false, + options: { format: 'image/png', transparent: true }, + }, + dimensions: { + metric: { + accessor: 1, + format: { id: 'number' }, + params: {}, + aggType: 'count', + }, + geohash: { + accessor: 0, + format: { id: 'string' }, + params: { precision: 2, useGeocentroid: true }, + aggType: 'geohash_grid', + }, + geocentroid: { + accessor: 2, + format: { id: 'string' }, + params: {}, + aggType: 'geo_centroid', + }, + }, + }, + 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: 'geohash_grid', + schema: 'segment', + params: { + field: 'GeoLocation.location', + autoPrecision: true, + precision: 2, + useGeocentroid: true, + isFilteredByCollar: true, + mapZoom: 1, + mapCenter: [0, 0], + }, + }, + ], + }, + }; +}; + +// Agent + +const getVisStateAgentTopSources = (indexPatternId: string) => { + return { + id: 'aws_agent_top_sources', + title: 'Sources', + type: 'pie', + params: { + type: 'pie', + addTooltip: true, + addLegend: true, + legendPosition: 'right', + isDonut: true, + labels: { + show: false, + values: true, + last_level: true, + truncate: 100, + }, + }, + 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: 'data.aws.source', + size: 5, + order: 'desc', + orderBy: '1', + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + }, + }, + ], + }, + }; +}; + +const getVisStateAgentTopAccounts = (indexPatternId: string) => { + return { + id: 'aws_agent_top_accounts', + title: 'Accounts', + type: 'pie', + params: { + type: 'pie', + addTooltip: true, + addLegend: true, + legendPosition: 'right', + isDonut: true, + labels: { + show: false, + values: true, + last_level: true, + truncate: 100, + }, + }, + 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: 'data.aws.accountId', + size: 5, + order: 'desc', + orderBy: '1', + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + }, + }, + ], + }, + }; +}; + +const getVisStateAgentTopBuckets = (indexPatternId: string) => { + return { + id: 'aws_agent_top_buckets', + title: 'Buckets', + type: 'pie', + params: { + type: 'pie', + addTooltip: true, + addLegend: true, + legendPosition: 'right', + isDonut: true, + labels: { + show: false, + values: true, + last_level: true, + truncate: 100, + }, + }, + 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: 'data.aws.log_info.s3bucket', + size: 5, + order: 'desc', + orderBy: '1', + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + }, + }, + ], + }, + }; +}; + +const getVisStateAgentRegions = (indexPatternId: string) => { + return { + id: 'aws_agent_regions', + title: 'Regions', + type: 'pie', + params: { + type: 'pie', + addTooltip: true, + addLegend: true, + legendPosition: 'right', + isDonut: true, + labels: { + show: false, + values: true, + last_level: true, + truncate: 100, + }, + }, + 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: 'data.aws.region', + size: 5, + order: 'desc', + orderBy: '1', + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + }, + }, + ], + }, + }; +}; + +const getVisStateAgentEventsBySource = (indexPatternId: string) => { + return { + id: 'aws_agent_events_by_source', + title: 'Events by source over time', + type: 'area', + params: { + type: 'area', + grid: { + categoryLines: true, + style: { color: '#eee' }, + valueAxis: 'ValueAxis-1', + }, + categoryAxes: [ + { + id: 'CategoryAxis-1', + type: 'category', + position: 'bottom', + show: true, + style: {}, + scale: { type: 'linear' }, + labels: { show: true, filter: true, truncate: 100 }, + title: {}, + }, + ], + valueAxes: [ + { + id: 'ValueAxis-1', + name: 'LeftAxis-1', + type: 'value', + position: 'left', + show: true, + style: {}, + scale: { type: 'linear', mode: 'normal' }, + labels: { show: true, rotate: 0, filter: false, truncate: 100 }, + title: { text: 'Count' }, + }, + ], + seriesParams: [ + { + show: 'true', + type: 'area', + mode: 'stacked', + data: { label: 'Count', id: '1' }, + drawLinesBetweenPoints: true, + showCircles: true, + interpolate: 'cardinal', + valueAxis: 'ValueAxis-1', + }, + ], + addTooltip: true, + addLegend: true, + legendPosition: 'left', + times: [], + addTimeMarker: 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: '3', + enabled: true, + type: 'terms', + schema: 'group', + params: { + field: 'data.aws.source', + size: 5, + order: 'desc', + orderBy: '1', + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + }, + }, + { + id: '2', + enabled: true, + type: 'date_histogram', + schema: 'segment', + params: { + field: 'timestamp', + timeRange: { from: 'now-24h', to: 'now', mode: 'quick' }, + useNormalizedEsInterval: true, + interval: 'auto', + time_zone: 'Europe/Berlin', + drop_partials: false, + customInterval: '2h', + min_doc_count: 1, + extended_bounds: {}, + }, + }, + ], + }, + }; +}; + +const getVisStateAgentEventsByBucket = (indexPatternId: string) => { + return { + id: 'aws_agent_events_by_bucket', + title: 'Events by S3 bucket over time', + type: 'area', + params: { + type: 'area', + grid: { + categoryLines: true, + style: { color: '#eee' }, + valueAxis: 'ValueAxis-1', + }, + categoryAxes: [ + { + id: 'CategoryAxis-1', + type: 'category', + position: 'bottom', + show: true, + style: {}, + scale: { type: 'linear' }, + labels: { show: true, filter: true, truncate: 100 }, + title: {}, + }, + ], + valueAxes: [ + { + id: 'ValueAxis-1', + name: 'LeftAxis-1', + type: 'value', + position: 'left', + show: true, + style: {}, + scale: { type: 'linear', mode: 'normal' }, + labels: { show: true, rotate: 0, filter: false, truncate: 100 }, + title: { text: 'Count' }, + }, + ], + seriesParams: [ + { + show: 'true', + type: 'area', + mode: 'stacked', + data: { label: 'Count', id: '1' }, + drawLinesBetweenPoints: true, + showCircles: true, + interpolate: 'cardinal', + valueAxis: 'ValueAxis-1', + }, + ], + addTooltip: true, + addLegend: true, + legendPosition: 'right', + times: [], + addTimeMarker: false, + }, + 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: 'data.aws.log_info.s3bucket', + size: 5, + order: 'desc', + orderBy: '1', + otherBucket: false, + otherBucketLabel: 'Other', + missingBucket: false, + missingBucketLabel: 'Missing', + }, + }, + { + id: '2', + enabled: true, + type: 'date_histogram', + schema: 'segment', + params: { + field: 'timestamp', + timeRange: { from: 'now-24h', to: 'now', mode: 'quick' }, + useNormalizedEsInterval: true, + interval: 'auto', + time_zone: 'Europe/Berlin', + drop_partials: false, + customInterval: '2h', + min_doc_count: 1, + extended_bounds: {}, + }, + }, + ], + }, + }; +}; + +const getVisStateAgentGeolocationMap = (indexPatternId: string) => { + return { + id: 'aws_agent_geolocation_map', + title: 'Geolocation map', + type: 'tile_map', + params: { + colorSchema: 'Green to Red', + mapType: 'Scaled Circle Markers', + isDesaturated: false, + addTooltip: true, + heatClusterSize: 1.5, + legendPosition: 'bottomright', + mapZoom: 1, + mapCenter: [0, 0], + wms: { + enabled: false, + options: { format: 'image/png', transparent: true }, + }, + dimensions: { + metric: { + accessor: 1, + format: { id: 'number' }, + params: {}, + aggType: 'count', + }, + geohash: { + accessor: 0, + format: { id: 'string' }, + params: { precision: 2, useGeocentroid: true }, + aggType: 'geohash_grid', + }, + geocentroid: { + accessor: 2, + format: { id: 'string' }, + params: {}, + aggType: 'geo_centroid', + }, + }, + }, + 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: 'geohash_grid', + schema: 'segment', + params: { + field: 'GeoLocation.location', + autoPrecision: true, + precision: 2, + useGeocentroid: true, + isFilteredByCollar: true, + mapZoom: 1, + mapCenter: [0, 0], + }, + }, + ], + }, + }; +}; + +export const getDashboardPanels = ( + indexPatternId: string, + isPinnedAgent: boolean, +): { + [panelId: string]: DashboardPanelState< + EmbeddableInput & { [k: string]: unknown } + >; +} => { + const overviewDashboardPanels = { + g1: { + gridData: { + w: 12, + h: 9, + x: 0, + y: 0, + i: 'g1', + }, + type: 'visualization', + explicitInput: { + id: 'g1', + savedVis: getVisStateTopSources(indexPatternId), + }, + }, + g2: { + gridData: { + w: 12, + h: 9, + x: 12, + y: 0, + i: 'g2', + }, + type: 'visualization', + explicitInput: { + id: 'g2', + savedVis: getVisStateTopAccounts(indexPatternId), + }, + }, + g3: { + gridData: { + w: 12, + h: 9, + x: 24, + y: 0, + i: 'g3', + }, + type: 'visualization', + explicitInput: { + id: 'g3', + savedVis: getVisStateTopBuckets(indexPatternId), + }, + }, + g4: { + gridData: { + w: 12, + h: 9, + x: 36, + y: 0, + i: 'g4', + }, + type: 'visualization', + explicitInput: { + id: 'g4', + savedVis: getVisStateRegions(indexPatternId), + }, + }, + g5: { + gridData: { + w: 24, + h: 12, + x: 0, + y: 9, + i: 'g5', + }, + type: 'visualization', + explicitInput: { + id: 'g5', + savedVis: getVisStateEventsBySource(indexPatternId), + }, + }, + g6: { + gridData: { + w: 24, + h: 12, + x: 24, + y: 9, + i: 'g6', + }, + type: 'visualization', + explicitInput: { + id: 'g6', + savedVis: getVisStateEventsByBucket(indexPatternId), + }, + }, + g7: { + gridData: { + w: 48, + h: 20, + x: 0, + y: 21, + i: 'g7', + }, + type: 'visualization', + explicitInput: { + id: 'g7', + savedVis: getVisStateGeolocationMap(indexPatternId), + }, + }, + }; + + const agentDashboardPanels = { + a1: { + gridData: { + w: 12, + h: 9, + x: 0, + y: 0, + i: 'a1', + }, + type: 'visualization', + explicitInput: { + id: 'a1', + savedVis: getVisStateAgentTopSources(indexPatternId), + }, + }, + a2: { + gridData: { + w: 12, + h: 9, + x: 12, + y: 0, + i: 'a2', + }, + type: 'visualization', + explicitInput: { + id: 'a2', + savedVis: getVisStateAgentTopAccounts(indexPatternId), + }, + }, + a3: { + gridData: { + w: 12, + h: 9, + x: 24, + y: 0, + i: 'a3', + }, + type: 'visualization', + explicitInput: { + id: 'a3', + savedVis: getVisStateAgentTopBuckets(indexPatternId), + }, + }, + a4: { + gridData: { + w: 12, + h: 9, + x: 36, + y: 0, + i: 'a4', + }, + type: 'visualization', + explicitInput: { + id: 'a4', + savedVis: getVisStateAgentRegions(indexPatternId), + }, + }, + a5: { + gridData: { + w: 24, + h: 12, + x: 0, + y: 9, + i: 'a5', + }, + type: 'visualization', + explicitInput: { + id: 'a5', + savedVis: getVisStateAgentEventsBySource(indexPatternId), + }, + }, + a6: { + gridData: { + w: 24, + h: 12, + x: 24, + y: 9, + i: 'a6', + }, + type: 'visualization', + explicitInput: { + id: 'a6', + savedVis: getVisStateAgentEventsByBucket(indexPatternId), + }, + }, + a7: { + gridData: { + w: 48, + h: 20, + x: 0, + y: 21, + i: 'a7', + }, + type: 'visualization', + explicitInput: { + id: 'a7', + savedVis: getVisStateAgentGeolocationMap(indexPatternId), + }, + }, + }; + + return isPinnedAgent ? agentDashboardPanels : overviewDashboardPanels; +}; diff --git a/plugins/main/public/components/overview/amazon-web-services/dashboards/index.tsx b/plugins/main/public/components/overview/amazon-web-services/dashboards/index.tsx new file mode 100644 index 0000000000..b58b6c9229 --- /dev/null +++ b/plugins/main/public/components/overview/amazon-web-services/dashboards/index.tsx @@ -0,0 +1 @@ +export * from './dashboard'; diff --git a/plugins/main/public/components/overview/amazon-web-services/dashboards/styles.scss b/plugins/main/public/components/overview/amazon-web-services/dashboards/styles.scss new file mode 100644 index 0000000000..18697c1dce --- /dev/null +++ b/plugins/main/public/components/overview/amazon-web-services/dashboards/styles.scss @@ -0,0 +1,10 @@ +.aws-dashboard-responsive { + @media (max-width: 767px) { + .react-grid-layout { + height: auto !important; + } + .dshLayout-isMaximizedPanel { + height: 100% !important; + } + } +} diff --git a/plugins/main/public/services/common-data.js b/plugins/main/public/services/common-data.js index 722ff4ddf4..f581075dce 100644 --- a/plugins/main/public/services/common-data.js +++ b/plugins/main/public/services/common-data.js @@ -139,7 +139,6 @@ export class CommonData { hipaa: { group: 'hipaa' }, nist: { group: 'nist' }, tsc: { group: 'tsc' }, - aws: { group: 'amazon' }, gcp: { group: 'gcp' }, office: { group: 'office365' }, osquery: { group: 'osquery' },