From 911b5bcea627a903447ff50162cf2ee80ae1d276 Mon Sep 17 00:00:00 2001 From: Amardeepsingh Siglani Date: Tue, 30 May 2023 14:21:02 -0700 Subject: [PATCH] [FEATURE] Rules UI/UX improvements (#592) (#609) * [FEATURE] Rules UI/UX improvements #585 * [BUG] Detection rules page | Filter name typo #588 * Code review --------- Signed-off-by: Jovan Cvetkovic Co-authored-by: Jovan Cvetkovic --- cypress/integration/2_rules.spec.js | 8 ++--- package.json | 1 + public/app.scss | 1 + .../DetectorRulesView.test.tsx.snap | 32 +++++++++---------- .../DetectorDetails.test.tsx.snap | 32 +++++++++---------- .../DetectorDetailsView.test.tsx.snap | 32 +++++++++---------- .../RuleEditor/RuleEditorContainer.tsx | 2 +- .../components/RuleEditor/RuleEditorForm.scss | 6 ++++ .../components/RuleEditor/RuleEditorForm.tsx | 4 +-- .../containers/CreateRule/CreateRule.tsx | 18 ++++++++++- public/pages/Rules/containers/Rules/Rules.tsx | 4 +-- public/pages/Rules/utils/helpers.tsx | 4 +-- public/utils/constants.ts | 4 +-- 13 files changed, 86 insertions(+), 62 deletions(-) create mode 100644 public/pages/Rules/components/RuleEditor/RuleEditorForm.scss diff --git a/cypress/integration/2_rules.spec.js b/cypress/integration/2_rules.spec.js index 84a919338..fd1ca9ac9 100644 --- a/cypress/integration/2_rules.spec.js +++ b/cypress/integration/2_rules.spec.js @@ -139,7 +139,7 @@ describe('Rules', () => { // Check that correct page is showing cy.waitForPageLoad('rules', { - contains: 'Rules', + contains: 'Detection rules', }); }); @@ -220,7 +220,7 @@ describe('Rules', () => { cy.wait('@getRules'); cy.waitForPageLoad('rules', { - contains: 'Rules', + contains: 'Detection rules', }); checkRulesFlyout(); @@ -228,7 +228,7 @@ describe('Rules', () => { it('...can be edited', () => { cy.waitForPageLoad('rules', { - contains: 'Rules', + contains: 'Detection rules', }); cy.get(`input[placeholder="Search rules"]`).ospSearch(SAMPLE_RULE.name); @@ -278,7 +278,7 @@ describe('Rules', () => { }); cy.waitForPageLoad('rules', { - contains: 'Rules', + contains: 'Detection rules', }); cy.wait('@getRules'); diff --git a/package.json b/package.json index 4b6826f1e..f6751889f 100644 --- a/package.json +++ b/package.json @@ -15,6 +15,7 @@ }, "scripts": { "cypress:open": "cypress open", + "cypress:run": "cypress run", "osd": "node ../../scripts/osd", "opensearch": "node ../../scripts/opensearch", "lint": "node ../../scripts/eslint .", diff --git a/public/app.scss b/public/app.scss index c879d2fbc..52b92d7d5 100644 --- a/public/app.scss +++ b/public/app.scss @@ -18,6 +18,7 @@ $euiTextColor: $euiColorDarkestShade !default; @import "./pages/Correlations/Correlations.scss"; @import "./pages/Correlations/components/FindingCard.scss"; @import "./pages/Findings/components/CorrelationsTable/CorrelationsTable.scss"; +@import "./pages/Rules/components/RuleEditor/RuleEditorForm.scss"; @import "./pages/Rules/components/RuleEditor/DetectionVisualEditor.scss"; .selected-radio-panel { 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 6cfeccf96..a4866d062 100644 --- a/public/pages/Detectors/components/DetectorRulesView/__snapshots__/DetectorRulesView.test.tsx.snap +++ b/public/pages/Detectors/components/DetectorRulesView/__snapshots__/DetectorRulesView.test.tsx.snap @@ -416,7 +416,7 @@ exports[` spec renders the component 1`] = ` Object { "field": "category", "multiSelect": "or", - "name": "Rule Type", + "name": "Log type", "options": Array [ Object { "name": "Network", @@ -476,7 +476,7 @@ exports[` spec renders the component 1`] = ` Object { "field": "level", "multiSelect": "or", - "name": "Rule Severity", + "name": "Rule severity", "options": Array [ Object { "color": "#cc5642", @@ -563,7 +563,7 @@ exports[` spec renders the component 1`] = ` Object { "field": "category", "multiSelect": "or", - "name": "Rule Type", + "name": "Log type", "options": Array [ Object { "name": "Network", @@ -623,7 +623,7 @@ exports[` spec renders the component 1`] = ` Object { "field": "level", "multiSelect": "or", - "name": "Rule Severity", + "name": "Rule severity", "options": Array [ Object { "color": "#cc5642", @@ -782,7 +782,7 @@ exports[` spec renders the component 1`] = ` Object { "field": "category", "multiSelect": "or", - "name": "Rule Type", + "name": "Log type", "options": Array [ Object { "name": "Network", @@ -842,7 +842,7 @@ exports[` spec renders the component 1`] = ` Object { "field": "level", "multiSelect": "or", - "name": "Rule Severity", + "name": "Rule severity", "options": Array [ Object { "color": "#cc5642", @@ -923,7 +923,7 @@ exports[` spec renders the component 1`] = ` Object { "field": "category", "multiSelect": "or", - "name": "Rule Type", + "name": "Log type", "options": Array [ Object { "name": "Network", @@ -1013,7 +1013,7 @@ exports[` spec renders the component 1`] = ` iconType="arrowDown" onClick={[Function]} > - Rule Type + Log type } closePopover={[Function]} @@ -1085,10 +1085,10 @@ exports[` spec renders the component 1`] = ` > - Rule Type + Log type @@ -1105,7 +1105,7 @@ exports[` spec renders the component 1`] = ` Object { "field": "level", "multiSelect": "or", - "name": "Rule Severity", + "name": "Rule severity", "options": Array [ Object { "color": "#cc5642", @@ -1173,7 +1173,7 @@ exports[` spec renders the component 1`] = ` iconType="arrowDown" onClick={[Function]} > - Rule Severity + Rule severity } closePopover={[Function]} @@ -1245,10 +1245,10 @@ exports[` spec renders the component 1`] = ` > - Rule Severity + Rule severity 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 d0da566e6..b0f21ba2a 100644 --- a/public/pages/Detectors/containers/Detector/__snapshots__/DetectorDetails.test.tsx.snap +++ b/public/pages/Detectors/containers/Detector/__snapshots__/DetectorDetails.test.tsx.snap @@ -2971,7 +2971,7 @@ exports[` spec renders the component 1`] = ` Object { "field": "category", "multiSelect": "or", - "name": "Rule Type", + "name": "Log type", "options": Array [ Object { "name": "Network", @@ -3031,7 +3031,7 @@ exports[` spec renders the component 1`] = ` Object { "field": "level", "multiSelect": "or", - "name": "Rule Severity", + "name": "Rule severity", "options": Array [ Object { "color": "#cc5642", @@ -3118,7 +3118,7 @@ exports[` spec renders the component 1`] = ` Object { "field": "category", "multiSelect": "or", - "name": "Rule Type", + "name": "Log type", "options": Array [ Object { "name": "Network", @@ -3178,7 +3178,7 @@ exports[` spec renders the component 1`] = ` Object { "field": "level", "multiSelect": "or", - "name": "Rule Severity", + "name": "Rule severity", "options": Array [ Object { "color": "#cc5642", @@ -3337,7 +3337,7 @@ exports[` spec renders the component 1`] = ` Object { "field": "category", "multiSelect": "or", - "name": "Rule Type", + "name": "Log type", "options": Array [ Object { "name": "Network", @@ -3397,7 +3397,7 @@ exports[` spec renders the component 1`] = ` Object { "field": "level", "multiSelect": "or", - "name": "Rule Severity", + "name": "Rule severity", "options": Array [ Object { "color": "#cc5642", @@ -3478,7 +3478,7 @@ exports[` spec renders the component 1`] = ` Object { "field": "category", "multiSelect": "or", - "name": "Rule Type", + "name": "Log type", "options": Array [ Object { "name": "Network", @@ -3568,7 +3568,7 @@ exports[` spec renders the component 1`] = ` iconType="arrowDown" onClick={[Function]} > - Rule Type + Log type } closePopover={[Function]} @@ -3640,10 +3640,10 @@ exports[` spec renders the component 1`] = ` > - Rule Type + Log type @@ -3660,7 +3660,7 @@ exports[` spec renders the component 1`] = ` Object { "field": "level", "multiSelect": "or", - "name": "Rule Severity", + "name": "Rule severity", "options": Array [ Object { "color": "#cc5642", @@ -3728,7 +3728,7 @@ exports[` spec renders the component 1`] = ` iconType="arrowDown" onClick={[Function]} > - Rule Severity + Rule severity } closePopover={[Function]} @@ -3800,10 +3800,10 @@ exports[` spec renders the component 1`] = ` > - Rule Severity + Rule severity 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 dbeb80f0b..6a83a71f9 100644 --- a/public/pages/Detectors/containers/DetectorDetailsView/__snapshots__/DetectorDetailsView.test.tsx.snap +++ b/public/pages/Detectors/containers/DetectorDetailsView/__snapshots__/DetectorDetailsView.test.tsx.snap @@ -1795,7 +1795,7 @@ exports[` spec renders the component 1`] = ` Object { "field": "category", "multiSelect": "or", - "name": "Rule Type", + "name": "Log type", "options": Array [ Object { "name": "Network", @@ -1855,7 +1855,7 @@ exports[` spec renders the component 1`] = ` Object { "field": "level", "multiSelect": "or", - "name": "Rule Severity", + "name": "Rule severity", "options": Array [ Object { "color": "#cc5642", @@ -1942,7 +1942,7 @@ exports[` spec renders the component 1`] = ` Object { "field": "category", "multiSelect": "or", - "name": "Rule Type", + "name": "Log type", "options": Array [ Object { "name": "Network", @@ -2002,7 +2002,7 @@ exports[` spec renders the component 1`] = ` Object { "field": "level", "multiSelect": "or", - "name": "Rule Severity", + "name": "Rule severity", "options": Array [ Object { "color": "#cc5642", @@ -2161,7 +2161,7 @@ exports[` spec renders the component 1`] = ` Object { "field": "category", "multiSelect": "or", - "name": "Rule Type", + "name": "Log type", "options": Array [ Object { "name": "Network", @@ -2221,7 +2221,7 @@ exports[` spec renders the component 1`] = ` Object { "field": "level", "multiSelect": "or", - "name": "Rule Severity", + "name": "Rule severity", "options": Array [ Object { "color": "#cc5642", @@ -2302,7 +2302,7 @@ exports[` spec renders the component 1`] = ` Object { "field": "category", "multiSelect": "or", - "name": "Rule Type", + "name": "Log type", "options": Array [ Object { "name": "Network", @@ -2392,7 +2392,7 @@ exports[` spec renders the component 1`] = ` iconType="arrowDown" onClick={[Function]} > - Rule Type + Log type } closePopover={[Function]} @@ -2464,10 +2464,10 @@ exports[` spec renders the component 1`] = ` > - Rule Type + Log type @@ -2484,7 +2484,7 @@ exports[` spec renders the component 1`] = ` Object { "field": "level", "multiSelect": "or", - "name": "Rule Severity", + "name": "Rule severity", "options": Array [ Object { "color": "#cc5642", @@ -2552,7 +2552,7 @@ exports[` spec renders the component 1`] = ` iconType="arrowDown" onClick={[Function]} > - Rule Severity + Rule severity } closePopover={[Function]} @@ -2624,10 +2624,10 @@ exports[` spec renders the component 1`] = ` > - Rule Severity + Rule severity diff --git a/public/pages/Rules/components/RuleEditor/RuleEditorContainer.tsx b/public/pages/Rules/components/RuleEditor/RuleEditorContainer.tsx index 26e62040e..d7db119de 100644 --- a/public/pages/Rules/components/RuleEditor/RuleEditorContainer.tsx +++ b/public/pages/Rules/components/RuleEditor/RuleEditorContainer.tsx @@ -16,7 +16,7 @@ import { validateRule } from '../../utils/helpers'; import { DataStore } from '../../../../store/DataStore'; export interface RuleEditorProps { - title: string; + title: string | JSX.Element; rule?: Rule; history: RouteComponentProps['history']; notifications?: NotificationsStart; diff --git a/public/pages/Rules/components/RuleEditor/RuleEditorForm.scss b/public/pages/Rules/components/RuleEditor/RuleEditorForm.scss new file mode 100644 index 000000000..b47a85482 --- /dev/null +++ b/public/pages/Rules/components/RuleEditor/RuleEditorForm.scss @@ -0,0 +1,6 @@ +.rule-editor-form { + .euiFlexGroup--gutterLarge + hr { + height: 0; + margin-bottom: 25px; + } +} diff --git a/public/pages/Rules/components/RuleEditor/RuleEditorForm.tsx b/public/pages/Rules/components/RuleEditor/RuleEditorForm.tsx index 2ec6a6c72..c63d2c048 100644 --- a/public/pages/Rules/components/RuleEditor/RuleEditorForm.tsx +++ b/public/pages/Rules/components/RuleEditor/RuleEditorForm.tsx @@ -35,7 +35,7 @@ export interface VisualRuleEditorProps { submit: (values: RuleEditorFormModel) => void; cancel: () => void; mode: 'create' | 'edit'; - title: string; + title: string | JSX.Element; } const editorTypes = [ @@ -119,7 +119,7 @@ export const RuleEditorForm: React.FC = ({ > {(props) => (
- + = ({ history, services, notif return ( + +

Create detection rule

+
+ + Create a rule for detectors to identify threat scenarios for different log sources.{' '} + + Learn more in the Sigma rules specification + + + + } history={history} notifications={notifications} mode={'create'} diff --git a/public/pages/Rules/containers/Rules/Rules.tsx b/public/pages/Rules/containers/Rules/Rules.tsx index ecdfcc49d..a5f3af2fe 100644 --- a/public/pages/Rules/containers/Rules/Rules.tsx +++ b/public/pages/Rules/containers/Rules/Rules.tsx @@ -67,7 +67,7 @@ export const Rules: React.FC = (props) => { Import rule , - Create new rule + Create detection rule , ], [] @@ -99,7 +99,7 @@ export const Rules: React.FC = (props) => { -

Rules

+

Detection rules

diff --git a/public/pages/Rules/utils/helpers.tsx b/public/pages/Rules/utils/helpers.tsx index ce1133ae4..d1c7e661d 100644 --- a/public/pages/Rules/utils/helpers.tsx +++ b/public/pages/Rules/utils/helpers.tsx @@ -84,7 +84,7 @@ export const getRulesTableSearchConfig = (): Search => { { type: 'field_value_selection', field: 'category', - name: 'Rule Type', + name: 'Log type', multiSelect: 'or', options: ruleTypes.map(({ value, label }) => ({ value, @@ -94,7 +94,7 @@ export const getRulesTableSearchConfig = (): Search => { { type: 'field_value_selection', field: 'level', - name: 'Rule Severity', + name: 'Rule severity', multiSelect: 'or', options: ruleSeverity, }, diff --git a/public/utils/constants.ts b/public/utils/constants.ts index daf2aca12..cac883c2d 100644 --- a/public/utils/constants.ts +++ b/public/utils/constants.ts @@ -67,9 +67,9 @@ export const BREADCRUMBS = Object.freeze({ text: `${name}`, href: `#${ROUTES.EDIT_DETECTOR_DETAILS}/${detectorId}`, }), - RULES: { text: 'Rules', href: `#${ROUTES.RULES}` }, + RULES: { text: 'Detection rules', href: `#${ROUTES.RULES}` }, ALERTS: { text: 'Alerts', href: `#${ROUTES.ALERTS}` }, - RULES_CREATE: { text: 'Create rule', href: `#${ROUTES.RULES_CREATE}` }, + RULES_CREATE: { text: 'Create detection rule', href: `#${ROUTES.RULES_CREATE}` }, RULES_EDIT: { text: 'Edit rule', href: `#${ROUTES.RULES_EDIT}` }, RULES_DUPLICATE: { text: 'Duplicate rule', href: `#${ROUTES.RULES_DUPLICATE}` }, RULES_IMPORT: { text: 'Import rule', href: `#${ROUTES.RULES_IMPORT}` },