diff --git a/public/pages/Correlations/components/CorrelationGraph.tsx b/public/pages/Correlations/components/CorrelationGraph.tsx
index ec6a836ee..4de34e6fc 100644
--- a/public/pages/Correlations/components/CorrelationGraph.tsx
+++ b/public/pages/Correlations/components/CorrelationGraph.tsx
@@ -37,7 +37,7 @@ export const CorrelationGraph: React.FC = ({
graph={{ nodes, edges }}
options={options}
events={events}
- style={{ border: '1px solid', backgroundColor: '#ffffff' }}
+ style={{ backgroundColor: '#ffffff' }}
getNetwork={getNetwork}
/>
);
diff --git a/public/pages/Correlations/components/ExperimentalBanner.tsx b/public/pages/Correlations/components/ExperimentalBanner.tsx
index 9c24a8f23..03c98dd81 100644
--- a/public/pages/Correlations/components/ExperimentalBanner.tsx
+++ b/public/pages/Correlations/components/ExperimentalBanner.tsx
@@ -14,15 +14,16 @@ export const CorrelationsExperimentalBanner = () => {
The feature is experimental and should not be used in a production environment. While we
are working on the finishing touches, share your ideas and feedback on
- forum.opensearch.org.
+ forum.opensearch.org
- For more information see
+ . For more information see
- Security Analytics Documentation.
+ Security Analytics Documentation
+ .
diff --git a/public/pages/Correlations/components/FilterGroup.tsx b/public/pages/Correlations/components/FilterGroup.tsx
index 5cb3defc7..b71a15eaa 100644
--- a/public/pages/Correlations/components/FilterGroup.tsx
+++ b/public/pages/Correlations/components/FilterGroup.tsx
@@ -23,6 +23,7 @@ export interface LogTypeFilterGroupProps {
export const FilterGroup: React.FC = ({ groupName, items, setItems }) => {
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
+ const [showActiveFilters, setShowActiveFilters] = useState(false);
const onButtonClick = () => {
setIsPopoverOpen(!isPopoverOpen);
@@ -55,6 +56,7 @@ export const FilterGroup: React.FC = ({ groupName, item
}
setItems(newItems);
+ setShowActiveFilters(true);
}
const button = (
@@ -62,9 +64,10 @@ export const FilterGroup: React.FC = ({ groupName, item
iconType="arrowDown"
onClick={onButtonClick}
isSelected={isPopoverOpen}
- numFilters={items.length}
- hasActiveFilters={!!items.find((item) => item.checked === 'on')}
- numActiveFilters={items.filter((item) => item.checked === 'on').length}
+ hasActiveFilters={showActiveFilters && !!items.find((item) => item.checked === 'on')}
+ numActiveFilters={
+ showActiveFilters ? items.filter((item) => item.checked === 'on').length : undefined
+ }
>
{groupName}
diff --git a/public/pages/Correlations/components/FindingCard.tsx b/public/pages/Correlations/components/FindingCard.tsx
index e3404c9ef..6e597606d 100644
--- a/public/pages/Correlations/components/FindingCard.tsx
+++ b/public/pages/Correlations/components/FindingCard.tsx
@@ -3,7 +3,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
-import React, { useCallback } from 'react';
+import React from 'react';
import {
EuiPanel,
EuiFlexGroup,
@@ -14,8 +14,8 @@ import {
EuiBadge,
EuiHorizontalRule,
EuiToolTip,
+ EuiDescriptionList,
} from '@elastic/eui';
-import { rulePriorityBySeverity } from '../../CreateDetector/components/DefineDetector/components/DetectionRules/DetectionRulesTable';
import {
getAbbrFromLogType,
getSeverityLabel,
@@ -32,7 +32,7 @@ export interface FindingCardProps {
detectionRule: { name: string; severity: string };
correlationData?: {
// ruleName: string;
- score: number;
+ score: string;
onInspect: (findingId: string, logType: string) => void;
};
finding: CorrelationFinding;
@@ -76,24 +76,22 @@ export const FindingCard: React.FC = ({
>
) : null;
- const createTextRow = useCallback((label: string, value: string) => {
- return (
-
-
- {label}
-
-
- {value}
-
-
- );
- }, []);
+ const list = [
+ {
+ title: 'Generated',
+ description: timestamp,
+ },
+ {
+ title: 'Detection rule',
+ description: detectionRule.name,
+ },
+ ];
return (
{correlationHeader}
-
+
= ({
fontSize: 10,
lineHeight: '35px',
textAlign: 'center',
+ borderColor: '#98A2B3',
+ color: '#98A2B3',
}}
>
{getAbbrFromLogType(logType)}
@@ -115,10 +115,10 @@ export const FindingCard: React.FC
= ({
position: 'absolute',
transform: 'translateY(-100%)',
left: '33px',
+ color: getSeverityColor(detectionRule.severity).text,
}}
- color={getSeverityColor(detectionRule.severity)}
+ color={getSeverityColor(detectionRule.severity).background}
>
- {rulePriorityBySeverity[detectionRule.severity]}{' '}
{getSeverityLabel(detectionRule.severity)}
) : null}
@@ -142,8 +142,7 @@ export const FindingCard: React.FC = ({
{correlationHeader ? : null}
- {createTextRow('Generated', timestamp)}
- {createTextRow('Detection rule', detectionRule.name)}
+
);
};
diff --git a/public/pages/Correlations/containers/CorrelationsContainer.tsx b/public/pages/Correlations/containers/CorrelationsContainer.tsx
index 22cab1abc..425f5b416 100644
--- a/public/pages/Correlations/containers/CorrelationsContainer.tsx
+++ b/public/pages/Correlations/containers/CorrelationsContainer.tsx
@@ -32,6 +32,7 @@ import {
EuiEmptyPrompt,
EuiButton,
EuiBadge,
+ EuiFilterGroup,
} from '@elastic/eui';
import { CorrelationsExperimentalBanner } from '../components/ExperimentalBanner';
import { FilterItem, FilterGroup } from '../components/FilterGroup';
@@ -251,6 +252,8 @@ export class Correlations extends React.Component${getAbbrFromLogType(
@@ -259,7 +262,15 @@ export class Correlations extends React.Component {
+ const { text, background } = getSeverityColor(detectionRule.severity);
const tooltipContent = (
-
+
{getSeverityLabel(detectionRule.severity)}
@@ -457,7 +471,7 @@ export class Correlations extends React.Component
-
-
-
-
+
-
+
+
+
+
Reset filters
@@ -529,7 +543,7 @@ export class Correlations extends React.Component (
- {sev.value}
+ {sev.value}
))}
diff --git a/public/pages/Correlations/utils/constants.tsx b/public/pages/Correlations/utils/constants.tsx
index e51b09aa9..0b95f4f44 100644
--- a/public/pages/Correlations/utils/constants.tsx
+++ b/public/pages/Correlations/utils/constants.tsx
@@ -62,7 +62,7 @@ export const defaultSeverityFilterItemOptions: FilterItem[] = Object.values(rule
return {
name: (
- {`${sev.priority} ${sev.name}`}
+ {`${sev.name}`}
),
id: sev.value,
@@ -92,5 +92,10 @@ export const getSeverityLabel = (sev: string) => {
};
export const getSeverityColor = (sev: string) => {
- return ruleSeverity.find((severity) => severity.value === sev)?.color || 'black';
+ return (
+ ruleSeverity.find((severity) => severity.value === sev.toLowerCase())?.color || {
+ background: 'white',
+ text: 'black',
+ }
+ );
};
diff --git a/public/pages/Correlations/utils/helpers.tsx b/public/pages/Correlations/utils/helpers.tsx
index f8b4a13c1..b06d07ecf 100644
--- a/public/pages/Correlations/utils/helpers.tsx
+++ b/public/pages/Correlations/utils/helpers.tsx
@@ -14,6 +14,7 @@ import {
import { Search } from '@opensearch-project/oui/src/eui_components/basic_table';
import { ruleTypes } from '../../Rules/utils/constants';
import { FieldClause } from '@opensearch-project/oui/src/eui_components/search_bar/query/ast';
+import { formatRuleType } from '../../../utils/helpers';
export const getCorrelationRulesTableColumns = (
onRuleNameClick: (rule: CorrelationRule) => void,
@@ -32,7 +33,9 @@ export const getCorrelationRulesTableColumns = (
{
name: 'Log types',
render: (ruleItem: CorrelationRule) => {
- const badges = [...new Set(ruleItem.queries?.map((query) => query.logType))];
+ const badges = [
+ ...new Set(ruleItem.queries?.map((query) => formatRuleType(query.logType))),
+ ];
return (
<>
{badges.map((badge) => (
@@ -78,7 +81,7 @@ export const getCorrelationRulesTableSearchConfig = (
): Search => {
return {
box: {
- placeholder: 'Search by rule name, log type?',
+ placeholder: 'Search by rule name, log type',
},
onChange: (args: ArgsWithQuery | ArgsWithError) => {
if (!args.error) {
diff --git a/public/pages/Detectors/components/DetectorRulesView/__snapshots__/DetectorRulesView.test.tsx.snap b/public/pages/Detectors/components/DetectorRulesView/__snapshots__/DetectorRulesView.test.tsx.snap
index a4866d062..7ef9d7164 100644
--- a/public/pages/Detectors/components/DetectorRulesView/__snapshots__/DetectorRulesView.test.tsx.snap
+++ b/public/pages/Detectors/components/DetectorRulesView/__snapshots__/DetectorRulesView.test.tsx.snap
@@ -479,31 +479,46 @@ exports[` spec renders the component 1`] = `
"name": "Rule severity",
"options": Array [
Object {
- "color": "#cc5642",
+ "color": Object {
+ "background": "#cc5642",
+ "text": "white",
+ },
"name": "Critical",
"priority": "1",
"value": "critical",
},
Object {
- "color": "#e7664c",
+ "color": Object {
+ "background": "#e7664c",
+ "text": "black",
+ },
"name": "High",
"priority": "2",
"value": "high",
},
Object {
- "color": "#d6bf57",
+ "color": Object {
+ "background": "#d6bf57",
+ "text": "black",
+ },
"name": "Medium",
"priority": "3",
"value": "medium",
},
Object {
- "color": "#54b399",
+ "color": Object {
+ "background": "#54b399",
+ "text": "black",
+ },
"name": "Low",
"priority": "4",
"value": "low",
},
Object {
- "color": "#209280",
+ "color": Object {
+ "background": "#209280",
+ "text": "white",
+ },
"name": "Informational",
"priority": "5",
"value": "informational",
@@ -626,31 +641,46 @@ exports[` spec renders the component 1`] = `
"name": "Rule severity",
"options": Array [
Object {
- "color": "#cc5642",
+ "color": Object {
+ "background": "#cc5642",
+ "text": "white",
+ },
"name": "Critical",
"priority": "1",
"value": "critical",
},
Object {
- "color": "#e7664c",
+ "color": Object {
+ "background": "#e7664c",
+ "text": "black",
+ },
"name": "High",
"priority": "2",
"value": "high",
},
Object {
- "color": "#d6bf57",
+ "color": Object {
+ "background": "#d6bf57",
+ "text": "black",
+ },
"name": "Medium",
"priority": "3",
"value": "medium",
},
Object {
- "color": "#54b399",
+ "color": Object {
+ "background": "#54b399",
+ "text": "black",
+ },
"name": "Low",
"priority": "4",
"value": "low",
},
Object {
- "color": "#209280",
+ "color": Object {
+ "background": "#209280",
+ "text": "white",
+ },
"name": "Informational",
"priority": "5",
"value": "informational",
@@ -845,31 +875,46 @@ exports[` spec renders the component 1`] = `
"name": "Rule severity",
"options": Array [
Object {
- "color": "#cc5642",
+ "color": Object {
+ "background": "#cc5642",
+ "text": "white",
+ },
"name": "Critical",
"priority": "1",
"value": "critical",
},
Object {
- "color": "#e7664c",
+ "color": Object {
+ "background": "#e7664c",
+ "text": "black",
+ },
"name": "High",
"priority": "2",
"value": "high",
},
Object {
- "color": "#d6bf57",
+ "color": Object {
+ "background": "#d6bf57",
+ "text": "black",
+ },
"name": "Medium",
"priority": "3",
"value": "medium",
},
Object {
- "color": "#54b399",
+ "color": Object {
+ "background": "#54b399",
+ "text": "black",
+ },
"name": "Low",
"priority": "4",
"value": "low",
},
Object {
- "color": "#209280",
+ "color": Object {
+ "background": "#209280",
+ "text": "white",
+ },
"name": "Informational",
"priority": "5",
"value": "informational",
@@ -1108,31 +1153,46 @@ exports[` spec renders the component 1`] = `
"name": "Rule severity",
"options": Array [
Object {
- "color": "#cc5642",
+ "color": Object {
+ "background": "#cc5642",
+ "text": "white",
+ },
"name": "Critical",
"priority": "1",
"value": "critical",
},
Object {
- "color": "#e7664c",
+ "color": Object {
+ "background": "#e7664c",
+ "text": "black",
+ },
"name": "High",
"priority": "2",
"value": "high",
},
Object {
- "color": "#d6bf57",
+ "color": Object {
+ "background": "#d6bf57",
+ "text": "black",
+ },
"name": "Medium",
"priority": "3",
"value": "medium",
},
Object {
- "color": "#54b399",
+ "color": Object {
+ "background": "#54b399",
+ "text": "black",
+ },
"name": "Low",
"priority": "4",
"value": "low",
},
Object {
- "color": "#209280",
+ "color": Object {
+ "background": "#209280",
+ "text": "white",
+ },
"name": "Informational",
"priority": "5",
"value": "informational",
diff --git a/public/pages/Detectors/containers/Detector/__snapshots__/DetectorDetails.test.tsx.snap b/public/pages/Detectors/containers/Detector/__snapshots__/DetectorDetails.test.tsx.snap
index b0f21ba2a..94f391386 100644
--- a/public/pages/Detectors/containers/Detector/__snapshots__/DetectorDetails.test.tsx.snap
+++ b/public/pages/Detectors/containers/Detector/__snapshots__/DetectorDetails.test.tsx.snap
@@ -3034,31 +3034,46 @@ exports[` spec renders the component 1`] = `
"name": "Rule severity",
"options": Array [
Object {
- "color": "#cc5642",
+ "color": Object {
+ "background": "#cc5642",
+ "text": "white",
+ },
"name": "Critical",
"priority": "1",
"value": "critical",
},
Object {
- "color": "#e7664c",
+ "color": Object {
+ "background": "#e7664c",
+ "text": "black",
+ },
"name": "High",
"priority": "2",
"value": "high",
},
Object {
- "color": "#d6bf57",
+ "color": Object {
+ "background": "#d6bf57",
+ "text": "black",
+ },
"name": "Medium",
"priority": "3",
"value": "medium",
},
Object {
- "color": "#54b399",
+ "color": Object {
+ "background": "#54b399",
+ "text": "black",
+ },
"name": "Low",
"priority": "4",
"value": "low",
},
Object {
- "color": "#209280",
+ "color": Object {
+ "background": "#209280",
+ "text": "white",
+ },
"name": "Informational",
"priority": "5",
"value": "informational",
@@ -3181,31 +3196,46 @@ exports[` spec renders the component 1`] = `
"name": "Rule severity",
"options": Array [
Object {
- "color": "#cc5642",
+ "color": Object {
+ "background": "#cc5642",
+ "text": "white",
+ },
"name": "Critical",
"priority": "1",
"value": "critical",
},
Object {
- "color": "#e7664c",
+ "color": Object {
+ "background": "#e7664c",
+ "text": "black",
+ },
"name": "High",
"priority": "2",
"value": "high",
},
Object {
- "color": "#d6bf57",
+ "color": Object {
+ "background": "#d6bf57",
+ "text": "black",
+ },
"name": "Medium",
"priority": "3",
"value": "medium",
},
Object {
- "color": "#54b399",
+ "color": Object {
+ "background": "#54b399",
+ "text": "black",
+ },
"name": "Low",
"priority": "4",
"value": "low",
},
Object {
- "color": "#209280",
+ "color": Object {
+ "background": "#209280",
+ "text": "white",
+ },
"name": "Informational",
"priority": "5",
"value": "informational",
@@ -3400,31 +3430,46 @@ exports[` spec renders the component 1`] = `
"name": "Rule severity",
"options": Array [
Object {
- "color": "#cc5642",
+ "color": Object {
+ "background": "#cc5642",
+ "text": "white",
+ },
"name": "Critical",
"priority": "1",
"value": "critical",
},
Object {
- "color": "#e7664c",
+ "color": Object {
+ "background": "#e7664c",
+ "text": "black",
+ },
"name": "High",
"priority": "2",
"value": "high",
},
Object {
- "color": "#d6bf57",
+ "color": Object {
+ "background": "#d6bf57",
+ "text": "black",
+ },
"name": "Medium",
"priority": "3",
"value": "medium",
},
Object {
- "color": "#54b399",
+ "color": Object {
+ "background": "#54b399",
+ "text": "black",
+ },
"name": "Low",
"priority": "4",
"value": "low",
},
Object {
- "color": "#209280",
+ "color": Object {
+ "background": "#209280",
+ "text": "white",
+ },
"name": "Informational",
"priority": "5",
"value": "informational",
@@ -3663,31 +3708,46 @@ exports[` spec renders the component 1`] = `
"name": "Rule severity",
"options": Array [
Object {
- "color": "#cc5642",
+ "color": Object {
+ "background": "#cc5642",
+ "text": "white",
+ },
"name": "Critical",
"priority": "1",
"value": "critical",
},
Object {
- "color": "#e7664c",
+ "color": Object {
+ "background": "#e7664c",
+ "text": "black",
+ },
"name": "High",
"priority": "2",
"value": "high",
},
Object {
- "color": "#d6bf57",
+ "color": Object {
+ "background": "#d6bf57",
+ "text": "black",
+ },
"name": "Medium",
"priority": "3",
"value": "medium",
},
Object {
- "color": "#54b399",
+ "color": Object {
+ "background": "#54b399",
+ "text": "black",
+ },
"name": "Low",
"priority": "4",
"value": "low",
},
Object {
- "color": "#209280",
+ "color": Object {
+ "background": "#209280",
+ "text": "white",
+ },
"name": "Informational",
"priority": "5",
"value": "informational",
diff --git a/public/pages/Detectors/containers/DetectorDetailsView/__snapshots__/DetectorDetailsView.test.tsx.snap b/public/pages/Detectors/containers/DetectorDetailsView/__snapshots__/DetectorDetailsView.test.tsx.snap
index 6a83a71f9..c9062d0ba 100644
--- a/public/pages/Detectors/containers/DetectorDetailsView/__snapshots__/DetectorDetailsView.test.tsx.snap
+++ b/public/pages/Detectors/containers/DetectorDetailsView/__snapshots__/DetectorDetailsView.test.tsx.snap
@@ -1858,31 +1858,46 @@ exports[` spec renders the component 1`] = `
"name": "Rule severity",
"options": Array [
Object {
- "color": "#cc5642",
+ "color": Object {
+ "background": "#cc5642",
+ "text": "white",
+ },
"name": "Critical",
"priority": "1",
"value": "critical",
},
Object {
- "color": "#e7664c",
+ "color": Object {
+ "background": "#e7664c",
+ "text": "black",
+ },
"name": "High",
"priority": "2",
"value": "high",
},
Object {
- "color": "#d6bf57",
+ "color": Object {
+ "background": "#d6bf57",
+ "text": "black",
+ },
"name": "Medium",
"priority": "3",
"value": "medium",
},
Object {
- "color": "#54b399",
+ "color": Object {
+ "background": "#54b399",
+ "text": "black",
+ },
"name": "Low",
"priority": "4",
"value": "low",
},
Object {
- "color": "#209280",
+ "color": Object {
+ "background": "#209280",
+ "text": "white",
+ },
"name": "Informational",
"priority": "5",
"value": "informational",
@@ -2005,31 +2020,46 @@ exports[` spec renders the component 1`] = `
"name": "Rule severity",
"options": Array [
Object {
- "color": "#cc5642",
+ "color": Object {
+ "background": "#cc5642",
+ "text": "white",
+ },
"name": "Critical",
"priority": "1",
"value": "critical",
},
Object {
- "color": "#e7664c",
+ "color": Object {
+ "background": "#e7664c",
+ "text": "black",
+ },
"name": "High",
"priority": "2",
"value": "high",
},
Object {
- "color": "#d6bf57",
+ "color": Object {
+ "background": "#d6bf57",
+ "text": "black",
+ },
"name": "Medium",
"priority": "3",
"value": "medium",
},
Object {
- "color": "#54b399",
+ "color": Object {
+ "background": "#54b399",
+ "text": "black",
+ },
"name": "Low",
"priority": "4",
"value": "low",
},
Object {
- "color": "#209280",
+ "color": Object {
+ "background": "#209280",
+ "text": "white",
+ },
"name": "Informational",
"priority": "5",
"value": "informational",
@@ -2224,31 +2254,46 @@ exports[` spec renders the component 1`] = `
"name": "Rule severity",
"options": Array [
Object {
- "color": "#cc5642",
+ "color": Object {
+ "background": "#cc5642",
+ "text": "white",
+ },
"name": "Critical",
"priority": "1",
"value": "critical",
},
Object {
- "color": "#e7664c",
+ "color": Object {
+ "background": "#e7664c",
+ "text": "black",
+ },
"name": "High",
"priority": "2",
"value": "high",
},
Object {
- "color": "#d6bf57",
+ "color": Object {
+ "background": "#d6bf57",
+ "text": "black",
+ },
"name": "Medium",
"priority": "3",
"value": "medium",
},
Object {
- "color": "#54b399",
+ "color": Object {
+ "background": "#54b399",
+ "text": "black",
+ },
"name": "Low",
"priority": "4",
"value": "low",
},
Object {
- "color": "#209280",
+ "color": Object {
+ "background": "#209280",
+ "text": "white",
+ },
"name": "Informational",
"priority": "5",
"value": "informational",
@@ -2487,31 +2532,46 @@ exports[` spec renders the component 1`] = `
"name": "Rule severity",
"options": Array [
Object {
- "color": "#cc5642",
+ "color": Object {
+ "background": "#cc5642",
+ "text": "white",
+ },
"name": "Critical",
"priority": "1",
"value": "critical",
},
Object {
- "color": "#e7664c",
+ "color": Object {
+ "background": "#e7664c",
+ "text": "black",
+ },
"name": "High",
"priority": "2",
"value": "high",
},
Object {
- "color": "#d6bf57",
+ "color": Object {
+ "background": "#d6bf57",
+ "text": "black",
+ },
"name": "Medium",
"priority": "3",
"value": "medium",
},
Object {
- "color": "#54b399",
+ "color": Object {
+ "background": "#54b399",
+ "text": "black",
+ },
"name": "Low",
"priority": "4",
"value": "low",
},
Object {
- "color": "#209280",
+ "color": Object {
+ "background": "#209280",
+ "text": "white",
+ },
"name": "Informational",
"priority": "5",
"value": "informational",
diff --git a/public/pages/Findings/components/CorrelationsTable/CorrelationsTable.tsx b/public/pages/Findings/components/CorrelationsTable/CorrelationsTable.tsx
index 90783f294..c94a7e819 100644
--- a/public/pages/Findings/components/CorrelationsTable/CorrelationsTable.tsx
+++ b/public/pages/Findings/components/CorrelationsTable/CorrelationsTable.tsx
@@ -7,7 +7,6 @@ import React, { useState } from 'react';
import { CorrelationFinding } from '../../../../../types';
import { ruleTypes } from '../../../Rules/utils/constants';
import { DEFAULT_EMPTY_DATA, ROUTES } from '../../../../utils/constants';
-import { getSeverityBadge } from '../../../Rules/utils/helpers';
import {
EuiButton,
EuiButtonIcon,
@@ -18,17 +17,24 @@ import {
EuiPanel,
EuiInMemoryTable,
EuiBasicTableColumn,
+ EuiPopover,
} from '@elastic/eui';
-import { RIGHT_ALIGNMENT } from '@elastic/eui/lib/services';
+import { FieldValueSelectionFilterConfigType } from '@elastic/eui/src/components/search_bar/filters/field_value_selection_filter';
import { FindingItemType } from '../../containers/Findings/Findings';
import { RouteComponentProps } from 'react-router-dom';
import { DataStore } from '../../../../store/DataStore';
+import { capitalizeFirstLetter, formatRuleType, getSeverityBadge } from '../../../../utils/helpers';
+import { parseAlertSeverityToOption } from '../../../CreateDetector/components/ConfigureAlerts/utils/helpers';
export interface CorrelationsTableProps {
finding: FindingItemType;
correlatedFindings: CorrelationFinding[];
history: RouteComponentProps['history'];
isLoading: boolean;
+ filterOptions: {
+ logTypes: Set;
+ ruleSeverity: Set;
+ };
}
export const CorrelationsTable: React.FC = ({
@@ -36,12 +42,15 @@ export const CorrelationsTable: React.FC = ({
finding,
history,
isLoading,
+ filterOptions: { logTypes, ruleSeverity },
}) => {
const [itemIdToExpandedRowMap, setItemIdToExpandedRowMap] = useState<{
[key: string]: JSX.Element;
}>({});
+ const [findingIdCopied, setFindingIdCopied] = useState(false);
+ const [copyPopoverTimeout, setCopyPopoverTimeout] = useState(undefined);
- const toggleCorrelationDetails = (item: any) => {
+ const toggleCorrelationDetails = (item: CorrelationFinding) => {
const itemIdToExpandedRowMapValues = { ...itemIdToExpandedRowMap };
if (itemIdToExpandedRowMapValues[item.id]) {
delete itemIdToExpandedRowMapValues[item.id];
@@ -87,6 +96,54 @@ export const CorrelationsTable: React.FC = ({
setItemIdToExpandedRowMap(itemIdToExpandedRowMapValues);
};
+ const actions = [
+ {
+ render: (item: CorrelationFinding) => (
+ toggleCorrelationDetails(item)}
+ aria-label={itemIdToExpandedRowMap[item.id] ? 'Collapse' : 'Expand'}
+ iconType={itemIdToExpandedRowMap[item.id] ? 'arrowUp' : 'arrowDown'}
+ />
+ ),
+ },
+ ];
+
+ if (window.navigator?.clipboard) {
+ const copyFindingIdToClipboard = (findingId: string) => {
+ try {
+ window.navigator.clipboard.writeText(findingId);
+ setFindingIdCopied(true);
+ window.clearTimeout(copyPopoverTimeout);
+ setCopyPopoverTimeout(
+ window.setTimeout(() => {
+ setFindingIdCopied(false);
+ }, 1000)
+ );
+ } catch (error: any) {
+ console.error('Failed to copy id');
+ }
+ };
+
+ actions.unshift({
+ render: (item: CorrelationFinding) => (
+ copyFindingIdToClipboard(item.id)}
+ aria-label="Copy"
+ iconType="copy"
+ />
+ }
+ isOpen={findingIdCopied}
+ closePopover={() => setFindingIdCopied(false)}
+ anchorPosition="upCenter"
+ >
+ Finding id copied
+
+ ),
+ });
+ }
+
const columns: EuiBasicTableColumn[] = [
{
field: 'timestamp',
@@ -96,7 +153,7 @@ export const CorrelationsTable: React.FC = ({
{
name: 'Correlated rule',
truncateText: true,
- render: (item: CorrelationFinding) => item?.correlationRule.name || DEFAULT_EMPTY_DATA,
+ render: (item: CorrelationFinding) => item?.correlationRule?.name || DEFAULT_EMPTY_DATA,
},
{
field: 'logType',
@@ -108,9 +165,11 @@ export const CorrelationsTable: React.FC = ({
},
{
name: 'Rule severity',
+ field: 'detectionRule.severity',
truncateText: true,
- align: 'center',
- render: (item: CorrelationFinding) => getSeverityBadge(item.detectionRule.severity),
+ sortable: true,
+ align: 'left',
+ render: (severity: string) => getSeverityBadge(severity),
},
{
field: 'correlationScore',
@@ -118,19 +177,42 @@ export const CorrelationsTable: React.FC = ({
sortable: true,
},
{
- align: RIGHT_ALIGNMENT,
- width: '40px',
+ name: 'Actions',
+ actions,
isExpander: true,
- render: (item: any) => (
- toggleCorrelationDetails(item)}
- aria-label={itemIdToExpandedRowMap[item.id] ? 'Collapse' : 'Expand'}
- iconType={itemIdToExpandedRowMap[item.id] ? 'arrowUp' : 'arrowDown'}
- />
- ),
},
];
+ const search = {
+ box: {
+ placeholder: 'Search findings',
+ schema: true,
+ },
+ filters: [
+ {
+ type: 'field_value_selection',
+ field: 'detectionRule.severity',
+ name: 'Rule severity',
+ options: Array.from(ruleSeverity).map((severity) => {
+ const name =
+ parseAlertSeverityToOption(severity)?.label || capitalizeFirstLetter(severity);
+ return { value: severity, name: name || severity };
+ }),
+ multiSelect: 'or',
+ } as FieldValueSelectionFilterConfigType,
+ {
+ type: 'field_value_selection',
+ field: 'logType',
+ name: 'Log type',
+ options: Array.from(logTypes).map((type) => ({
+ value: type,
+ name: formatRuleType(type),
+ })),
+ multiSelect: 'or',
+ } as FieldValueSelectionFilterConfigType,
+ ],
+ };
+
const goToCorrelationsPage = () => {
DataStore.findings.closeFlyout();
history.push({
@@ -169,8 +251,13 @@ export const CorrelationsTable: React.FC = ({
isExpandable={true}
hasActions={true}
pagination={true}
- search={true}
- sorting={true}
+ search={search}
+ sorting={{
+ sort: {
+ field: 'timestamp',
+ direction: 'desc',
+ },
+ }}
loading={isLoading}
/>
diff --git a/public/pages/Findings/components/FindingDetailsFlyout.tsx b/public/pages/Findings/components/FindingDetailsFlyout.tsx
index a8c356d1e..9adba27e8 100644
--- a/public/pages/Findings/components/FindingDetailsFlyout.tsx
+++ b/public/pages/Findings/components/FindingDetailsFlyout.tsx
@@ -30,8 +30,6 @@ import {
EuiIcon,
EuiTabs,
EuiTab,
- EuiInMemoryTable,
- EuiBasicTableColumn,
EuiLoadingContent,
} from '@elastic/eui';
import { capitalizeFirstLetter, renderTime } from '../../../utils/helpers';
@@ -46,7 +44,6 @@ import { FindingItemType } from '../containers/Findings/Findings';
import { CorrelationFinding, RuleItemInfoBase } from '../../../../types';
import { FindingFlyoutTabId, FindingFlyoutTabs } from '../utils/constants';
import { DataStore } from '../../../store/DataStore';
-import { ruleTypes } from '../../Rules/utils/constants';
import { CorrelationsTable } from './CorrelationsTable/CorrelationsTable';
export interface FindingDetailsFlyoutBaseProps {
@@ -417,12 +414,23 @@ export default class FindingDetailsFlyout extends Component<
private getTabContent(tabId: FindingFlyoutTabId, isDocumentLoading = false) {
switch (tabId) {
case FindingFlyoutTabId.CORRELATIONS:
+ const logTypes = new Set();
+ const ruleSeverity = new Set();
+ Object.values(this.state.allRules).forEach((rule) => {
+ logTypes.add(rule.category);
+ ruleSeverity.add(rule.level);
+ });
+
return (
);
case FindingFlyoutTabId.DETAILS:
@@ -477,7 +485,7 @@ export default class FindingDetailsFlyout extends Component<
/>
)}
{this.createIndexPatternModal()}
-
+
diff --git a/public/pages/Findings/components/FindingsTable/FindingsTable.tsx b/public/pages/Findings/components/FindingsTable/FindingsTable.tsx
index 2790af14c..1ed9a091d 100644
--- a/public/pages/Findings/components/FindingsTable/FindingsTable.tsx
+++ b/public/pages/Findings/components/FindingsTable/FindingsTable.tsx
@@ -13,6 +13,7 @@ import {
EuiLink,
EuiToolTip,
EuiEmptyPrompt,
+ EuiBadge,
} from '@elastic/eui';
import { FieldValueSelectionFilterConfigType } from '@elastic/eui/src/components/search_bar/filters/field_value_selection_filter';
import dateMath from '@elastic/datemath';
@@ -31,6 +32,7 @@ import { FindingItemType } from '../../containers/Findings/Findings';
import { parseAlertSeverityToOption } from '../../../CreateDetector/components/ConfigureAlerts/utils/helpers';
import { RuleSource } from '../../../../../server/models/interfaces';
import { DataStore } from '../../../../store/DataStore';
+import { getSeverityColor } from '../../../Correlations/utils/constants';
interface FindingsTableProps extends RouteComponentProps {
detectorService: DetectorsService;
@@ -193,7 +195,6 @@ export default class FindingsTable extends Component name || DEFAULT_EMPTY_DATA,
},
{
- // field: 'queries',
field: 'logType',
name: 'Log type',
sortable: true,
@@ -205,7 +206,17 @@ export default class FindingsTable extends Component capitalizeFirstLetter(ruleSeverity) || DEFAULT_EMPTY_DATA,
+ align: 'left',
+ render: (ruleSeverity: string) => {
+ const severity = capitalizeFirstLetter(ruleSeverity) || DEFAULT_EMPTY_DATA;
+ const { background, text } = getSeverityColor(severity);
+
+ return (
+
+ {severity}
+
+ );
+ },
},
{
name: 'Actions',
@@ -217,7 +228,7 @@ export default class FindingsTable extends Component
DataStore.findings.openFlyout(finding, this.state.filteredFindings)
}
@@ -283,7 +294,7 @@ export default class FindingsTable extends Component {
- const severityLevel = ruleSeverity.find((sev) => sev.value === severity);
- return {severity || DEFAULT_EMPTY_DATA};
-};
diff --git a/public/store/CorrelationsStore.ts b/public/store/CorrelationsStore.ts
index 89fa8795d..5d0ceaba2 100644
--- a/public/store/CorrelationsStore.ts
+++ b/public/store/CorrelationsStore.ts
@@ -175,7 +175,9 @@ export class CorrelationsStore implements ICorrelationsStore {
if (findingRes.ok) {
findingRes.response.findings.forEach((f) => {
const rule = allRules.find((rule) => rule._id === f.queries[0].id);
-
+ if (!rule) {
+ console.log(f.queries[0].id);
+ }
findings[f.id] = {
...f,
id: f.id,
@@ -218,7 +220,7 @@ export class CorrelationsStore implements ICorrelationsStore {
const correlatedFindings = response.response.findings.map((f) => {
return {
...allFindings[f.finding],
- correlationScore: Math.round(100 * f.score) / 100,
+ correlationScore: f.score.toExponential(2),
};
});
return {
diff --git a/public/utils/helpers.tsx b/public/utils/helpers.tsx
index b325ec055..294a22d9e 100644
--- a/public/utils/helpers.tsx
+++ b/public/utils/helpers.tsx
@@ -12,6 +12,7 @@ import {
EuiSelectOption,
EuiSpacer,
EuiText,
+ EuiBadge,
} from '@elastic/eui';
import moment from 'moment';
import { PeriodSchedule } from '../../models/interfaces';
@@ -27,7 +28,7 @@ import { expressionInterpreter as vegaExpressionInterpreter } from 'vega-interpr
import { RuleInfo } from '../../server/models/interfaces';
import { NotificationsStart } from 'opensearch-dashboards/public';
import { OpenSearchService } from '../services';
-import { ruleTypes } from '../pages/Rules/utils/constants';
+import { ruleSeverity, ruleTypes } from '../pages/Rules/utils/constants';
import { Handler } from 'vega-tooltip';
import _ from 'lodash';
@@ -299,3 +300,12 @@ export const formatRuleType = (matchingRuleType: string) => {
DEFAULT_EMPTY_DATA
);
};
+
+export const getSeverityBadge = (severity: string) => {
+ const severityLevel = ruleSeverity.find((sev) => sev.value === severity);
+ return (
+
+ {severity || DEFAULT_EMPTY_DATA}
+
+ );
+};
diff --git a/types/Correlations.ts b/types/Correlations.ts
index 4db43c44e..35481ddcc 100644
--- a/types/Correlations.ts
+++ b/types/Correlations.ts
@@ -25,8 +25,8 @@ export interface CorrelationGraphData {
export type CorrelationFinding = {
id: string;
- correlationScore?: number;
- correlationRule?: CorrelationFindingHit;
+ correlationScore?: string;
+ correlationRule?: CorrelationRule;
logType: string;
timestamp: string;
detectionRule: { name: string; severity: string };