Skip to content

Commit

Permalink
[Backport main] Correlation engine ux (opensearch-project#537)
Browse files Browse the repository at this point in the history
* Correlation engine ux (opensearch-project#524)

* wip

Signed-off-by: Amardeepsingh Siglani <[email protected]>

* completed rules page; added placeholder for findings flyout tabs

Signed-off-by: Amardeepsingh Siglani <[email protected]>

* reverted change to show empty table

Signed-off-by: Amardeepsingh Siglani <[email protected]>

* updated rule type

Signed-off-by: Amardeepsingh Siglani <[email protected]>

* updated create correlation rule page

Signed-off-by: Amardeepsingh Siglani <[email protected]>

* correlation page wip

Signed-off-by: Amardeepsingh Siglani <[email protected]>

* Correlation store and API services

Signed-off-by: Jovan Cvetkovic <[email protected]>

* Correlation store and API services

Signed-off-by: Jovan Cvetkovic <[email protected]>

* Correlation store and API services

Signed-off-by: Jovan Cvetkovic <[email protected]>

* Correlation store and API services

Signed-off-by: Jovan Cvetkovic <[email protected]>

* Correlation store and API services

Signed-off-by: Jovan Cvetkovic <[email protected]>

* updated correlations page

Signed-off-by: Amardeepsingh Siglani <[email protected]>

* updated store interfaces

Signed-off-by: Amardeepsingh Siglani <[email protected]>

* fixed correlation store

Signed-off-by: Amardeepsingh Siglani <[email protected]>

* added api for all correlations

Signed-off-by: Amardeepsingh Siglani <[email protected]>

* added filter support for correlations

Signed-off-by: Amardeepsingh Siglani <[email protected]>

* using apis; added validation

Signed-off-by: Amardeepsingh Siglani <[email protected]>

* Implemented logic to populate correlations tables data.

Signed-off-by: AWSHurneyt <[email protected]>

* restricted to AND

Signed-off-by: Amardeepsingh Siglani <[email protected]>

* log type clearable

Signed-off-by: Amardeepsingh Siglani <[email protected]>

* code cleanup

Signed-off-by: Jovan Cvetkovic <[email protected]>

* fixed API issue

Signed-off-by: Amardeepsingh Siglani <[email protected]>

* updated snapshots

Signed-off-by: Amardeepsingh Siglani <[email protected]>

* ux improvements

Signed-off-by: Amardeepsingh Siglani <[email protected]>

* code cleanup

Signed-off-by: Jovan Cvetkovic <[email protected]>

* removed redundant code

Signed-off-by: Amardeepsingh Siglani <[email protected]>

* removed unwanted param

Signed-off-by: Amardeepsingh Siglani <[email protected]>

* connected refresh

Signed-off-by: Amardeepsingh Siglani <[email protected]>

---------

Signed-off-by: Amardeepsingh Siglani <[email protected]>
Signed-off-by: Jovan Cvetkovic <[email protected]>
Signed-off-by: AWSHurneyt <[email protected]>
Co-authored-by: Jovan Cvetkovic <[email protected]>
Co-authored-by: AWSHurneyt <[email protected]>
(cherry picked from commit f565a923c6bfec1b8a69128d21e5d823a50cb142)

* Removed duplicate import for EuiSpacer (opensearch-project#538) (opensearch-project#540)

* removed duplicate import



* updated snapshots



---------

Signed-off-by: Amardeepsingh Siglani <[email protected]>

* Pinned babel traverse and core (opensearch-project#539) (opensearch-project#544)

* pinned babel traverse and core



* removed cyclic dependency



* added types for vis



* refactored code



---------

Signed-off-by: Amardeepsingh Siglani <[email protected]>

---------

Signed-off-by: Amardeepsingh Siglani <[email protected]>
Co-authored-by: Amardeepsingh Siglani <[email protected]>
  • Loading branch information
opensearch-trigger-bot[bot] and amsiglan authored Apr 19, 2023
1 parent b10b3a4 commit 804f872
Show file tree
Hide file tree
Showing 57 changed files with 3,395 additions and 240 deletions.
10 changes: 7 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@
"minimist": "^1.2.6",
"moment": "^2.29.2",
"async": "^3.2.3",
"json5": "^2.2.3"
"json5": "^2.2.3",
"@babel/core": "^7.20.12",
"@babel/traverse": "^7.20.12"
},
"devDependencies": {
"@elastic/elastic-eslint-config-kibana": "link:../../packages/opensearch-eslint-config-opensearch-dashboards",
Expand All @@ -65,12 +67,14 @@
"jest-cli": "^27.5.1",
"jest-environment-jsdom": "^27.5.1",
"lint-staged": "^10.2.0",
"ts-loader": "^6.2.1"
"ts-loader": "^6.2.1",
"@types/vis": "^4.21.21"
},
"engines": {
"yarn": "^1.21.1"
},
"dependencies": {
"formik": "^2.2.6"
"formik": "^2.2.6",
"react-graph-vis": "^1.0.7"
}
}
1 change: 1 addition & 0 deletions public/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ $euiTextColor: $euiColorDarkestShade !default;
@import "./pages/Overview/components/Widgets/WidgetContainer.scss";
@import "./pages/Main/components/Callout.scss";
@import "./pages/Detectors/components/ReviewFieldMappings/ReviewFieldMappings.scss";
@import "./pages/Correlations//Correlations.scss";

.selected-radio-panel {
background-color: tintOrShade($euiColorPrimary, 90%, 70%);
Expand Down
2 changes: 2 additions & 0 deletions public/models/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ import {
NotificationsService,
IndexPatternsService,
} from '../services';
import CorrelationService from '../services/CorrelationService';

export interface BrowserServices {
detectorsService: DetectorsService;
correlationsService: CorrelationService;
findingsService: FindingsService;
indexService: IndexService;
opensearchService: OpenSearchService;
Expand Down
11 changes: 7 additions & 4 deletions public/pages/Alerts/components/AlertFlyout/AlertFlyout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,21 @@ import {
formatRuleType,
renderTime,
} from '../../../../utils/helpers';
import { FindingsService, OpenSearchService } from '../../../../services';
import { FindingsService, IndexPatternsService, OpenSearchService } from '../../../../services';
import FindingDetailsFlyout from '../../../Findings/components/FindingDetailsFlyout';
import { Detector } from '../../../../../models/interfaces';
import { parseAlertSeverityToOption } from '../../../CreateDetector/components/ConfigureAlerts/utils/helpers';
import { Finding } from '../../../Findings/models/interfaces';
import { NotificationsStart } from 'opensearch-dashboards/public';
import { DataStore } from '../../../../store/DataStore';
import { Detector } from '../../../../../types';

export interface AlertFlyoutProps {
alertItem: AlertItem;
detector: Detector;
findingsService: FindingsService;
notifications: NotificationsStart;
opensearchService: OpenSearchService;
indexPatternService: IndexPatternsService;
onClose: () => void;
onAcknowledge: (selectedItems: AlertItem[]) => void;
}
Expand Down Expand Up @@ -180,9 +181,10 @@ export class AlertFlyout extends React.Component<AlertFlyoutProps, AlertFlyoutSt
<FindingDetailsFlyout
{...this.props}
finding={{
...findingFlyoutData,
detector: { _id: detector.id, _index: '', _source: detector },
...(findingFlyoutData as Finding),
detector: { _id: detector.id as string, _index: '', _source: detector },
}}
findings={findingItems}
closeFlyout={onClose}
backButton={
<EuiButtonIcon
Expand All @@ -195,6 +197,7 @@ export class AlertFlyout extends React.Component<AlertFlyoutProps, AlertFlyoutSt
/>
}
allRules={rules}
indexPatternsService={this.props.indexPatternService}
/>
) : (
<EuiFlyout
Expand Down
6 changes: 4 additions & 2 deletions public/pages/Alerts/containers/Alerts/Alerts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,7 @@ import AlertsService from '../../../../services/AlertsService';
import DetectorService from '../../../../services/DetectorService';
import { AlertItem } from '../../../../../server/models/interfaces';
import { AlertFlyout } from '../../components/AlertFlyout/AlertFlyout';
import { FindingsService, OpenSearchService } from '../../../../services';
import { Detector } from '../../../../../models/interfaces';
import { FindingsService, IndexPatternsService, OpenSearchService } from '../../../../services';
import { parseAlertSeverityToOption } from '../../../CreateDetector/components/ConfigureAlerts/utils/helpers';
import { DISABLE_ACKNOWLEDGED_ALERT_HELP_TEXT } from '../../utils/constants';
import {
Expand All @@ -58,13 +57,15 @@ import { NotificationsStart } from 'opensearch-dashboards/public';
import { match, RouteComponentProps, withRouter } from 'react-router-dom';
import { DateTimeFilter } from '../../../Overview/models/interfaces';
import { ChartContainer } from '../../../../components/Charts/ChartContainer';
import { Detector } from '../../../../../types';

export interface AlertsProps extends RouteComponentProps {
alertService: AlertsService;
detectorService: DetectorService;
findingService: FindingsService;
opensearchService: OpenSearchService;
notifications: NotificationsStart;
indexPatternService: IndexPatternsService;
match: match;
dateTimeFilter?: DateTimeFilter;
setDateTimeFilter?: Function;
Expand Down Expand Up @@ -500,6 +501,7 @@ export class Alerts extends Component<AlertsProps, AlertsState> {
onClose={this.onFlyoutClose}
onAcknowledge={this.onAcknowledge}
findingsService={this.props.findingService}
indexPatternService={this.props.indexPatternService}
/>
)}
<EuiFlexGroup direction="column">
Expand Down
8 changes: 8 additions & 0 deletions public/pages/Correlations/Correlations.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

.correlation_rule_field_condition .euiButtonGroup__buttons {
box-shadow: none;
}
20 changes: 20 additions & 0 deletions public/pages/Correlations/components/CorrelationGraph.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import Graph from 'react-graph-vis';

export const CorrelationGraph = ({ graph: { nodes, edges }, options, events }) => {
return (
<Graph
key={`network`}
identifier={`network`}
graph={{ nodes, edges }}
options={options}
events={events}
style={{ border: '1px solid' }}
/>
);
};
33 changes: 33 additions & 0 deletions public/pages/Correlations/components/DeleteModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import { EuiConfirmModal } from '@elastic/eui';
import React from 'react';

export interface DeleteRuleModalProps {
title: string;
onCancel: () => void;
onConfirm: () => void;
}

export const DeleteCorrelationRuleModal: React.FC<DeleteRuleModalProps> = ({
title,
onCancel,
onConfirm,
}) => {
return (
<EuiConfirmModal
title={`Delete ${title}?`}
onCancel={onCancel}
onConfirm={onConfirm}
cancelButtonText="Cancel"
confirmButtonText="Delete"
buttonColor="danger"
defaultFocusedButton="confirm"
>
<p>Delete the correlation rule permanently? This action cannot be undone.</p>
</EuiConfirmModal>
);
};
31 changes: 31 additions & 0 deletions public/pages/Correlations/components/ExperimentalBanner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import { EuiCallOut, EuiLink, EuiSpacer } from '@elastic/eui';

export const CorrelationsExperimentalBanner = () => {
return (
<>
<EuiCallOut title="Experimental Feature" iconType="beaker">
<p>
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&nbsp;
<EuiLink target="_blank" href="https://forum.opensearch.org/">
forum.opensearch.org.
</EuiLink>
For more information see &nbsp;
<EuiLink
href="https://opensearch.org/docs/latest/security-analytics/index/"
target="_blank"
>
Security Analytics Documentation.
</EuiLink>
</p>
</EuiCallOut>
<EuiSpacer />
</>
);
};
100 changes: 100 additions & 0 deletions public/pages/Correlations/components/FilterGroup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
/*
* Copyright OpenSearch Contributors
* SPDX-License-Identifier: Apache-2.0
*/

import React, { useState } from 'react';
import {
EuiFilterButton,
EuiFilterGroup,
EuiFilterSelectItem,
EuiPopover,
EuiPopoverTitle,
EuiFieldSearch,
FilterChecked,
} from '@elastic/eui';

export type FilterItem = { name: string | React.ReactNode; id: string; checked?: FilterChecked };
export interface LogTypeFilterGroupProps {
groupName: string;
items: FilterItem[];
setItems: (items: FilterItem[]) => void;
}

export const FilterGroup: React.FC<LogTypeFilterGroupProps> = ({ groupName, items, setItems }) => {
const [isPopoverOpen, setIsPopoverOpen] = useState(false);

const onButtonClick = () => {
setIsPopoverOpen(!isPopoverOpen);
};

const closePopover = () => {
setIsPopoverOpen(false);
};

function updateItem(index: number) {
if (!items[index]) {
return;
}

const newItems = [...items];

switch (newItems[index].checked) {
case 'on':
newItems[index] = {
...newItems[index],
checked: undefined,
};
break;

default:
newItems[index] = {
...newItems[index],
checked: 'on',
};
}

setItems(newItems);
}

const button = (
<EuiFilterButton
iconType="arrowDown"
onClick={onButtonClick}
isSelected={isPopoverOpen}
numFilters={items.length}
hasActiveFilters={!!items.find((item) => item.checked === 'on')}
numActiveFilters={items.filter((item) => item.checked === 'on').length}
>
{groupName}
</EuiFilterButton>
);

return (
<EuiFilterGroup>
<EuiPopover
id="popoverExampleMultiSelect"
button={button}
isOpen={isPopoverOpen}
closePopover={closePopover}
panelPaddingSize="none"
>
<EuiPopoverTitle paddingSize="s">
<EuiFieldSearch compressed />
</EuiPopoverTitle>
<div className="ouiFilterSelect__items">
{items.map((item, index) => (
<EuiFilterSelectItem
checked={item.checked}
key={index}
onClick={() => updateItem(index)}
showIcons={true}
>
{item.name}
</EuiFilterSelectItem>
))}
</div>
</EuiPopover>
</EuiFilterGroup>
);
};
Loading

0 comments on commit 804f872

Please sign in to comment.