Skip to content

Commit

Permalink
Updates to log types related UX (opensearch-project#694)
Browse files Browse the repository at this point in the history
* updated log types related UX

Signed-off-by: Amardeepsingh Siglani <amardeep7194@gmail.com>

* added rule flyout in log type details page; removed log type column from rules table in log type details

Signed-off-by: Amardeepsingh Siglani <amardeep7194@gmail.com>

* added search support

Signed-off-by: Amardeepsingh Siglani <amardeep7194@gmail.com>

* using badge for severity in rules table

Signed-off-by: Amardeepsingh Siglani <amardeep7194@gmail.com>

* fixed flaky test

Signed-off-by: Amardeepsingh Siglani <amardeep7194@gmail.com>

---------

Signed-off-by: Amardeepsingh Siglani <amardeep7194@gmail.com>
  • Loading branch information
amsiglan committed Sep 5, 2023
1 parent 7e5985f commit 77410b0
Show file tree
Hide file tree
Showing 26 changed files with 211 additions and 85 deletions.
3 changes: 2 additions & 1 deletion cypress/integration/1_detectors.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ const validatePendingFieldMappingsPanel = (mappings) => {
const fillDetailsForm = (detectorName, dataSource) => {
getNameField().type(detectorName);
getDataSourceField().selectComboboxItem(dataSource);
getDataSourceField().blur();
getLogTypeField().selectComboboxItem(cypressLogTypeDns);
getLogTypeField().blur();
};
Expand Down Expand Up @@ -371,7 +372,7 @@ describe('Detectors', () => {
getDataSourceField().selectComboboxItem(cypressIndexWindows);
getDataSourceField().focus().blur();

cy.get('.euiCallOut')
cy.get('[data-test-subj="define-detector-diff-log-types-warning"]')
.should('be.visible')
.contains(
'To avoid issues with field mappings, we recommend creating separate detectors for different log types.'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import {
EuiHorizontalRule,
CriteriaWithPagination,
EuiText,
EuiEmptyPrompt,
EuiButton,
EuiIcon,
} from '@elastic/eui';

import React, { useMemo, useState } from 'react';
Expand All @@ -17,6 +20,7 @@ import { RuleItem, RuleItemInfo } from './types/interfaces';
import { RuleViewerFlyout } from '../../../../../Rules/components/RuleViewerFlyout/RuleViewerFlyout';
import { RuleTableItem } from '../../../../../Rules/utils/helpers';
import { RuleItemInfoBase } from '../../../../../../../types';
import { ROUTES } from '../../../../../../utils/constants';

export interface CreateDetectorRulesState {
allRules: RuleItemInfo[];
Expand All @@ -26,6 +30,7 @@ export interface CreateDetectorRulesState {
}

export interface DetectionRulesProps {
detectorType: string;
rulesState: CreateDetectorRulesState;
loading?: boolean;
onRuleToggle: (changedItem: RuleItem, isActive: boolean) => void;
Expand All @@ -34,6 +39,7 @@ export interface DetectionRulesProps {
}

export const DetectionRules: React.FC<DetectionRulesProps> = ({
detectorType,
rulesState,
loading,
onPageChange,
Expand All @@ -55,7 +61,7 @@ export const DetectionRules: React.FC<DetectionRulesProps> = ({
id: rule._id,
active: rule.enabled,
description: rule._source.description,
library: rule.prePackaged ? 'Sigma' : 'Custom',
library: rule.prePackaged ? 'Standard' : 'Custom',
logType: rule._source.category,
name: rule._source.title,
severity: rule._source.level,
Expand Down Expand Up @@ -106,14 +112,42 @@ export const DetectionRules: React.FC<DetectionRulesProps> = ({
isLoading={loading}
>
<EuiHorizontalRule margin={'xs'} />
<DetectionRulesTable
pageIndex={rulesState.page.index}
ruleItems={ruleItems}
onAllRulesToggled={onAllRulesToggle}
onRuleActivationToggle={onRuleToggle}
onTableChange={onTableChange}
onRuleDetails={onRuleDetails}
/>

{ruleItems.length ? (
<DetectionRulesTable
pageIndex={rulesState.page.index}
ruleItems={ruleItems}
onAllRulesToggled={onAllRulesToggle}
onRuleActivationToggle={onRuleToggle}
onTableChange={onTableChange}
onRuleDetails={onRuleDetails}
/>
) : (
<EuiEmptyPrompt
title={
<EuiTitle>
<h1>No detection rules {detectorType ? 'to display' : 'selected'}</h1>
</EuiTitle>
}
body={
<p>
{detectorType
? 'There are no applicable detection rules for the selected log type. Consider creating new detection rules.'
: 'Select a log type to be able to select detection rules.'}
</p>
}
actions={
detectorType
? [
<EuiButton href={`#${ROUTES.RULES}`} target="_blank">
Manage&nbsp;
<EuiIcon type={'popout'} />
</EuiButton>,
]
: undefined
}
/>
)}
</EuiAccordion>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ export default class DetectorDataSource extends Component<
<EuiCallOut
title="The selected log sources contain different log types"
color="warning"
data-test-subj={'define-detector-diff-log-types-warning'}
>
<EuiTextColor color={'default'}>
To avoid issues with field mappings, we recommend creating separate detectors for
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ export default class DetectorType extends Component<DetectorTypeProps, DetectorT

<EuiFormRow fullWidth={true}>
<DetectionRules
detectorType={detectorType}
rulesState={this.props.rulesState}
loading={this.props.loadingRules}
onPageChange={this.props.onPageChange}
Expand Down
5 changes: 4 additions & 1 deletion public/pages/CreateDetector/containers/CreateDetector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,10 @@ export default class CreateDetector extends Component<CreateDetectorProps, Creat

this.state = {
currentStep: DetectorCreationStep.DEFINE_DETECTOR,
detector: EMPTY_DEFAULT_DETECTOR,
detector: {
...EMPTY_DEFAULT_DETECTOR,
detector_type: '',
},
fieldMappings: [],
stepDataValid: {
[DetectorCreationStep.DEFINE_DETECTOR]: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const mapRuleItemToRuleTableItem = (ruleItem: RuleItem): RuleTableItem => {
description: ruleItem.description,
source: ruleItem.library,
ruleId: ruleItem.id,
ruleInfo: { ...ruleItem.ruleInfo, prePackaged: ruleItem.library === 'Sigma' },
ruleInfo: { ...ruleItem.ruleInfo, prePackaged: ruleItem.library === 'Standard' },
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -478,7 +478,7 @@ exports[`<DetectorRulesView /> spec renders the component 1`] = `
"name": "Source",
"options": Array [
Object {
"value": "Sigma",
"value": "Standard",
},
Object {
"value": "Custom",
Expand Down Expand Up @@ -587,7 +587,7 @@ exports[`<DetectorRulesView /> spec renders the component 1`] = `
"name": "Source",
"options": Array [
Object {
"value": "Sigma",
"value": "Standard",
},
Object {
"value": "Custom",
Expand Down Expand Up @@ -768,7 +768,7 @@ exports[`<DetectorRulesView /> spec renders the component 1`] = `
"name": "Source",
"options": Array [
Object {
"value": "Sigma",
"value": "Standard",
},
Object {
"value": "Custom",
Expand Down Expand Up @@ -1115,7 +1115,7 @@ exports[`<DetectorRulesView /> spec renders the component 1`] = `
"name": "Source",
"options": Array [
Object {
"value": "Sigma",
"value": "Standard",
},
Object {
"value": "Custom",
Expand Down
4 changes: 2 additions & 2 deletions public/pages/Detectors/components/UpdateRules/UpdateRules.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ export const UpdateDetectorRules: React.FC<UpdateDetectorRulesProps> = (props) =
id: rule._id,
severity: rule._source.level,
logType: rule._source.category,
library: 'Sigma',
library: 'Standard',
description: rule._source.description,
active: enabledRuleIds.includes(rule._id),
ruleInfo: rule,
Expand Down Expand Up @@ -140,7 +140,7 @@ export const UpdateDetectorRules: React.FC<UpdateDetectorRulesProps> = (props) =
.filter((rule) => rule.active);
await getRuleFieldsForEnabledRules(withCustomRulesUpdated);
break;
case 'Sigma':
case 'Standard':
const updatedPrePackgedRules: RuleItem[] = prePackagedRuleItems.map((rule) =>
rule.id === changedItem.id ? { ...rule, active: isActive } : rule
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3032,7 +3032,7 @@ exports[`<DetectorDetails /> spec renders the component 1`] = `
"name": "Source",
"options": Array [
Object {
"value": "Sigma",
"value": "Standard",
},
Object {
"value": "Custom",
Expand Down Expand Up @@ -3141,7 +3141,7 @@ exports[`<DetectorDetails /> spec renders the component 1`] = `
"name": "Source",
"options": Array [
Object {
"value": "Sigma",
"value": "Standard",
},
Object {
"value": "Custom",
Expand Down Expand Up @@ -3322,7 +3322,7 @@ exports[`<DetectorDetails /> spec renders the component 1`] = `
"name": "Source",
"options": Array [
Object {
"value": "Sigma",
"value": "Standard",
},
Object {
"value": "Custom",
Expand Down Expand Up @@ -3669,7 +3669,7 @@ exports[`<DetectorDetails /> spec renders the component 1`] = `
"name": "Source",
"options": Array [
Object {
"value": "Sigma",
"value": "Standard",
},
Object {
"value": "Custom",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1856,7 +1856,7 @@ exports[`<DetectorDetailsView /> spec renders the component 1`] = `
"name": "Source",
"options": Array [
Object {
"value": "Sigma",
"value": "Standard",
},
Object {
"value": "Custom",
Expand Down Expand Up @@ -1965,7 +1965,7 @@ exports[`<DetectorDetailsView /> spec renders the component 1`] = `
"name": "Source",
"options": Array [
Object {
"value": "Sigma",
"value": "Standard",
},
Object {
"value": "Custom",
Expand Down Expand Up @@ -2146,7 +2146,7 @@ exports[`<DetectorDetailsView /> spec renders the component 1`] = `
"name": "Source",
"options": Array [
Object {
"value": "Sigma",
"value": "Standard",
},
Object {
"value": "Custom",
Expand Down Expand Up @@ -2493,7 +2493,7 @@ exports[`<DetectorDetailsView /> spec renders the component 1`] = `
"name": "Source",
"options": Array [
Object {
"value": "Sigma",
"value": "Standard",
},
Object {
"value": "Custom",
Expand Down
3 changes: 2 additions & 1 deletion public/pages/LogTypes/components/LogTypeDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,10 @@ export const LogTypeDetails: React.FC<LogTypeDetailsProps> = ({
return (
<ContentPanel
title="Details"
titleSize="l"
actions={
!isEditMode &&
logTypeDetails.source.toLocaleLowerCase() !== 'sigma' && [
logTypeDetails.source.toLocaleLowerCase() !== 'standard' && [
<EuiButton onClick={() => setIsEditMode(true)}>Edit</EuiButton>,
]
}
Expand Down
72 changes: 43 additions & 29 deletions public/pages/LogTypes/components/LogTypeDetectionRules.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@
* SPDX-License-Identifier: Apache-2.0
*/

import React from 'react';
import React, { useState, useCallback } from 'react';
import { RulesTable } from '../../Rules/components/RulesTable/RulesTable';
import { RuleTableItem } from '../../Rules/utils/helpers';
import { ContentPanel } from '../../../components/ContentPanel';
import { EuiButton, EuiFlexGroup, EuiFlexItem, EuiIcon, EuiSpacer, EuiText } from '@elastic/eui';
import { RuleViewerFlyout } from '../../Rules/components/RuleViewerFlyout/RuleViewerFlyout';

export interface LogTypeDetectionRulesProps {
rules: RuleTableItem[];
Expand All @@ -20,34 +21,47 @@ export const LogTypeDetectionRules: React.FC<LogTypeDetectionRulesProps> = ({
loadingRules,
refreshRules,
}) => {
const [flyoutData, setFlyoutData] = useState<RuleTableItem | undefined>(undefined);
const hideFlyout = useCallback(() => {
setFlyoutData(undefined);
}, []);

return (
<ContentPanel
title="Detection rules"
hideHeaderBorder={true}
actions={[<EuiButton onClick={refreshRules}>Refresh</EuiButton>]}
>
{rules.length === 0 ? (
<EuiFlexGroup justifyContent="center" alignItems="center" direction="column">
<EuiFlexItem grow={false}>
<EuiText color="subdued">
<p>There are no detection rules associated with this log type. </p>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
fill
href={`opensearch_security_analytics_dashboards#/create-rule`}
target="_blank"
>
Create detection rule&nbsp;
<EuiIcon type={'popout'} />
</EuiButton>
<EuiSpacer size="xl" />
</EuiFlexItem>
</EuiFlexGroup>
) : (
<RulesTable loading={loadingRules} ruleItems={rules} showRuleDetails={() => {}} />
)}
</ContentPanel>
<>
{flyoutData && <RuleViewerFlyout hideFlyout={hideFlyout} ruleTableItem={flyoutData} />}
<ContentPanel
title="Detection rules"
hideHeaderBorder={true}
actions={[<EuiButton onClick={refreshRules}>Refresh</EuiButton>]}
>
{rules.length === 0 ? (
<EuiFlexGroup justifyContent="center" alignItems="center" direction="column">
<EuiFlexItem grow={false}>
<EuiText color="subdued">
<p>There are no detection rules associated with this log type. </p>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
fill
href={`opensearch_security_analytics_dashboards#/create-rule`}
target="_blank"
>
Create detection rule&nbsp;
<EuiIcon type={'popout'} />
</EuiButton>
<EuiSpacer size="xl" />
</EuiFlexItem>
</EuiFlexGroup>
) : (
<RulesTable
loading={loadingRules}
ruleItems={rules}
columnsToHide={['category']}
showRuleDetails={setFlyoutData}
/>
)}
</ContentPanel>
</>
);
};
9 changes: 8 additions & 1 deletion public/pages/LogTypes/components/LogTypeForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,14 @@ export const LogTypeForm: React.FC<LogTypeFormProps> = ({
/>
</EuiFormRow>
<EuiSpacer />
<EuiFormRow label="Description">
<EuiFormRow
label={
<>
{'Description - '}
<em>optional</em>
</>
}
>
<EuiTextArea
value={logTypeDetails?.description}
onChange={(e) => {
Expand Down
Loading

0 comments on commit 77410b0

Please sign in to comment.