Skip to content

Commit

Permalink
Add a details button to open the findings flyout from the correlation…
Browse files Browse the repository at this point in the history
…s page. (#572)

* Add a details button to open the findings flyout from the correlations page. #564

Signed-off-by: Jovan Cvetkovic <jovanca.cvetkovic@gmail.com>

* Add a details button to open the findings flyout from the correlations page. #564

Signed-off-by: Jovan Cvetkovic <jovanca.cvetkovic@gmail.com>

* [FEATURE] Add a details button to open the findings flyout from the correlations page. #564

Signed-off-by: Jovan Cvetkovic <jovanca.cvetkovic@gmail.com>

* fix tests

Signed-off-by: Jovan Cvetkovic <jovanca.cvetkovic@gmail.com>

* code review

Signed-off-by: Jovan Cvetkovic <jovanca.cvetkovic@gmail.com>

* code review

Signed-off-by: Jovan Cvetkovic <jovanca.cvetkovic@gmail.com>

* [BUG] Wrong field mappings for the cloud trail logs #573

Signed-off-by: Jovan Cvetkovic <jovanca.cvetkovic@gmail.com>

* code review

Signed-off-by: Jovan Cvetkovic <jovanca.cvetkovic@gmail.com>

---------

Signed-off-by: Jovan Cvetkovic <jovanca.cvetkovic@gmail.com>
  • Loading branch information
jovancacvetkovic committed May 4, 2023
1 parent 0ea5311 commit 01c3266
Show file tree
Hide file tree
Showing 14 changed files with 196 additions and 93 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/cypress-workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,12 @@ jobs:
# Window is slow so wait longer
- name: Sleep until OSD server starts - windows
if: ${{ matrix.os == 'windows-latest' }}
run: Start-Sleep -s 400
run: Start-Sleep -s 450
shell: powershell

- name: Sleep until OSD server starts - non-windows
if: ${{ matrix.os != 'windows-latest' }}
run: sleep 400
run: sleep 450
shell: bash

- name: Install Cypress
Expand Down Expand Up @@ -138,6 +138,7 @@ jobs:
working-directory: OpenSearch-Dashboards/plugins/security-analytics-dashboards-plugin
command: yarn run cypress run
wait-on: 'http://localhost:5601'
wait-on-timeout: 300
browser: chrome
env:
CYPRESS_CACHE_FOLDER: ${{ matrix.cypress_cache_folder }}
Expand Down
2 changes: 1 addition & 1 deletion cypress/integration/1_detectors.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ describe('Detectors', () => {
beforeEach(() => {
cy.intercept('/detectors/_search').as('detectorsSearch');

// Visit Detectors page
// Visit Detectors page before any test
cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/detectors`);
cy.wait('@detectorsSearch').should('have.property', 'state', 'Complete');
});
Expand Down
5 changes: 5 additions & 0 deletions public/app.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ $euiTextColor: $euiColorDarkestShade !default;
@import "./pages/Main/components/Callout.scss";
@import "./pages/Detectors/components/ReviewFieldMappings/ReviewFieldMappings.scss";
@import "./pages/Correlations/Correlations.scss";
@import "./pages/Correlations/components/FindingCard.scss";
@import "./pages/Findings/components/CorrelationsTable/CorrelationsTable.scss";

.selected-radio-panel {
Expand All @@ -39,6 +40,10 @@ $euiTextColor: $euiColorDarkestShade !default;
@return mix($euiColorInk, $color, $percent);
}

.euiLoadingContent__singleLineBackground {
background: linear-gradient(137deg, #d3dae6 45%, #bac0ca 50%, #d3dae6 55%) !important;
}

.refresh-button {
min-width: 0;
.euiButtonContent {
Expand Down
62 changes: 30 additions & 32 deletions public/pages/Alerts/components/AlertFlyout/AlertFlyout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import {
renderTime,
} from '../../../../utils/helpers';
import { FindingsService, IndexPatternsService, OpenSearchService } from '../../../../services';
import FindingDetailsFlyout from '../../../Findings/components/FindingDetailsFlyout';
import { parseAlertSeverityToOption } from '../../../CreateDetector/components/ConfigureAlerts/utils/helpers';
import { Finding } from '../../../Findings/models/interfaces';
import { NotificationsStart } from 'opensearch-dashboards/public';
Expand All @@ -49,7 +48,6 @@ export interface AlertFlyoutProps {

export interface AlertFlyoutState {
acknowledged: boolean;
findingFlyoutData?: Finding;
findingItems: Finding[];
loading: boolean;
rules: { [key: string]: RuleSource };
Expand All @@ -71,10 +69,6 @@ export class AlertFlyout extends React.Component<AlertFlyoutProps, AlertFlyoutSt
this.getFindings();
}

setFindingFlyoutData(finding?: Finding) {
this.setState({ findingFlyoutData: finding });
}

getFindings = async () => {
this.setState({ loading: true });
const {
Expand Down Expand Up @@ -126,6 +120,18 @@ export class AlertFlyout extends React.Component<AlertFlyoutProps, AlertFlyoutSt
createFindingTableColumns(): EuiBasicTableColumn<Finding>[] {
const { detector } = this.props;
const { rules } = this.state;

const backButton = (
<EuiButtonIcon
iconType="arrowLeft"
aria-label="back"
onClick={() => DataStore.findings.closeFlyout()}
display="base"
size="s"
data-test-subj={'finding-details-flyout-back-button'}
/>
);

return [
{
field: 'timestamp',
Expand All @@ -142,7 +148,22 @@ export class AlertFlyout extends React.Component<AlertFlyoutProps, AlertFlyoutSt
render: (id, finding) =>
(
<EuiLink
onClick={() => this.setFindingFlyoutData(finding)}
onClick={() => {
const customRules = detector.inputs[0].detector_input.custom_rules[0];
const prePackagedRules = detector.inputs[0].detector_input.pre_packaged_rules[0];
const rule = rules[customRules?.id] || rules[prePackagedRules?.id] || {};
DataStore.findings.openFlyout(
{
...finding,
detector: { _id: detector.id as string, _index: '', _source: detector },
ruleName: rule.title,
ruleSeverity: rule.level,
},
[...this.state.findingItems, finding],
true,
backButton
);
}}
data-test-subj={'finding-details-flyout-button'}
>
{`${(id as string).slice(0, 7)}...`}
Expand Down Expand Up @@ -175,32 +196,9 @@ export class AlertFlyout extends React.Component<AlertFlyoutProps, AlertFlyoutSt
render() {
const { onClose, alertItem, detector, onAcknowledge } = this.props;
const { trigger_name, state, severity, start_time, last_notification_time } = alertItem;
const { acknowledged, findingItems, findingFlyoutData, loading, rules } = this.state;
const { acknowledged, findingItems, loading } = this.state;

return !!this.state.findingFlyoutData ? (
<FindingDetailsFlyout
{...this.props}
shouldLoadAllFindings={true}
finding={{
...(findingFlyoutData as Finding),
detector: { _id: detector.id as string, _index: '', _source: detector },
}}
findings={findingItems}
closeFlyout={onClose}
backButton={
<EuiButtonIcon
iconType="arrowLeft"
aria-label="back"
onClick={() => this.setFindingFlyoutData()}
display="base"
size="s"
data-test-subj={'finding-details-flyout-back-button'}
/>
}
allRules={rules}
indexPatternsService={this.props.indexPatternService}
/>
) : (
return (
<EuiFlyout
onClose={onClose}
hideCloseButton
Expand Down
9 changes: 9 additions & 0 deletions public/pages/Correlations/components/FindingCard.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.finding-card-header {
.euiFlexItem:nth-child(2) {
margin-right: 6px;
}

.euiFlexItem:nth-child(3) {
margin-left: 6px;
}
}
33 changes: 31 additions & 2 deletions public/pages/Correlations/components/FindingCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
EuiSpacer,
EuiBadge,
EuiHorizontalRule,
EuiToolTip,
} from '@elastic/eui';
import { rulePriorityBySeverity } from '../../CreateDetector/components/DefineDetector/components/DetectionRules/DetectionRulesTable';
import {
Expand All @@ -21,6 +22,8 @@ import {
getSeverityColor,
getLabelFromLogType,
} from '../utils/constants';
import { DataStore } from '../../../store/DataStore';
import { CorrelationFinding } from '../../../../types';

export interface FindingCardProps {
id: string;
Expand All @@ -32,6 +35,8 @@ export interface FindingCardProps {
score: number;
onInspect: (findingId: string, logType: string) => void;
};
finding: CorrelationFinding;
findings: CorrelationFinding[];
}

export const FindingCard: React.FC<FindingCardProps> = ({
Expand All @@ -40,13 +45,25 @@ export const FindingCard: React.FC<FindingCardProps> = ({
logType,
timestamp,
detectionRule,
finding,
findings,
}) => {
const correlationHeader = correlationData ? (
<>
<EuiFlexGroup justifyContent="spaceBetween">
<EuiFlexItem grow={false}>
<EuiFlexGroup className={'finding-card-header'}>
<EuiFlexItem grow={true}>
<EuiText style={{ fontSize: 22, fontWeight: 300 }}>{correlationData.score}</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiToolTip content={'View finding details'}>
<EuiButtonIcon
aria-label={'View finding details'}
data-test-subj={`view-details-icon`}
iconType={'expand'}
onClick={() => DataStore.findings.openFlyout(finding, findings, false)}
/>
</EuiToolTip>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButtonIcon
iconType={'inspect'}
Expand Down Expand Up @@ -110,6 +127,18 @@ export const FindingCard: React.FC<FindingCardProps> = ({
<EuiFlexItem grow={1}>
<strong>{getLabelFromLogType(logType)}</strong>
</EuiFlexItem>
{!correlationData && (
<EuiFlexItem grow={false}>
<EuiToolTip content={'View finding details'}>
<EuiButtonIcon
aria-label={'View finding details'}
data-test-subj={`view-details-icon`}
iconType={'expand'}
onClick={() => DataStore.findings.openFlyout(finding, findings, false)}
/>
</EuiToolTip>
</EuiFlexItem>
)}
</EuiFlexGroup>
{correlationHeader ? <EuiHorizontalRule margin="s" /> : null}
<EuiSpacer size="m" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,10 @@ export class Correlations extends React.Component<CorrelationsProps, Correlation
private async updateState() {
if (this.props.location.state) {
const state = this.props.location.state;

const specificFindingInfo: SpecificFindingCorrelations = {
finding: {
...state.finding,
id: state.finding.id,
logType: state.finding.detector._source.detector_type,
timestamp: new Date(state.finding.timestamp).toLocaleString(),
Expand Down Expand Up @@ -434,6 +436,8 @@ export class Correlations extends React.Component<CorrelationsProps, Correlation
logType={findingCardsData.finding.logType}
timestamp={findingCardsData.finding.timestamp}
detectionRule={findingCardsData.finding.detectionRule}
finding={findingCardsData.finding}
findings={findingCardsData.correlatedFindings}
/>
<EuiSpacer />
<EuiTitle size="xs">
Expand All @@ -456,6 +460,8 @@ export class Correlations extends React.Component<CorrelationsProps, Correlation
score: finding.correlationScore || 0,
onInspect: this.onFindingInspect,
}}
finding={finding}
findings={[...findingCardsData.correlatedFindings, findingCardsData.finding]}
/>
<EuiSpacer size="m" />
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
import { RIGHT_ALIGNMENT } from '@elastic/eui/lib/services';
import { FindingItemType } from '../../containers/Findings/Findings';
import { RouteComponentProps } from 'react-router-dom';
import { DataStore } from '../../../../store/DataStore';

export interface CorrelationsTableProps {
finding: FindingItemType;
Expand Down Expand Up @@ -131,6 +132,7 @@ export const CorrelationsTable: React.FC<CorrelationsTableProps> = ({
];

const goToCorrelationsPage = () => {
DataStore.findings.closeFlyout();
history.push({
pathname: `${ROUTES.CORRELATIONS}`,
state: {
Expand Down
Loading

0 comments on commit 01c3266

Please sign in to comment.