From ee00b9f84670aff6766e69a6bf3d0be99e8a2d39 Mon Sep 17 00:00:00 2001 From: Gloria Hornero Date: Thu, 10 Sep 2020 17:45:13 +0200 Subject: [PATCH 01/14] improves 'Creates and activates a new custom rule' test --- .../alerts_detection_rules_custom.spec.ts | 41 +++++++++++++-- .../security_solution/cypress/objects/rule.ts | 26 ++++++++++ .../cypress/screens/alerts.ts | 50 +++++++++++-------- .../cypress/screens/create_new_rule.ts | 12 +++++ .../cypress/screens/rule_details.ts | 2 +- .../cypress/tasks/create_new_rule.ts | 19 ++++++- .../rules/schedule_item_form/index.tsx | 2 + 7 files changed, 126 insertions(+), 26 deletions(-) diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts index d9d9fde8fc8cc..b2720752c5deb 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts @@ -5,6 +5,13 @@ */ import { newRule } from '../objects/rule'; +import { + ALERT_RULE_METHOD, + ALERT_RULE_NAME, + ALERT_RULE_SEVERITY, + ALERT_RULE_VERSION, + NUMBER_OF_ALERTS, +} from '../screens/alerts'; import { CUSTOM_RULES_BTN, @@ -33,7 +40,7 @@ import { INVESTIGATION_NOTES_TOGGLE, RULE_ABOUT_DETAILS_HEADER_TOGGLE, RULE_NAME_HEADER, - SCHEDULE_LOOPBACK, + SCHEDULE_LOOKBACK, SCHEDULE_RUNS, SCHEDULE_STEP, } from '../screens/rule_details'; @@ -58,11 +65,14 @@ import { createAndActivateRule, fillAboutRuleAndContinue, fillDefineCustomRuleWithImportedQueryAndContinue, + fillScheduleRuleAndContinue, expectDefineFormToRepopulateAndContinue, expectAboutFormToRepopulateAndContinue, + waitForTheRuleToBeExecuted, } from '../tasks/create_new_rule'; import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver'; import { loginAndWaitForPageWithoutDateRange } from '../tasks/login'; +import { refreshPage } from '../tasks/security_header'; import { DETECTIONS_URL } from '../urls/navigation'; @@ -84,10 +94,14 @@ describe('Detection rules, custom', () => { goToCreateNewRule(); fillDefineCustomRuleWithImportedQueryAndContinue(newRule); fillAboutRuleAndContinue(newRule); + fillScheduleRuleAndContinue(newRule); expectDefineFormToRepopulateAndContinue(newRule); expectAboutFormToRepopulateAndContinue(newRule); createAndActivateRule(); + esArchiverLoad('auditbeat'); + waitForTheRuleToBeExecuted(newRule); + cy.get(CUSTOM_RULES_BTN).invoke('text').should('eql', 'Custom rules (1)'); changeToThreeHundredRowsPerPage(); @@ -166,8 +180,29 @@ describe('Detection rules, custom', () => { .should('eql', `${newRule.customQuery} `); cy.get(DEFINITION_STEP).eq(DEFINITION_TIMELINE).invoke('text').should('eql', 'None'); - cy.get(SCHEDULE_STEP).eq(SCHEDULE_RUNS).invoke('text').should('eql', '5m'); - cy.get(SCHEDULE_STEP).eq(SCHEDULE_LOOPBACK).invoke('text').should('eql', '1m'); + cy.get(SCHEDULE_STEP) + .eq(SCHEDULE_RUNS) + .invoke('text') + .should('eql', `${newRule.runsEvery.interval}${newRule.runsEvery.type}`); + cy.get(SCHEDULE_STEP) + .eq(SCHEDULE_LOOKBACK) + .invoke('text') + .should('eql', `${newRule.lookBack.interval}${newRule.lookBack.type}`); + + refreshPage(); + + cy.get(NUMBER_OF_ALERTS) + .invoke('text') + .then((numberOfAlertsText) => { + cy.wrap(parseInt(numberOfAlertsText, 10)).should('be.above', 0); + }); + cy.get(ALERT_RULE_NAME).first().should('have.text', newRule.name); + cy.get(ALERT_RULE_VERSION).first().should('have.text', '1'); + cy.get(ALERT_RULE_METHOD).first().should('have.text', 'query'); + cy.get(ALERT_RULE_SEVERITY).first().should('have.text', newRule.severity.toLowerCase()); + cy.get('[data-test-subj="draggable-content-signal.rule.risk_score"]') + .first() + .should('have.text', newRule.riskScore); }); }); diff --git a/x-pack/plugins/security_solution/cypress/objects/rule.ts b/x-pack/plugins/security_solution/cypress/objects/rule.ts index 0624606fe8481..ecdf65bb59da9 100644 --- a/x-pack/plugins/security_solution/cypress/objects/rule.ts +++ b/x-pack/plugins/security_solution/cypress/objects/rule.ts @@ -23,6 +23,12 @@ interface SeverityOverride { sourceValue: string; } +interface Interval { + interval: string; + timeType: string; + type: string; +} + export interface CustomRule { customQuery: string; name: string; @@ -36,6 +42,8 @@ export interface CustomRule { mitre: Mitre[]; note: string; timelineId: string; + runsEvery: Interval; + lookBack: Interval; } export interface ThresholdRule extends CustomRule { @@ -95,6 +103,18 @@ const severityOverride4: SeverityOverride = { sourceValue: '10/02/2020', }; +const runsEvery: Interval = { + interval: '1', + timeType: 'Seconds', + type: 's', +}; + +const lookBack: Interval = { + interval: '17520', + timeType: 'Hours', + type: 'h', +}; + export const newRule: CustomRule = { customQuery: 'host.name:*', name: 'New Rule Test', @@ -107,6 +127,8 @@ export const newRule: CustomRule = { mitre: [mitre1, mitre2], note: '# test markdown', timelineId: '0162c130-78be-11ea-9718-118a926974a4', + runsEvery, + lookBack, }; export const newOverrideRule: OverrideRule = { @@ -125,6 +147,8 @@ export const newOverrideRule: OverrideRule = { riskOverride: 'destination.port', nameOverride: 'agent.type', timestampOverride: '@timestamp', + runsEvery, + lookBack, }; export const newThresholdRule: ThresholdRule = { @@ -141,6 +165,8 @@ export const newThresholdRule: ThresholdRule = { timelineId: '0162c130-78be-11ea-9718-118a926974a4', thresholdField: 'host.name', threshold: '10', + runsEvery, + lookBack, }; export const machineLearningRule: MachineLearningRule = { diff --git a/x-pack/plugins/security_solution/cypress/screens/alerts.ts b/x-pack/plugins/security_solution/cypress/screens/alerts.ts index fb7e7e73986b9..ec907ccffa3c4 100644 --- a/x-pack/plugins/security_solution/cypress/screens/alerts.ts +++ b/x-pack/plugins/security_solution/cypress/screens/alerts.ts @@ -4,45 +4,55 @@ * you may not use this file except in compliance with the Elastic License. */ -export const EXPAND_ALERT_BTN = '[data-test-subj="expand-event"]'; +export const ALERTS = '[data-test-subj="event"]'; -export const LOADING_ALERTS_PANEL = '[data-test-subj="loading-alerts-panel"]'; +export const ALERT_CHECKBOX = '[data-test-subj="select-event-container"] .euiCheckbox__input'; -export const MANAGE_ALERT_DETECTION_RULES_BTN = '[data-test-subj="manage-alert-detection-rules"]'; +export const ALERT_ID = '[data-test-subj="draggable-content-_id"]'; -export const NUMBER_OF_ALERTS = '[data-test-subj="server-side-event-count"] .euiBadge__text'; +export const ALERT_RULE_METHOD = '[data-test-subj="draggable-content-signal.rule.type"]'; -export const OPENED_ALERTS_FILTER_BTN = '[data-test-subj="openAlerts"]'; +export const ALERT_RULE_NAME = '[data-test-subj="draggable-content-signal.rule.name"]'; -export const CLOSED_ALERTS_FILTER_BTN = '[data-test-subj="closedAlerts"]'; +export const ALERT_RULE_RISK_SCORE = '[data-test-subj="draggable-content-signal.rule.risk_score"]'; -export const IN_PROGRESS_ALERTS_FILTER_BTN = '[data-test-subj="inProgressAlerts"]'; +export const ALERT_RULE_SEVERITY = '[data-test-subj="draggable-content-signal.rule.severity"]'; -export const SELECTED_ALERTS = '[data-test-subj="selectedAlerts"]'; +export const ALERT_RULE_VERSION = '[data-test-subj="draggable-content-signal.rule.version"]'; -export const SEND_ALERT_TO_TIMELINE_BTN = '[data-test-subj="send-alert-to-timeline-button"]'; - -export const SHOWING_ALERTS = '[data-test-subj="showingAlerts"]'; +export const CLOSE_ALERT_BTN = '[data-test-subj="close-alert-status"]'; -export const ALERTS = '[data-test-subj="event"]'; +export const CLOSE_SELECTED_ALERTS_BTN = '[data-test-subj="closeSelectedAlertsButton"]'; -export const ALERT_ID = '[data-test-subj="draggable-content-_id"]'; +export const CLOSED_ALERTS_FILTER_BTN = '[data-test-subj="closedAlerts"]'; -export const ALERT_CHECKBOX = '[data-test-subj="select-event-container"] .euiCheckbox__input'; +export const EXPAND_ALERT_BTN = '[data-test-subj="expand-event"]'; -export const TAKE_ACTION_POPOVER_BTN = '[data-test-subj="alertActionPopover"] button'; +export const IN_PROGRESS_ALERTS_FILTER_BTN = '[data-test-subj="inProgressAlerts"]'; -export const TIMELINE_CONTEXT_MENU_BTN = '[data-test-subj="timeline-context-menu-button"]'; +export const LOADING_ALERTS_PANEL = '[data-test-subj="loading-alerts-panel"]'; -export const OPEN_SELECTED_ALERTS_BTN = '[data-test-subj="openSelectedAlertsButton"]'; +export const MANAGE_ALERT_DETECTION_RULES_BTN = '[data-test-subj="manage-alert-detection-rules"]'; -export const CLOSE_SELECTED_ALERTS_BTN = '[data-test-subj="closeSelectedAlertsButton"]'; +export const MARK_ALERT_IN_PROGRESS_BTN = '[data-test-subj="in-progress-alert-status"]'; export const MARK_SELECTED_ALERTS_IN_PROGRESS_BTN = '[data-test-subj="markSelectedAlertsInProgressButton"]'; +export const NUMBER_OF_ALERTS = '[data-test-subj="server-side-event-count"] .euiBadge__text'; + export const OPEN_ALERT_BTN = '[data-test-subj="open-alert-status"]'; -export const CLOSE_ALERT_BTN = '[data-test-subj="close-alert-status"]'; +export const OPEN_SELECTED_ALERTS_BTN = '[data-test-subj="openSelectedAlertsButton"]'; -export const MARK_ALERT_IN_PROGRESS_BTN = '[data-test-subj="in-progress-alert-status"]'; +export const OPENED_ALERTS_FILTER_BTN = '[data-test-subj="openAlerts"]'; + +export const SELECTED_ALERTS = '[data-test-subj="selectedAlerts"]'; + +export const SEND_ALERT_TO_TIMELINE_BTN = '[data-test-subj="send-alert-to-timeline-button"]'; + +export const SHOWING_ALERTS = '[data-test-subj="showingAlerts"]'; + +export const TAKE_ACTION_POPOVER_BTN = '[data-test-subj="alertActionPopover"] button'; + +export const TIMELINE_CONTEXT_MENU_BTN = '[data-test-subj="timeline-context-menu-button"]'; diff --git a/x-pack/plugins/security_solution/cypress/screens/create_new_rule.ts b/x-pack/plugins/security_solution/cypress/screens/create_new_rule.ts index 1c25ed88c3bee..95d207673940c 100644 --- a/x-pack/plugins/security_solution/cypress/screens/create_new_rule.ts +++ b/x-pack/plugins/security_solution/cypress/screens/create_new_rule.ts @@ -45,6 +45,12 @@ export const INVESTIGATION_NOTES_TEXTAREA = export const FALSE_POSITIVES_INPUT = '[data-test-subj="detectionEngineStepAboutRuleFalsePositives"] input'; +export const LOOK_BACK_INTERVAL = + '[data-test-subj="detectionEngineStepScheduleRuleFrom"] [data-test-subj="interval"]'; + +export const LOOK_BACK_TIME_TYPE = + '[data-test-subj="detectionEngineStepScheduleRuleFrom"] [data-test-subj="timeType"]'; + export const MACHINE_LEARNING_DROPDOWN = '[data-test-subj="mlJobSelect"] button'; export const MACHINE_LEARNING_LIST = '.euiContextMenuItem__text'; @@ -79,6 +85,12 @@ export const RULE_NAME_OVERRIDE = '[data-test-subj="detectionEngineStepAboutRule export const RULE_TIMESTAMP_OVERRIDE = '[data-test-subj="detectionEngineStepAboutRuleTimestampOverride"]'; +export const RUNS_EVERY_INTERVAL = + '[data-test-subj="detectionEngineStepScheduleRuleInterval"] [data-test-subj="interval"]'; + +export const RUNS_EVERY_TIME_TYPE = + '[data-test-subj="detectionEngineStepScheduleRuleInterval"] [data-test-subj="timeType"]'; + export const SCHEDULE_CONTINUE_BUTTON = '[data-test-subj="schedule-continue"]'; export const SEVERITY_DROPDOWN = diff --git a/x-pack/plugins/security_solution/cypress/screens/rule_details.ts b/x-pack/plugins/security_solution/cypress/screens/rule_details.ts index b221709966943..32ff35898e776 100644 --- a/x-pack/plugins/security_solution/cypress/screens/rule_details.ts +++ b/x-pack/plugins/security_solution/cypress/screens/rule_details.ts @@ -72,4 +72,4 @@ export const SCHEDULE_STEP = '[data-test-subj="schedule"] .euiDescriptionList__ export const SCHEDULE_RUNS = 0; -export const SCHEDULE_LOOPBACK = 1; +export const SCHEDULE_LOOKBACK = 1; diff --git a/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts b/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts index f26a77171462c..719dab9dc244d 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts @@ -13,6 +13,7 @@ import { } from '../objects/rule'; import { ABOUT_CONTINUE_BTN, + ABOUT_EDIT_BUTTON, ANOMALY_THRESHOLD_INPUT, ADD_FALSE_POSITIVE_BTN, ADD_REFERENCE_URL_BTN, @@ -21,10 +22,13 @@ import { CREATE_AND_ACTIVATE_BTN, CUSTOM_QUERY_INPUT, DEFINE_CONTINUE_BUTTON, + DEFINE_EDIT_BUTTON, FALSE_POSITIVES_INPUT, IMPORT_QUERY_FROM_SAVED_TIMELINE_LINK, INPUT, INVESTIGATION_NOTES_TEXTAREA, + LOOK_BACK_INTERVAL, + LOOK_BACK_TIME_TYPE, MACHINE_LEARNING_DROPDOWN, MACHINE_LEARNING_LIST, MACHINE_LEARNING_TYPE, @@ -40,6 +44,8 @@ import { RULE_NAME_INPUT, RULE_NAME_OVERRIDE, RULE_TIMESTAMP_OVERRIDE, + RUNS_EVERY_INTERVAL, + RUNS_EVERY_TIME_TYPE, SCHEDULE_CONTINUE_BUTTON, SEVERITY_DROPDOWN, SEVERITY_MAPPING_OVERRIDE_OPTION, @@ -48,8 +54,6 @@ import { THRESHOLD_FIELD_SELECTION, THRESHOLD_INPUT_AREA, THRESHOLD_TYPE, - DEFINE_EDIT_BUTTON, - ABOUT_EDIT_BUTTON, EQL_TYPE, EQL_QUERY_INPUT, } from '../screens/create_new_rule'; @@ -179,6 +183,13 @@ export const fillDefineCustomRuleWithImportedQueryAndContinue = ( cy.get(CUSTOM_QUERY_INPUT).should('not.exist'); }; +export const fillScheduleRuleAndContinue = (rule: CustomRule) => { + cy.get(RUNS_EVERY_INTERVAL).clear().type(rule.runsEvery.interval); + cy.get(RUNS_EVERY_TIME_TYPE).select(rule.runsEvery.timeType); + cy.get(LOOK_BACK_INTERVAL).clear().type(rule.lookBack.interval); + cy.get(LOOK_BACK_TIME_TYPE).select(rule.lookBack.timeType); +}; + export const expectDefineFormToRepopulateAndContinue = (rule: CustomRule) => { cy.get(DEFINE_EDIT_BUTTON).click(); cy.get(CUSTOM_QUERY_INPUT).invoke('text').should('eq', rule.customQuery); @@ -238,6 +249,10 @@ export const selectThresholdRuleType = () => { cy.get(THRESHOLD_TYPE).click({ force: true }); }; +export const waitForTheRuleToBeExecuted = (rule: CustomRule) => { + cy.wait(parseInt(rule.runsEvery.interval, 10) * 1000); +}; + export const selectEqlRuleType = () => { cy.get(EQL_TYPE).click({ force: true }); }; diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/schedule_item_form/index.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/schedule_item_form/index.tsx index bb33767f4f5d5..ae012774fa30d 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/schedule_item_form/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/schedule_item_form/index.tsx @@ -149,6 +149,7 @@ export const ScheduleItem = ({ options={timeTypeOptions} onChange={onChangeTimeType} value={timeType} + data-test-subj="timeType" {...rest} /> } @@ -158,6 +159,7 @@ export const ScheduleItem = ({ min={minimumValue} onChange={onChangeTimeVal} value={timeVal} + data-test-subj="interval" {...rest} /> From 5e3f5d53a32739682b99bac8c504fbf96b67bb12 Mon Sep 17 00:00:00 2001 From: Gloria Hornero Date: Sun, 13 Sep 2020 17:20:18 +0200 Subject: [PATCH 02/14] fixes constant problem --- .../cypress/integration/alerts_detection_rules_ml.spec.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_ml.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_ml.spec.ts index b6b30ef550eb1..3a6dd2d5dec5b 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_ml.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_ml.spec.ts @@ -30,7 +30,7 @@ import { MACHINE_LEARNING_JOB_ID, MACHINE_LEARNING_JOB_STATUS, RULE_NAME_HEADER, - SCHEDULE_LOOPBACK, + SCHEDULE_LOOKBACK, SCHEDULE_RUNS, SCHEDULE_STEP, RULE_TYPE, @@ -156,6 +156,6 @@ describe('Detection rules, machine learning', () => { cy.get(DEFINITION_STEP).eq(DEFINITION_TIMELINE).invoke('text').should('eql', 'None'); cy.get(SCHEDULE_STEP).eq(SCHEDULE_RUNS).invoke('text').should('eql', '5m'); - cy.get(SCHEDULE_STEP).eq(SCHEDULE_LOOPBACK).invoke('text').should('eql', '1m'); + cy.get(SCHEDULE_STEP).eq(SCHEDULE_LOOKBACK).invoke('text').should('eql', '1m'); }); }); From 0b5afe17db7986e00a53a248e6993ec4b8e739e4 Mon Sep 17 00:00:00 2001 From: Gloria Hornero Date: Sun, 13 Sep 2020 18:43:02 +0200 Subject: [PATCH 03/14] improves 'Creates and activates a new custom rule with override option' test --- .../alerts_detection_rules_custom.spec.ts | 5 +-- .../alerts_detection_rules_override.spec.ts | 44 +++++++++++++++++-- .../security_solution/cypress/objects/rule.ts | 8 ++-- .../cypress/screens/alerts.ts | 2 + .../security_solution/cypress/tasks/alerts.ts | 7 +++ .../cypress/tasks/security_header.ts | 4 ++ 6 files changed, 60 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts index b2720752c5deb..9e5b1bbce638e 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts @@ -8,6 +8,7 @@ import { newRule } from '../objects/rule'; import { ALERT_RULE_METHOD, ALERT_RULE_NAME, + ALERT_RULE_RISK_SCORE, ALERT_RULE_SEVERITY, ALERT_RULE_VERSION, NUMBER_OF_ALERTS, @@ -200,9 +201,7 @@ describe('Detection rules, custom', () => { cy.get(ALERT_RULE_VERSION).first().should('have.text', '1'); cy.get(ALERT_RULE_METHOD).first().should('have.text', 'query'); cy.get(ALERT_RULE_SEVERITY).first().should('have.text', newRule.severity.toLowerCase()); - cy.get('[data-test-subj="draggable-content-signal.rule.risk_score"]') - .first() - .should('have.text', newRule.riskScore); + cy.get(ALERT_RULE_RISK_SCORE).first().should('have.text', newRule.riskScore); }); }); diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_override.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_override.spec.ts index e3526c63e2310..ee9a35c12c107 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_override.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_override.spec.ts @@ -5,6 +5,14 @@ */ import { newOverrideRule } from '../objects/rule'; +import { + NUMBER_OF_ALERTS, + ALERT_RULE_NAME, + ALERT_RULE_VERSION, + ALERT_RULE_METHOD, + ALERT_RULE_SEVERITY, + ALERT_RULE_RISK_SCORE, +} from '../screens/alerts'; import { CUSTOM_RULES_BTN, @@ -36,13 +44,14 @@ import { INVESTIGATION_NOTES_TOGGLE, RULE_ABOUT_DETAILS_HEADER_TOGGLE, RULE_NAME_HEADER, - SCHEDULE_LOOPBACK, + SCHEDULE_LOOKBACK, SCHEDULE_RUNS, SCHEDULE_STEP, } from '../screens/rule_details'; import { goToManageAlertsDetectionRules, + sortRiskScore, waitForAlertsIndexToBeCreated, waitForAlertsPanelToBeLoaded, } from '../tasks/alerts'; @@ -58,9 +67,12 @@ import { createAndActivateRule, fillAboutRuleWithOverrideAndContinue, fillDefineCustomRuleWithImportedQueryAndContinue, + fillScheduleRuleAndContinue, + waitForTheRuleToBeExecuted, } from '../tasks/create_new_rule'; import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver'; import { loginAndWaitForPageWithoutDateRange } from '../tasks/login'; +import { refreshPage } from '../tasks/security_header'; import { DETECTIONS_URL } from '../urls/navigation'; @@ -82,8 +94,12 @@ describe('Detection rules, override', () => { goToCreateNewRule(); fillDefineCustomRuleWithImportedQueryAndContinue(newOverrideRule); fillAboutRuleWithOverrideAndContinue(newOverrideRule); + fillScheduleRuleAndContinue(newOverrideRule); createAndActivateRule(); + esArchiverLoad('auditbeat'); + waitForTheRuleToBeExecuted(newOverrideRule); + cy.get(CUSTOM_RULES_BTN).invoke('text').should('eql', 'Custom rules (1)'); changeToThreeHundredRowsPerPage(); @@ -190,7 +206,29 @@ describe('Detection rules, override', () => { .should('eql', `${newOverrideRule.customQuery} `); cy.get(DEFINITION_STEP).eq(DEFINITION_TIMELINE).invoke('text').should('eql', 'None'); - cy.get(SCHEDULE_STEP).eq(SCHEDULE_RUNS).invoke('text').should('eql', '5m'); - cy.get(SCHEDULE_STEP).eq(SCHEDULE_LOOPBACK).invoke('text').should('eql', '1m'); + cy.get(SCHEDULE_STEP) + .eq(SCHEDULE_RUNS) + .invoke('text') + .should('eql', `${newOverrideRule.runsEvery.interval}${newOverrideRule.runsEvery.type}`); + cy.get(SCHEDULE_STEP) + .eq(SCHEDULE_LOOKBACK) + .invoke('text') + .should('eql', `${newOverrideRule.lookBack.interval}${newOverrideRule.lookBack.type}`); + + refreshPage(); + + cy.get(NUMBER_OF_ALERTS) + .invoke('text') + .then((numberOfAlertsText) => { + cy.wrap(parseInt(numberOfAlertsText, 10)).should('be.above', 0); + }); + cy.get(ALERT_RULE_NAME).first().should('have.text', 'auditbeat'); + cy.get(ALERT_RULE_VERSION).first().should('have.text', '1'); + cy.get(ALERT_RULE_METHOD).first().should('have.text', 'query'); + cy.get(ALERT_RULE_SEVERITY).first().should('have.text', 'critical'); + + sortRiskScore(); + + cy.get(ALERT_RULE_RISK_SCORE).first().should('have.text', '80'); }); }); diff --git a/x-pack/plugins/security_solution/cypress/objects/rule.ts b/x-pack/plugins/security_solution/cypress/objects/rule.ts index ecdf65bb59da9..15a2f6f850765 100644 --- a/x-pack/plugins/security_solution/cypress/objects/rule.ts +++ b/x-pack/plugins/security_solution/cypress/objects/rule.ts @@ -89,8 +89,8 @@ const severityOverride1: SeverityOverride = { }; const severityOverride2: SeverityOverride = { - sourceField: 'agent.type', - sourceValue: 'endpoint', + sourceField: '@timestamp', + sourceValue: '10/02/2020', }; const severityOverride3: SeverityOverride = { @@ -99,8 +99,8 @@ const severityOverride3: SeverityOverride = { }; const severityOverride4: SeverityOverride = { - sourceField: '@timestamp', - sourceValue: '10/02/2020', + sourceField: 'agent.type', + sourceValue: 'auditbeat', }; const runsEvery: Interval = { diff --git a/x-pack/plugins/security_solution/cypress/screens/alerts.ts b/x-pack/plugins/security_solution/cypress/screens/alerts.ts index ec907ccffa3c4..ed05874bd4c4d 100644 --- a/x-pack/plugins/security_solution/cypress/screens/alerts.ts +++ b/x-pack/plugins/security_solution/cypress/screens/alerts.ts @@ -10,6 +10,8 @@ export const ALERT_CHECKBOX = '[data-test-subj="select-event-container"] .euiChe export const ALERT_ID = '[data-test-subj="draggable-content-_id"]'; +export const ALERT_RISK_SCORE_HEADER = '[data-test-subj="header-text-signal.rule.risk_score"]'; + export const ALERT_RULE_METHOD = '[data-test-subj="draggable-content-signal.rule.type"]'; export const ALERT_RULE_NAME = '[data-test-subj="draggable-content-signal.rule.name"]'; diff --git a/x-pack/plugins/security_solution/cypress/tasks/alerts.ts b/x-pack/plugins/security_solution/cypress/tasks/alerts.ts index ebd37b522924f..21cc0979c0ad3 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/alerts.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/alerts.ts @@ -22,8 +22,10 @@ import { OPEN_SELECTED_ALERTS_BTN, MARK_ALERT_IN_PROGRESS_BTN, MARK_SELECTED_ALERTS_IN_PROGRESS_BTN, + ALERT_RISK_SCORE_HEADER, } from '../screens/alerts'; import { REFRESH_BUTTON } from '../screens/security_header'; +import { waitForThePageToBeUpdated } from './security_header'; export const closeFirstAlert = () => { cy.get(TIMELINE_CONTEXT_MENU_BTN).first().click({ force: true }); @@ -81,6 +83,11 @@ export const selectNumberOfAlerts = (numberOfAlerts: number) => { } }; +export const sortRiskScore = () => { + cy.get(ALERT_RISK_SCORE_HEADER).click(); + waitForThePageToBeUpdated(); +}; + export const investigateFirstAlertInTimeline = () => { cy.get(SEND_ALERT_TO_TIMELINE_BTN).first().click({ force: true }); }; diff --git a/x-pack/plugins/security_solution/cypress/tasks/security_header.ts b/x-pack/plugins/security_solution/cypress/tasks/security_header.ts index 7427104a9d889..28efc47120d32 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/security_header.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/security_header.ts @@ -21,3 +21,7 @@ export const navigateFromHeaderTo = (page: string) => { export const refreshPage = () => { cy.get(REFRESH_BUTTON).click({ force: true }).invoke('text').should('not.equal', 'Updating'); }; + +export const waitForThePageToBeUpdated = () => { + cy.get(REFRESH_BUTTON).should('not.equal', 'Updating'); +}; From 0c34e9bf80321e4338bec75c9f171e454be47180 Mon Sep 17 00:00:00 2001 From: Gloria Hornero Date: Sun, 13 Sep 2020 19:25:31 +0200 Subject: [PATCH 04/14] improves 'Creates and activates a new threshold rule' test --- .../alerts_detection_rules_threshold.spec.ts | 38 +++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_threshold.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_threshold.spec.ts index 10f9ebb5623df..609e464e746b9 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_threshold.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_threshold.spec.ts @@ -5,6 +5,14 @@ */ import { newThresholdRule } from '../objects/rule'; +import { + ALERT_RULE_METHOD, + ALERT_RULE_NAME, + ALERT_RULE_RISK_SCORE, + ALERT_RULE_SEVERITY, + ALERT_RULE_VERSION, + NUMBER_OF_ALERTS, +} from '../screens/alerts'; import { CUSTOM_RULES_BTN, @@ -33,7 +41,7 @@ import { INVESTIGATION_NOTES_TOGGLE, RULE_ABOUT_DETAILS_HEADER_TOGGLE, RULE_NAME_HEADER, - SCHEDULE_LOOPBACK, + SCHEDULE_LOOKBACK, SCHEDULE_RUNS, SCHEDULE_STEP, } from '../screens/rule_details'; @@ -55,10 +63,12 @@ import { createAndActivateRule, fillAboutRuleAndContinue, fillDefineThresholdRuleAndContinue, + fillScheduleRuleAndContinue, selectThresholdRuleType, } from '../tasks/create_new_rule'; import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver'; import { loginAndWaitForPageWithoutDateRange } from '../tasks/login'; +import { refreshPage } from '../tasks/security_header'; import { DETECTIONS_URL } from '../urls/navigation'; @@ -81,6 +91,7 @@ describe('Detection rules, threshold', () => { selectThresholdRuleType(); fillDefineThresholdRuleAndContinue(newThresholdRule); fillAboutRuleAndContinue(newThresholdRule); + fillScheduleRuleAndContinue(newThresholdRule); createAndActivateRule(); cy.get(CUSTOM_RULES_BTN).invoke('text').should('eql', 'Custom rules (1)'); @@ -168,7 +179,28 @@ describe('Detection rules, threshold', () => { `Results aggregated by ${newThresholdRule.thresholdField} >= ${newThresholdRule.threshold}` ); - cy.get(SCHEDULE_STEP).eq(SCHEDULE_RUNS).invoke('text').should('eql', '5m'); - cy.get(SCHEDULE_STEP).eq(SCHEDULE_LOOPBACK).invoke('text').should('eql', '1m'); + cy.get(SCHEDULE_STEP) + .eq(SCHEDULE_RUNS) + .invoke('text') + .should('eql', `${newThresholdRule.runsEvery.interval}${newThresholdRule.runsEvery.type}`); + cy.get(SCHEDULE_STEP) + .eq(SCHEDULE_LOOKBACK) + .invoke('text') + .should('eql', `${newThresholdRule.lookBack.interval}${newThresholdRule.lookBack.type}`); + + refreshPage(); + + cy.get(NUMBER_OF_ALERTS) + .invoke('text') + .then((numberOfAlertsText) => { + cy.wrap(parseInt(numberOfAlertsText, 10)).should('be.below', 20); + }); + cy.get(ALERT_RULE_NAME).first().should('have.text', newThresholdRule.name); + cy.get(ALERT_RULE_VERSION).first().should('have.text', '1'); + cy.get(ALERT_RULE_METHOD).first().should('have.text', 'threshold'); + cy.get(ALERT_RULE_SEVERITY) + .first() + .should('have.text', newThresholdRule.severity.toLowerCase()); + cy.get(ALERT_RULE_RISK_SCORE).first().should('have.text', newThresholdRule.riskScore); }); }); From 56c4c9237a096856ccdeb7c4ff7055a919410c53 Mon Sep 17 00:00:00 2001 From: Gloria Hornero Date: Wed, 16 Sep 2020 14:56:24 +0200 Subject: [PATCH 05/14] refactor --- .../cypress/integration/alerts.spec.ts | 65 +-- .../alerts_detection_rules.spec.ts | 3 +- .../alerts_detection_rules_custom.spec.ts | 436 +++++++++--------- .../alerts_detection_rules_eql.spec.ts | 128 ++--- .../alerts_detection_rules_ml.spec.ts | 135 +++--- .../alerts_detection_rules_override.spec.ts | 175 ++++--- .../alerts_detection_rules_prebuilt.spec.ts | 43 +- .../alerts_detection_rules_threshold.spec.ts | 153 +++--- .../integration/alerts_timeline.spec.ts | 2 +- .../security_solution/cypress/objects/rule.ts | 18 + .../cypress/screens/rule_details.ts | 46 +- .../security_solution/cypress/tasks/alerts.ts | 3 +- .../cypress/tasks/create_new_rule.ts | 11 +- .../components/rules/rule_status/index.tsx | 5 +- .../rules/schedule_item_form/index.tsx | 2 - 15 files changed, 628 insertions(+), 597 deletions(-) diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts.spec.ts index 3de57b085a9c6..64a864c936554 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts.spec.ts @@ -140,24 +140,25 @@ describe('Alerts', () => { waitForAlerts(); const expectedNumberOfAlerts = +numberOfAlerts - numberOfAlertsToBeClosed; - cy.get(NUMBER_OF_ALERTS).invoke('text').should('eq', expectedNumberOfAlerts.toString()); - cy.get(SHOWING_ALERTS) - .invoke('text') - .should('eql', `Showing ${expectedNumberOfAlerts.toString()} alerts`); + cy.get(NUMBER_OF_ALERTS).should('have.text', expectedNumberOfAlerts.toString()); + cy.get(SHOWING_ALERTS).should( + 'have.text', + `Showing ${expectedNumberOfAlerts.toString()} alerts` + ); goToClosedAlerts(); waitForAlerts(); - cy.get(NUMBER_OF_ALERTS) - .invoke('text') - .should('eql', numberOfAlertsToBeClosed.toString()); - cy.get(SHOWING_ALERTS) - .invoke('text') - .should('eql', `Showing ${numberOfAlertsToBeClosed.toString()} alert`); + cy.get(NUMBER_OF_ALERTS).should('have.text', numberOfAlertsToBeClosed.toString()); + cy.get(SHOWING_ALERTS).should( + 'have.text', + `Showing ${numberOfAlertsToBeClosed.toString()} alert` + ); cy.get(ALERTS).should('have.length', numberOfAlertsToBeClosed); }); }); }); + context('Opening alerts', () => { beforeEach(() => { esArchiverLoad('closed_alerts'); @@ -186,24 +187,25 @@ describe('Alerts', () => { waitForAlerts(); const expectedNumberOfAlerts = +numberOfAlerts - numberOfAlertsToBeOpened; - cy.get(NUMBER_OF_ALERTS).invoke('text').should('eq', expectedNumberOfAlerts.toString()); - cy.get(SHOWING_ALERTS) - .invoke('text') - .should('eql', `Showing ${expectedNumberOfAlerts.toString()} alerts`); + cy.get(NUMBER_OF_ALERTS).should('have.text', expectedNumberOfAlerts.toString()); + cy.get(SHOWING_ALERTS).should( + 'have.text', + `Showing ${expectedNumberOfAlerts.toString()} alerts` + ); goToOpenedAlerts(); waitForAlerts(); - cy.get(NUMBER_OF_ALERTS) - .invoke('text') - .should('eql', numberOfAlertsToBeOpened.toString()); - cy.get(SHOWING_ALERTS) - .invoke('text') - .should('eql', `Showing ${numberOfAlertsToBeOpened.toString()} alert`); + cy.get(NUMBER_OF_ALERTS).should('have.text', numberOfAlertsToBeOpened.toString()); + cy.get(SHOWING_ALERTS).should( + 'have.text', + `Showing ${numberOfAlertsToBeOpened.toString()} alert` + ); cy.get(ALERTS).should('have.length', numberOfAlertsToBeOpened); }); }); }); + context('Marking alerts as in-progress', () => { beforeEach(() => { esArchiverLoad('alerts'); @@ -231,20 +233,23 @@ describe('Alerts', () => { waitForAlerts(); const expectedNumberOfAlerts = +numberOfAlerts - numberOfAlertsToBeMarkedInProgress; - cy.get(NUMBER_OF_ALERTS).invoke('text').should('eq', expectedNumberOfAlerts.toString()); - cy.get(SHOWING_ALERTS) - .invoke('text') - .should('eql', `Showing ${expectedNumberOfAlerts.toString()} alerts`); + cy.get(NUMBER_OF_ALERTS).should('have.text', expectedNumberOfAlerts.toString()); + cy.get(SHOWING_ALERTS).should( + 'have.text', + `Showing ${expectedNumberOfAlerts.toString()} alerts` + ); goToInProgressAlerts(); waitForAlerts(); - cy.get(NUMBER_OF_ALERTS) - .invoke('text') - .should('eql', numberOfAlertsToBeMarkedInProgress.toString()); - cy.get(SHOWING_ALERTS) - .invoke('text') - .should('eql', `Showing ${numberOfAlertsToBeMarkedInProgress.toString()} alert`); + cy.get(NUMBER_OF_ALERTS).should( + 'have.text', + numberOfAlertsToBeMarkedInProgress.toString() + ); + cy.get(SHOWING_ALERTS).should( + 'have.text', + `Showing ${numberOfAlertsToBeMarkedInProgress.toString()} alert` + ); cy.get(ALERTS).should('have.length', numberOfAlertsToBeMarkedInProgress); }); }); diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules.spec.ts index 20cf624b3360d..3fa304ab7cf19 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules.spec.ts @@ -43,6 +43,7 @@ describe('Alerts detection rules', () => { waitForAlertsIndexToBeCreated(); goToManageAlertsDetectionRules(); waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded(); + cy.get(RULE_NAME) .eq(FIFTH_RULE) .invoke('text') @@ -56,7 +57,6 @@ describe('Alerts detection rules', () => { activateRule(SEVENTH_RULE); waitForRuleToBeActivated(); sortByActivatedRules(); - cy.get(RULE_NAME) .eq(FIRST_RULE) .invoke('text') @@ -70,7 +70,6 @@ describe('Alerts detection rules', () => { cy.wrap(expectedRulesNames).should('include', seventhRuleName); }); }); - cy.get(RULE_SWITCH).eq(FIRST_RULE).should('have.attr', 'role', 'switch'); cy.get(RULE_SWITCH).eq(SECOND_RULE).should('have.attr', 'role', 'switch'); }); diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts index 8229c92a582f4..1e541cf9c3fd1 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { newRule, existingRule } from '../objects/rule'; +import { newRule, existingRule, indexPatterns, editedRule } from '../objects/rule'; import { ALERT_RULE_METHOD, ALERT_RULE_NAME, @@ -20,20 +20,49 @@ import { RULE_NAME, RULES_ROW, RULES_TABLE, + RULE_SWITCH, SEVERITY, SHOWING_RULES_TEXT, } from '../screens/alerts_detection_rules'; import { + ABOUT_CONTINUE_BTN, + ABOUT_EDIT_BUTTON, + ACTIONS_THROTTLE_INPUT, + CUSTOM_QUERY_INPUT, + DEFINE_CONTINUE_BUTTON, + DEFINE_EDIT_BUTTON, + DEFINE_INDEX_INPUT, + RISK_INPUT, + RULE_DESCRIPTION_INPUT, + RULE_NAME_INPUT, + SCHEDULE_INTERVAL_AMOUNT_INPUT, + SCHEDULE_INTERVAL_UNITS_INPUT, + SEVERITY_DROPDOWN, + TAGS_FIELD, +} from '../screens/create_new_rule'; +import { + ADDITIONAL_LOOK_BACK_DETAILS, + ABOUT_DETAILS, ABOUT_INVESTIGATION_NOTES, ABOUT_RULE_DESCRIPTION, + CUSTOM_QUERY_DETAILS, + DEFINITION_DETAILS, + FALSE_POSITIVES_DETAILS, + getDetails, + INDEX_PATTERNS_DETAILS, INVESTIGATION_NOTES_MARKDOWN, INVESTIGATION_NOTES_TOGGLE, + MITRE_ATTACK_DETAILS, + REFERENCE_URLS_DETAILS, + RISK_SCORE_DETAILS, RULE_ABOUT_DETAILS_HEADER_TOGGLE, RULE_NAME_HEADER, - getDescriptionForTitle, - ABOUT_DETAILS, - DEFINITION_DETAILS, + RULE_TYPE_DETAILS, + RUNS_EVERY_DETAILS, SCHEDULE_DETAILS, + SEVERITY_DETAILS, + TAGS_DETAILS, + TIMELINE_TEMPLATE_DETAILS, } from '../screens/rule_details'; import { @@ -45,49 +74,57 @@ import { changeToThreeHundredRowsPerPage, deleteFirstRule, deleteSelectedRules, + editFirstRule, filterByCustomRules, goToCreateNewRule, goToRuleDetails, selectNumberOfRules, waitForLoadElasticPrebuiltDetectionRulesTableToBeLoaded, waitForRulesToBeLoaded, - editFirstRule, } from '../tasks/alerts_detection_rules'; import { createAndActivateRule, + fillAboutRule, fillAboutRuleAndContinue, fillDefineCustomRuleWithImportedQueryAndContinue, fillScheduleRuleAndContinue, goToAboutStepTab, - goToScheduleStepTab, goToActionsStepTab, - fillAboutRule, + goToScheduleStepTab, waitForTheRuleToBeExecuted, } from '../tasks/create_new_rule'; +import { saveEditedRule } from '../tasks/edit_rule'; import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver'; import { loginAndWaitForPageWithoutDateRange } from '../tasks/login'; import { refreshPage } from '../tasks/security_header'; import { DETECTIONS_URL } from '../urls/navigation'; -import { - ACTIONS_THROTTLE_INPUT, - CUSTOM_QUERY_INPUT, - DEFINE_INDEX_INPUT, - RULE_NAME_INPUT, - RULE_DESCRIPTION_INPUT, - TAGS_FIELD, - SEVERITY_DROPDOWN, - RISK_INPUT, - SCHEDULE_INTERVAL_AMOUNT_INPUT, - SCHEDULE_INTERVAL_UNITS_INPUT, - DEFINE_EDIT_BUTTON, - DEFINE_CONTINUE_BUTTON, - ABOUT_EDIT_BUTTON, - ABOUT_CONTINUE_BTN, -} from '../screens/create_new_rule'; -import { saveEditedRule } from '../tasks/edit_rule'; -describe('Detection rules, custom', () => { +let expectedUrls = ''; +newRule.referenceUrls.forEach((url) => { + expectedUrls = expectedUrls + url; +}); +let expectedFalsePositives = ''; +newRule.falsePositivesExamples.forEach((falsePositive) => { + expectedFalsePositives = expectedFalsePositives + falsePositive; +}); +let expectedTags = ''; +newRule.tags.forEach((tag) => { + expectedTags = expectedTags + tag; +}); +let expectedMitre = ''; +newRule.mitre.forEach((mitre) => { + expectedMitre = expectedMitre + mitre.tactic; + mitre.techniques.forEach((technique) => { + expectedMitre = expectedMitre + technique; + }); +}); +const expectedNumberOfRules = 1; +const expectedEditedtags = editedRule.tags.join(''); +const expectedEditedIndexPatterns = + editedRule.index && editedRule.index.length ? editedRule.index : indexPatterns; + +describe('Custom detection rules creation', () => { before(() => { esArchiverLoad('timeline'); }); @@ -96,7 +133,7 @@ describe('Detection rules, custom', () => { esArchiverUnload('timeline'); }); - it('Creates and activates a new custom rule', () => { + it('Creates and activates a new rule', () => { loginAndWaitForPageWithoutDateRange(DETECTIONS_URL); waitForAlertsPanelToBeLoaded(); waitForAlertsIndexToBeCreated(); @@ -109,27 +146,23 @@ describe('Detection rules, custom', () => { // expect define step to repopulate cy.get(DEFINE_EDIT_BUTTON).click(); - cy.get(CUSTOM_QUERY_INPUT).invoke('text').should('eq', newRule.customQuery); + cy.get(CUSTOM_QUERY_INPUT).should('have.text', newRule.customQuery); cy.get(DEFINE_CONTINUE_BUTTON).should('exist').click({ force: true }); cy.get(DEFINE_CONTINUE_BUTTON).should('not.exist'); // expect about step to populate cy.get(ABOUT_EDIT_BUTTON).click(); - cy.get(RULE_NAME_INPUT).invoke('val').should('eq', newRule.name); + cy.get(RULE_NAME_INPUT).invoke('val').should('eql', newRule.name); cy.get(ABOUT_CONTINUE_BTN).should('exist').click({ force: true }); cy.get(ABOUT_CONTINUE_BTN).should('not.exist'); createAndActivateRule(); - esArchiverLoad('auditbeat'); - waitForTheRuleToBeExecuted(newRule); - - cy.get(CUSTOM_RULES_BTN).invoke('text').should('eql', 'Custom rules (1)'); + cy.get(CUSTOM_RULES_BTN).should('have.text', 'Custom rules (1)'); changeToThreeHundredRowsPerPage(); waitForRulesToBeLoaded(); - const expectedNumberOfRules = 1; cy.get(RULES_TABLE).then(($table) => { cy.wrap($table.find(RULES_ROW).length).should('eql', expectedNumberOfRules); }); @@ -139,80 +172,42 @@ describe('Detection rules, custom', () => { cy.get(RULES_TABLE).then(($table) => { cy.wrap($table.find(RULES_ROW).length).should('eql', 1); }); - cy.get(RULE_NAME).invoke('text').should('eql', newRule.name); - cy.get(RISK_SCORE).invoke('text').should('eql', newRule.riskScore); - cy.get(SEVERITY).invoke('text').should('eql', newRule.severity); - cy.get('[data-test-subj="rule-switch"]').should('have.attr', 'aria-checked', 'true'); + cy.get(RULE_NAME).should('have.text', newRule.name); + cy.get(RISK_SCORE).should('have.text', newRule.riskScore); + cy.get(SEVERITY).should('have.text', newRule.severity); + cy.get(RULE_SWITCH).should('have.attr', 'aria-checked', 'true'); goToRuleDetails(); + waitForTheRuleToBeExecuted(); - let expectedUrls = ''; - newRule.referenceUrls.forEach((url) => { - expectedUrls = expectedUrls + url; - }); - let expectedFalsePositives = ''; - newRule.falsePositivesExamples.forEach((falsePositive) => { - expectedFalsePositives = expectedFalsePositives + falsePositive; - }); - let expectedTags = ''; - newRule.tags.forEach((tag) => { - expectedTags = expectedTags + tag; - }); - let expectedMitre = ''; - newRule.mitre.forEach((mitre) => { - expectedMitre = expectedMitre + mitre.tactic; - mitre.techniques.forEach((technique) => { - expectedMitre = expectedMitre + technique; - }); - }); - const expectedIndexPatterns = [ - 'apm-*-transaction*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ]; - - cy.get(RULE_NAME_HEADER).invoke('text').should('eql', `${newRule.name} Beta`); - - cy.get(ABOUT_RULE_DESCRIPTION).invoke('text').should('eql', newRule.description); + cy.get(RULE_NAME_HEADER).should('have.text', `${newRule.name} Beta`); + cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', newRule.description); cy.get(ABOUT_DETAILS).within(() => { - getDescriptionForTitle('Severity').invoke('text').should('eql', newRule.severity); - getDescriptionForTitle('Risk score').invoke('text').should('eql', newRule.riskScore); - getDescriptionForTitle('Reference URLs').invoke('text').should('eql', expectedUrls); - getDescriptionForTitle('False positive examples') - .invoke('text') - .should('eql', expectedFalsePositives); - getDescriptionForTitle('MITRE ATT&CK').invoke('text').should('eql', expectedMitre); - getDescriptionForTitle('Tags').invoke('text').should('eql', expectedTags); + getDetails(SEVERITY_DETAILS).should('have.text', newRule.severity); + getDetails(RISK_SCORE_DETAILS).should('have.text', newRule.riskScore); + getDetails(REFERENCE_URLS_DETAILS).should('have.text', expectedUrls); + getDetails(FALSE_POSITIVES_DETAILS).should('have.text', expectedFalsePositives); + getDetails(MITRE_ATTACK_DETAILS).should('have.text', expectedMitre); + getDetails(TAGS_DETAILS).should('have.text', expectedTags); }); - cy.get(RULE_ABOUT_DETAILS_HEADER_TOGGLE).eq(INVESTIGATION_NOTES_TOGGLE).click({ force: true }); - cy.get(ABOUT_INVESTIGATION_NOTES).invoke('text').should('eql', INVESTIGATION_NOTES_MARKDOWN); - + cy.get(ABOUT_INVESTIGATION_NOTES).should('have.text', INVESTIGATION_NOTES_MARKDOWN); cy.get(DEFINITION_DETAILS).within(() => { - getDescriptionForTitle('Index patterns') - .invoke('text') - .should('eql', expectedIndexPatterns.join('')); - getDescriptionForTitle('Custom query') - .invoke('text') - .should('eql', `${newRule.customQuery} `); - getDescriptionForTitle('Rule type').invoke('text').should('eql', 'Query'); - getDescriptionForTitle('Timeline template').invoke('text').should('eql', 'None'); + getDetails(INDEX_PATTERNS_DETAILS).should('have.text', indexPatterns.join('')); + getDetails(CUSTOM_QUERY_DETAILS).should('have.text', `${newRule.customQuery} `); + getDetails(RULE_TYPE_DETAILS).should('have.text', 'Query'); + getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', 'None'); + }); + cy.get(SCHEDULE_DETAILS).within(() => { + getDetails(RUNS_EVERY_DETAILS).should( + 'have.text', + `${newRule.runsEvery.interval}${newRule.runsEvery.type}` + ); + getDetails(ADDITIONAL_LOOK_BACK_DETAILS).should( + 'have.text', + `${newRule.lookBack.interval}${newRule.lookBack.type}` + ); }); - - cy.get('[data-test-subj=schedule] [data-test-subj="listItemColumnStepRuleDescription"]').within( - () => { - getDescriptionForTitle('Runs every') - .invoke('text') - .should('eql', `${newRule.runsEvery.interval}${newRule.runsEvery.type}`); - getDescriptionForTitle('Additional look-back time') - .invoke('text') - .should('eql', `${newRule.lookBack.interval}${newRule.lookBack.type}`); - } - ); refreshPage(); @@ -229,7 +224,7 @@ describe('Detection rules, custom', () => { }); }); -describe('Deletes custom rules', () => { +describe('Custom detection rules deletion and edition', () => { beforeEach(() => { esArchiverLoad('custom_rules'); loginAndWaitForPageWithoutDateRange(DETECTIONS_URL); @@ -242,143 +237,132 @@ describe('Deletes custom rules', () => { esArchiverUnload('custom_rules'); }); - it('Deletes one rule', () => { - cy.get(RULES_TABLE) - .find(RULES_ROW) - .then((rules) => { - const initialNumberOfRules = rules.length; - const expectedNumberOfRulesAfterDeletion = initialNumberOfRules - 1; - - cy.get(SHOWING_RULES_TEXT) - .invoke('text') - .should('eql', `Showing ${initialNumberOfRules} rules`); - - deleteFirstRule(); - waitForRulesToBeLoaded(); - - cy.get(RULES_TABLE).then(($table) => { - cy.wrap($table.find(RULES_ROW).length).should('eql', expectedNumberOfRulesAfterDeletion); + context('Deletion', () => { + it('Deletes one rule', () => { + cy.get(RULES_TABLE) + .find(RULES_ROW) + .then((rules) => { + const initialNumberOfRules = rules.length; + const expectedNumberOfRulesAfterDeletion = initialNumberOfRules - 1; + + cy.get(SHOWING_RULES_TEXT).should('have.text', `Showing ${initialNumberOfRules} rules`); + + deleteFirstRule(); + waitForRulesToBeLoaded(); + + cy.get(RULES_TABLE).then(($table) => { + cy.wrap($table.find(RULES_ROW).length).should( + 'eql', + expectedNumberOfRulesAfterDeletion + ); + }); + cy.get(SHOWING_RULES_TEXT).should( + 'have.text', + `Showing ${expectedNumberOfRulesAfterDeletion} rules` + ); + cy.get(CUSTOM_RULES_BTN).should( + 'have.text', + `Custom rules (${expectedNumberOfRulesAfterDeletion})` + ); }); - cy.get(SHOWING_RULES_TEXT) - .invoke('text') - .should('eql', `Showing ${expectedNumberOfRulesAfterDeletion} rules`); - cy.get(CUSTOM_RULES_BTN) - .invoke('text') - .should('eql', `Custom rules (${expectedNumberOfRulesAfterDeletion})`); - }); - }); - - it('Deletes more than one rule', () => { - cy.get(RULES_TABLE) - .find(RULES_ROW) - .then((rules) => { - const initialNumberOfRules = rules.length; - const numberOfRulesToBeDeleted = 3; - const expectedNumberOfRulesAfterDeletion = initialNumberOfRules - numberOfRulesToBeDeleted; - - selectNumberOfRules(numberOfRulesToBeDeleted); - deleteSelectedRules(); - waitForRulesToBeLoaded(); + }); - cy.get(RULES_TABLE).then(($table) => { - cy.wrap($table.find(RULES_ROW).length).should('eql', expectedNumberOfRulesAfterDeletion); + it('Deletes more than one rule', () => { + cy.get(RULES_TABLE) + .find(RULES_ROW) + .then((rules) => { + const initialNumberOfRules = rules.length; + const numberOfRulesToBeDeleted = 3; + const expectedNumberOfRulesAfterDeletion = + initialNumberOfRules - numberOfRulesToBeDeleted; + + selectNumberOfRules(numberOfRulesToBeDeleted); + deleteSelectedRules(); + waitForRulesToBeLoaded(); + + cy.get(RULES_TABLE).then(($table) => { + cy.wrap($table.find(RULES_ROW).length).should( + 'eql', + expectedNumberOfRulesAfterDeletion + ); + }); + cy.get(SHOWING_RULES_TEXT).should( + 'have.text', + `Showing ${expectedNumberOfRulesAfterDeletion} rule` + ); + cy.get(CUSTOM_RULES_BTN).should( + 'have.text', + `Custom rules (${expectedNumberOfRulesAfterDeletion})` + ); }); - cy.get(SHOWING_RULES_TEXT) - .invoke('text') - .should('eql', `Showing ${expectedNumberOfRulesAfterDeletion} rule`); - cy.get(CUSTOM_RULES_BTN) - .invoke('text') - .should('eql', `Custom rules (${expectedNumberOfRulesAfterDeletion})`); - }); + }); }); - it('Allows a rule to be edited', () => { - editFirstRule(); + context('Edition', () => { + it('Allows a rule to be edited', () => { + editFirstRule(); - // expect define step to populate - cy.get(CUSTOM_QUERY_INPUT).invoke('text').should('eq', existingRule.customQuery); - if (existingRule.index && existingRule.index.length > 0) { - cy.get(DEFINE_INDEX_INPUT).invoke('text').should('eq', existingRule.index.join('')); - } + // expect define step to populate + cy.get(CUSTOM_QUERY_INPUT).should('have.text', existingRule.customQuery); + if (existingRule.index && existingRule.index.length > 0) { + cy.get(DEFINE_INDEX_INPUT).should('have.text', existingRule.index.join('')); + } - goToAboutStepTab(); + goToAboutStepTab(); + + // expect about step to populate + cy.get(RULE_NAME_INPUT).invoke('val').should('eql', existingRule.name); + cy.get(RULE_DESCRIPTION_INPUT).should('have.text', existingRule.description); + cy.get(TAGS_FIELD).should('have.text', existingRule.tags.join('')); + cy.get(SEVERITY_DROPDOWN).should('have.text', existingRule.severity); + cy.get(RISK_INPUT).invoke('val').should('eql', existingRule.riskScore); + + goToScheduleStepTab(); + + // expect schedule step to populate + const intervalParts = + existingRule.interval && existingRule.interval.match(/[0-9]+|[a-zA-Z]+/g); + if (intervalParts) { + const [amount, unit] = intervalParts; + cy.get(SCHEDULE_INTERVAL_AMOUNT_INPUT).invoke('val').should('eql', amount); + cy.get(SCHEDULE_INTERVAL_UNITS_INPUT).invoke('val').should('eql', unit); + } else { + throw new Error('Cannot assert scheduling info on a rule without an interval'); + } - // expect about step to populate - cy.get(RULE_NAME_INPUT).invoke('val').should('eql', existingRule.name); - cy.get(RULE_DESCRIPTION_INPUT).invoke('text').should('eql', existingRule.description); - cy.get(TAGS_FIELD).invoke('text').should('eql', existingRule.tags.join('')); - - cy.get(SEVERITY_DROPDOWN).invoke('text').should('eql', existingRule.severity); - cy.get(RISK_INPUT).invoke('val').should('eql', existingRule.riskScore); - - goToScheduleStepTab(); - - // expect schedule step to populate - const intervalParts = existingRule.interval && existingRule.interval.match(/[0-9]+|[a-zA-Z]+/g); - if (intervalParts) { - const [amount, unit] = intervalParts; - cy.get(SCHEDULE_INTERVAL_AMOUNT_INPUT).invoke('val').should('eql', amount); - cy.get(SCHEDULE_INTERVAL_UNITS_INPUT).invoke('val').should('eql', unit); - } else { - throw new Error('Cannot assert scheduling info on a rule without an interval'); - } - - goToActionsStepTab(); - - cy.get(ACTIONS_THROTTLE_INPUT).invoke('val').should('eql', 'no_actions'); - - goToAboutStepTab(); - - const editedRule = { - ...existingRule, - severity: 'Medium', - description: 'Edited Rule description', - }; - - fillAboutRule(editedRule); - saveEditedRule(); - - const expectedTags = editedRule.tags.join(''); - const expectedIndexPatterns = - editedRule.index && editedRule.index.length - ? editedRule.index - : [ - 'apm-*-transaction*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ]; - - cy.get(RULE_NAME_HEADER).invoke('text').should('eql', `${editedRule.name} Beta`); - - cy.get(ABOUT_RULE_DESCRIPTION).invoke('text').should('eql', editedRule.description); - cy.get(ABOUT_DETAILS).within(() => { - getDescriptionForTitle('Severity').invoke('text').should('eql', editedRule.severity); - getDescriptionForTitle('Risk score').invoke('text').should('eql', editedRule.riskScore); - getDescriptionForTitle('Tags').invoke('text').should('eql', expectedTags); - }); + goToActionsStepTab(); - cy.get(RULE_ABOUT_DETAILS_HEADER_TOGGLE).eq(INVESTIGATION_NOTES_TOGGLE).click({ force: true }); - cy.get(ABOUT_INVESTIGATION_NOTES).invoke('text').should('eql', editedRule.note); + cy.get(ACTIONS_THROTTLE_INPUT).invoke('val').should('eql', 'no_actions'); - cy.get(DEFINITION_DETAILS).within(() => { - getDescriptionForTitle('Index patterns') - .invoke('text') - .should('eql', expectedIndexPatterns.join('')); - getDescriptionForTitle('Custom query') - .invoke('text') - .should('eql', `${editedRule.customQuery} `); - getDescriptionForTitle('Rule type').invoke('text').should('eql', 'Query'); - getDescriptionForTitle('Timeline template').invoke('text').should('eql', 'None'); - }); + goToAboutStepTab(); + fillAboutRule(editedRule); + saveEditedRule(); - if (editedRule.interval) { - cy.get(SCHEDULE_DETAILS).within(() => { - getDescriptionForTitle('Runs every').invoke('text').should('eql', editedRule.interval); + cy.get(RULE_NAME_HEADER).should('have.text', `${editedRule.name} Beta`); + cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', editedRule.description); + cy.get(ABOUT_DETAILS).within(() => { + getDetails(SEVERITY_DETAILS).should('have.text', editedRule.severity); + getDetails(RISK_SCORE_DETAILS).should('have.text', editedRule.riskScore); + getDetails(TAGS_DETAILS).should('have.text', expectedEditedtags); + }); + cy.get(RULE_ABOUT_DETAILS_HEADER_TOGGLE) + .eq(INVESTIGATION_NOTES_TOGGLE) + .click({ force: true }); + cy.get(ABOUT_INVESTIGATION_NOTES).should('have.text', editedRule.note); + cy.get(DEFINITION_DETAILS).within(() => { + getDetails(INDEX_PATTERNS_DETAILS).should( + 'have.text', + expectedEditedIndexPatterns.join('') + ); + getDetails(CUSTOM_QUERY_DETAILS).should('have.text', `${editedRule.customQuery} `); + getDetails(RULE_TYPE_DETAILS).should('have.text', 'Query'); + getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', 'None'); }); - } + if (editedRule.interval) { + cy.get(SCHEDULE_DETAILS).within(() => { + getDetails(RUNS_EVERY_DETAILS).should('have.text', editedRule.interval); + }); + } + }); }); }); diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_eql.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_eql.spec.ts index 76871929fe050..2e08fb5e6044c 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_eql.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_eql.spec.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { eqlRule } from '../objects/rule'; +import { eqlRule, indexPatterns } from '../objects/rule'; import { CUSTOM_RULES_BTN, @@ -12,19 +12,32 @@ import { RULE_NAME, RULES_ROW, RULES_TABLE, + RULE_SWITCH, SEVERITY, } from '../screens/alerts_detection_rules'; import { ABOUT_DETAILS, ABOUT_INVESTIGATION_NOTES, ABOUT_RULE_DESCRIPTION, + ADDITIONAL_LOOK_BACK_DETAILS, + CUSTOM_QUERY_DETAILS, DEFINITION_DETAILS, - getDescriptionForTitle, + FALSE_POSITIVES_DETAILS, + getDetails, + INDEX_PATTERNS_DETAILS, INVESTIGATION_NOTES_MARKDOWN, INVESTIGATION_NOTES_TOGGLE, + MITRE_ATTACK_DETAILS, + REFERENCE_URLS_DETAILS, + RISK_SCORE_DETAILS, RULE_ABOUT_DETAILS_HEADER_TOGGLE, RULE_NAME_HEADER, + RULE_TYPE_DETAILS, + RUNS_EVERY_DETAILS, SCHEDULE_DETAILS, + SEVERITY_DETAILS, + TAGS_DETAILS, + TIMELINE_TEMPLATE_DETAILS, } from '../screens/rule_details'; import { @@ -43,14 +56,36 @@ import { import { createAndActivateRule, fillAboutRuleAndContinue, - selectEqlRuleType, fillDefineEqlRuleAndContinue, + fillScheduleRuleAndContinue, + selectEqlRuleType, } from '../tasks/create_new_rule'; import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver'; import { loginAndWaitForPageWithoutDateRange } from '../tasks/login'; import { DETECTIONS_URL } from '../urls/navigation'; +let expectedUrls = ''; +eqlRule.referenceUrls.forEach((url) => { + expectedUrls = expectedUrls + url; +}); +let expectedFalsePositives = ''; +eqlRule.falsePositivesExamples.forEach((falsePositive) => { + expectedFalsePositives = expectedFalsePositives + falsePositive; +}); +let expectedTags = ''; +eqlRule.tags.forEach((tag) => { + expectedTags = expectedTags + tag; +}); +let expectedMitre = ''; +eqlRule.mitre.forEach((mitre) => { + expectedMitre = expectedMitre + mitre.tactic; + mitre.techniques.forEach((technique) => { + expectedMitre = expectedMitre + technique; + }); +}); +const expectedNumberOfRules = 1; + describe('Detection rules, EQL', () => { before(() => { esArchiverLoad('timeline'); @@ -70,14 +105,14 @@ describe('Detection rules, EQL', () => { selectEqlRuleType(); fillDefineEqlRuleAndContinue(eqlRule); fillAboutRuleAndContinue(eqlRule); + fillScheduleRuleAndContinue(eqlRule); createAndActivateRule(); - cy.get(CUSTOM_RULES_BTN).invoke('text').should('eql', 'Custom rules (1)'); + cy.get(CUSTOM_RULES_BTN).should('have.text', 'Custom rules (1)'); changeToThreeHundredRowsPerPage(); waitForRulesToBeLoaded(); - const expectedNumberOfRules = 1; cy.get(RULES_TABLE).then(($table) => { cy.wrap($table.find(RULES_ROW).length).should('eql', expectedNumberOfRules); }); @@ -87,73 +122,40 @@ describe('Detection rules, EQL', () => { cy.get(RULES_TABLE).then(($table) => { cy.wrap($table.find(RULES_ROW).length).should('eql', 1); }); - cy.get(RULE_NAME).invoke('text').should('eql', eqlRule.name); - cy.get(RISK_SCORE).invoke('text').should('eql', eqlRule.riskScore); - cy.get(SEVERITY).invoke('text').should('eql', eqlRule.severity); - cy.get('[data-test-subj="rule-switch"]').should('have.attr', 'aria-checked', 'true'); + cy.get(RULE_NAME).should('have.text', eqlRule.name); + cy.get(RISK_SCORE).should('have.text', eqlRule.riskScore); + cy.get(SEVERITY).should('have.text', eqlRule.severity); + cy.get(RULE_SWITCH).should('have.attr', 'aria-checked', 'true'); goToRuleDetails(); - let expectedUrls = ''; - eqlRule.referenceUrls.forEach((url) => { - expectedUrls = expectedUrls + url; - }); - let expectedFalsePositives = ''; - eqlRule.falsePositivesExamples.forEach((falsePositive) => { - expectedFalsePositives = expectedFalsePositives + falsePositive; - }); - let expectedTags = ''; - eqlRule.tags.forEach((tag) => { - expectedTags = expectedTags + tag; - }); - let expectedMitre = ''; - eqlRule.mitre.forEach((mitre) => { - expectedMitre = expectedMitre + mitre.tactic; - mitre.techniques.forEach((technique) => { - expectedMitre = expectedMitre + technique; - }); - }); - const expectedIndexPatterns = [ - 'apm-*-transaction*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ]; - - cy.get(RULE_NAME_HEADER).invoke('text').should('eql', `${eqlRule.name} Beta`); - - cy.get(ABOUT_RULE_DESCRIPTION).invoke('text').should('eql', eqlRule.description); + cy.get(RULE_NAME_HEADER).should('have.text', `${eqlRule.name} Beta`); + cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', eqlRule.description); cy.get(ABOUT_DETAILS).within(() => { - getDescriptionForTitle('Severity').invoke('text').should('eql', eqlRule.severity); - getDescriptionForTitle('Risk score').invoke('text').should('eql', eqlRule.riskScore); - getDescriptionForTitle('Reference URLs').invoke('text').should('eql', expectedUrls); - getDescriptionForTitle('False positive examples') - .invoke('text') - .should('eql', expectedFalsePositives); - getDescriptionForTitle('MITRE ATT&CK').invoke('text').should('eql', expectedMitre); - getDescriptionForTitle('Tags').invoke('text').should('eql', expectedTags); + getDetails(SEVERITY_DETAILS).should('have.text', eqlRule.severity); + getDetails(RISK_SCORE_DETAILS).should('have.text', eqlRule.riskScore); + getDetails(REFERENCE_URLS_DETAILS).should('have.text', expectedUrls); + getDetails(FALSE_POSITIVES_DETAILS).should('have.text', expectedFalsePositives); + getDetails(MITRE_ATTACK_DETAILS).should('have.text', expectedMitre); + getDetails(TAGS_DETAILS).should('have.text', expectedTags); }); - cy.get(RULE_ABOUT_DETAILS_HEADER_TOGGLE).eq(INVESTIGATION_NOTES_TOGGLE).click({ force: true }); - cy.get(ABOUT_INVESTIGATION_NOTES).invoke('text').should('eql', INVESTIGATION_NOTES_MARKDOWN); - + cy.get(ABOUT_INVESTIGATION_NOTES).should('have.text', INVESTIGATION_NOTES_MARKDOWN); cy.get(DEFINITION_DETAILS).within(() => { - getDescriptionForTitle('Index patterns') - .invoke('text') - .should('eql', expectedIndexPatterns.join('')); - getDescriptionForTitle('Custom query') - .invoke('text') - .should('eql', `${eqlRule.customQuery} `); - getDescriptionForTitle('Rule type').invoke('text').should('eql', 'Event Correlation'); - getDescriptionForTitle('Timeline template').invoke('text').should('eql', 'None'); + getDetails(INDEX_PATTERNS_DETAILS).should('have.text', indexPatterns.join('')); + getDetails(CUSTOM_QUERY_DETAILS).should('have.text', `${eqlRule.customQuery} `); + getDetails(RULE_TYPE_DETAILS).should('have.text', 'Event Correlation'); + getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', 'None'); }); - cy.get(SCHEDULE_DETAILS).within(() => { - getDescriptionForTitle('Runs every').invoke('text').should('eql', '5m'); - getDescriptionForTitle('Additional look-back time').invoke('text').should('eql', '1m'); + getDetails(RUNS_EVERY_DETAILS).should( + 'have.text', + `${eqlRule.runsEvery.interval}${eqlRule.runsEvery.type}` + ); + getDetails(ADDITIONAL_LOOK_BACK_DETAILS).should( + 'have.text', + `${eqlRule.lookBack.interval}${eqlRule.lookBack.type}` + ); }); }); }); diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_ml.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_ml.spec.ts index 3a79d13ccc679..8011a47560ed8 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_ml.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_ml.spec.ts @@ -16,13 +16,25 @@ import { SEVERITY, } from '../screens/alerts_detection_rules'; import { + ABOUT_DETAILS, ABOUT_RULE_DESCRIPTION, + ADDITIONAL_LOOK_BACK_DETAILS, + ANOMALY_SCORE_DETAILS, + DEFINITION_DETAILS, + FALSE_POSITIVES_DETAILS, + getDetails, MACHINE_LEARNING_JOB_ID, MACHINE_LEARNING_JOB_STATUS, + MITRE_ATTACK_DETAILS, + REFERENCE_URLS_DETAILS, + RISK_SCORE_DETAILS, RULE_NAME_HEADER, - getDescriptionForTitle, - ABOUT_DETAILS, - DEFINITION_DETAILS, + RULE_TYPE_DETAILS, + RUNS_EVERY_DETAILS, + SCHEDULE_DETAILS, + SEVERITY_DETAILS, + TAGS_DETAILS, + TIMELINE_TEMPLATE_DETAILS, } from '../screens/rule_details'; import { @@ -50,6 +62,27 @@ import { loginAndWaitForPageWithoutDateRange } from '../tasks/login'; import { DETECTIONS_URL } from '../urls/navigation'; +let expectedUrls = ''; +machineLearningRule.referenceUrls.forEach((url) => { + expectedUrls = expectedUrls + url; +}); +let expectedFalsePositives = ''; +machineLearningRule.falsePositivesExamples.forEach((falsePositive) => { + expectedFalsePositives = expectedFalsePositives + falsePositive; +}); +let expectedTags = ''; +machineLearningRule.tags.forEach((tag) => { + expectedTags = expectedTags + tag; +}); +let expectedMitre = ''; +machineLearningRule.mitre.forEach((mitre) => { + expectedMitre = expectedMitre + mitre.tactic; + mitre.techniques.forEach((technique) => { + expectedMitre = expectedMitre + technique; + }); +}); +const expectedNumberOfRules = totalNumberOfPrebuiltRulesInEsArchive + 1; + describe('Detection rules, machine learning', () => { before(() => { esArchiverLoad('prebuilt_rules_loaded'); @@ -77,7 +110,6 @@ describe('Detection rules, machine learning', () => { changeToThreeHundredRowsPerPage(); waitForRulesToBeLoaded(); - const expectedNumberOfRules = totalNumberOfPrebuiltRulesInEsArchive + 1; cy.get(RULES_TABLE).then(($table) => { cy.wrap($table.find(RULES_ROW).length).should('eql', expectedNumberOfRules); }); @@ -87,79 +119,42 @@ describe('Detection rules, machine learning', () => { cy.get(RULES_TABLE).then(($table) => { cy.wrap($table.find(RULES_ROW).length).should('eql', 1); }); - cy.get(RULE_NAME).invoke('text').should('eql', machineLearningRule.name); - cy.get(RISK_SCORE).invoke('text').should('eql', machineLearningRule.riskScore); - cy.get(SEVERITY).invoke('text').should('eql', machineLearningRule.severity); + cy.get(RULE_NAME).should('have.text', machineLearningRule.name); + cy.get(RISK_SCORE).should('have.text', machineLearningRule.riskScore); + cy.get(SEVERITY).should('have.text', machineLearningRule.severity); cy.get(RULE_SWITCH).should('have.attr', 'aria-checked', 'true'); goToRuleDetails(); - let expectedUrls = ''; - machineLearningRule.referenceUrls.forEach((url) => { - expectedUrls = expectedUrls + url; - }); - let expectedFalsePositives = ''; - machineLearningRule.falsePositivesExamples.forEach((falsePositive) => { - expectedFalsePositives = expectedFalsePositives + falsePositive; - }); - let expectedTags = ''; - machineLearningRule.tags.forEach((tag) => { - expectedTags = expectedTags + tag; - }); - let expectedMitre = ''; - machineLearningRule.mitre.forEach((mitre) => { - expectedMitre = expectedMitre + mitre.tactic; - mitre.techniques.forEach((technique) => { - expectedMitre = expectedMitre + technique; - }); - }); - - cy.get(RULE_NAME_HEADER).invoke('text').should('eql', `${machineLearningRule.name} Beta`); - - cy.get(ABOUT_RULE_DESCRIPTION).invoke('text').should('eql', machineLearningRule.description); + cy.get(RULE_NAME_HEADER).should('have.text', `${machineLearningRule.name} Beta`); + cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', machineLearningRule.description); cy.get(ABOUT_DETAILS).within(() => { - getDescriptionForTitle('Severity').invoke('text').should('eql', machineLearningRule.severity); - getDescriptionForTitle('Risk score') - .invoke('text') - .should('eql', machineLearningRule.riskScore); - getDescriptionForTitle('Reference URLs').invoke('text').should('eql', expectedUrls); - getDescriptionForTitle('False positive examples') - .invoke('text') - .should('eql', expectedFalsePositives); - getDescriptionForTitle('MITRE ATT&CK').invoke('text').should('eql', expectedMitre); - getDescriptionForTitle('Tags').invoke('text').should('eql', expectedTags); + getDetails(SEVERITY_DETAILS).should('have.text', machineLearningRule.severity); + getDetails(RISK_SCORE_DETAILS).should('have.text', machineLearningRule.riskScore); + getDetails(REFERENCE_URLS_DETAILS).should('have.text', expectedUrls); + getDetails(FALSE_POSITIVES_DETAILS).should('have.text', expectedFalsePositives); + getDetails(MITRE_ATTACK_DETAILS).should('have.text', expectedMitre); + getDetails(TAGS_DETAILS).should('have.text', expectedTags); }); - cy.get(DEFINITION_DETAILS).within(() => { - getDescriptionForTitle('Anomaly score') - .invoke('text') - .should('eql', machineLearningRule.anomalyScoreThreshold); - getDescriptionForTitle('Anomaly score') - .invoke('text') - .should('eql', machineLearningRule.anomalyScoreThreshold); - getDescriptionForTitle('Rule type').invoke('text').should('eql', 'Machine Learning'); - getDescriptionForTitle('Timeline template').invoke('text').should('eql', 'None'); - cy.get(MACHINE_LEARNING_JOB_STATUS).invoke('text').should('eql', 'Stopped'); - cy.get(MACHINE_LEARNING_JOB_ID) - .invoke('text') - .should('eql', machineLearningRule.machineLearningJob); + getDetails(ANOMALY_SCORE_DETAILS).should( + 'have.text', + machineLearningRule.anomalyScoreThreshold + ); + getDetails(RULE_TYPE_DETAILS).should('have.text', 'Machine Learning'); + getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', 'None'); + cy.get(MACHINE_LEARNING_JOB_STATUS).should('have.text', 'Stopped'); + cy.get(MACHINE_LEARNING_JOB_ID).should('have.text', machineLearningRule.machineLearningJob); + }); + cy.get(SCHEDULE_DETAILS).within(() => { + getDetails(RUNS_EVERY_DETAILS).should( + 'have.text', + `${machineLearningRule.runsEvery.interval}${machineLearningRule.runsEvery.type}` + ); + getDetails(ADDITIONAL_LOOK_BACK_DETAILS).should( + 'have.text', + `${machineLearningRule.lookBack.interval}${machineLearningRule.lookBack.type}` + ); }); - - cy.get('[data-test-subj=schedule] [data-test-subj="listItemColumnStepRuleDescription"]').within( - () => { - getDescriptionForTitle('Runs every') - .invoke('text') - .should( - 'eql', - `${machineLearningRule.runsEvery.interval}${machineLearningRule.runsEvery.type}` - ); - getDescriptionForTitle('Additional look-back time') - .invoke('text') - .should( - 'eql', - `${machineLearningRule.lookBack.interval}${machineLearningRule.lookBack.type}` - ); - } - ); }); }); diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_override.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_override.spec.ts index aeb836228e364..0632a878dfecc 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_override.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_override.spec.ts @@ -4,36 +4,53 @@ * you may not use this file except in compliance with the Elastic License. */ -import { newOverrideRule } from '../objects/rule'; +import { indexPatterns, newOverrideRule, severitiesOverride } from '../objects/rule'; import { NUMBER_OF_ALERTS, ALERT_RULE_NAME, - ALERT_RULE_VERSION, ALERT_RULE_METHOD, - ALERT_RULE_SEVERITY, ALERT_RULE_RISK_SCORE, + ALERT_RULE_SEVERITY, + ALERT_RULE_VERSION, } from '../screens/alerts'; import { CUSTOM_RULES_BTN, RISK_SCORE, RULE_NAME, + RULE_SWITCH, RULES_ROW, RULES_TABLE, SEVERITY, } from '../screens/alerts_detection_rules'; import { ABOUT_INVESTIGATION_NOTES, + ABOUT_DETAILS, ABOUT_RULE_DESCRIPTION, + ADDITIONAL_LOOK_BACK_DETAILS, + CUSTOM_QUERY_DETAILS, + DEFINITION_DETAILS, + DETAILS_DESCRIPTION, + DETAILS_TITLE, + FALSE_POSITIVES_DETAILS, + getDetails, + INDEX_PATTERNS_DETAILS, INVESTIGATION_NOTES_MARKDOWN, INVESTIGATION_NOTES_TOGGLE, + MITRE_ATTACK_DETAILS, + REFERENCE_URLS_DETAILS, + RISK_SCORE_DETAILS, + RISK_SCORE_OVERRIDE_DETAILS, RULE_ABOUT_DETAILS_HEADER_TOGGLE, RULE_NAME_HEADER, - ABOUT_DETAILS, - getDescriptionForTitle, - DEFINITION_DETAILS, - DETAILS_TITLE, - DETAILS_DESCRIPTION, + RULE_NAME_OVERRIDE_DETAILS, + RULE_TYPE_DETAILS, + RUNS_EVERY_DETAILS, + SCHEDULE_DETAILS, + SEVERITY_DETAILS, + TAGS_DETAILS, + TIMELINE_TEMPLATE_DETAILS, + TIMESTAMP_OVERRIDE_DETAILS, } from '../screens/rule_details'; import { @@ -63,6 +80,26 @@ import { refreshPage } from '../tasks/security_header'; import { DETECTIONS_URL } from '../urls/navigation'; +let expectedUrls = ''; +newOverrideRule.referenceUrls.forEach((url) => { + expectedUrls = expectedUrls + url; +}); +let expectedFalsePositives = ''; +newOverrideRule.falsePositivesExamples.forEach((falsePositive) => { + expectedFalsePositives = expectedFalsePositives + falsePositive; +}); +let expectedTags = ''; +newOverrideRule.tags.forEach((tag) => { + expectedTags = expectedTags + tag; +}); +let expectedMitre = ''; +newOverrideRule.mitre.forEach((mitre) => { + expectedMitre = expectedMitre + mitre.tactic; + mitre.techniques.forEach((technique) => { + expectedMitre = expectedMitre + technique; + }); +}); + describe('Detection rules, override', () => { before(() => { esArchiverLoad('timeline'); @@ -84,10 +121,7 @@ describe('Detection rules, override', () => { fillScheduleRuleAndContinue(newOverrideRule); createAndActivateRule(); - esArchiverLoad('auditbeat'); - waitForTheRuleToBeExecuted(newOverrideRule); - - cy.get(CUSTOM_RULES_BTN).invoke('text').should('eql', 'Custom rules (1)'); + cy.get(CUSTOM_RULES_BTN).should('have.text', 'Custom rules (1)'); changeToThreeHundredRowsPerPage(); waitForRulesToBeLoaded(); @@ -102,105 +136,60 @@ describe('Detection rules, override', () => { cy.get(RULES_TABLE).then(($table) => { cy.wrap($table.find(RULES_ROW).length).should('eql', 1); }); - cy.get(RULE_NAME).invoke('text').should('eql', newOverrideRule.name); - cy.get(RISK_SCORE).invoke('text').should('eql', newOverrideRule.riskScore); - cy.get(SEVERITY).invoke('text').should('eql', newOverrideRule.severity); - cy.get('[data-test-subj="rule-switch"]').should('have.attr', 'aria-checked', 'true'); + cy.get(RULE_NAME).should('have.text', newOverrideRule.name); + cy.get(RISK_SCORE).should('have.text', newOverrideRule.riskScore); + cy.get(SEVERITY).should('have.text', newOverrideRule.severity); + cy.get(RULE_SWITCH).should('have.attr', 'aria-checked', 'true'); goToRuleDetails(); + waitForTheRuleToBeExecuted(); - let expectedUrls = ''; - newOverrideRule.referenceUrls.forEach((url) => { - expectedUrls = expectedUrls + url; - }); - let expectedFalsePositives = ''; - newOverrideRule.falsePositivesExamples.forEach((falsePositive) => { - expectedFalsePositives = expectedFalsePositives + falsePositive; - }); - let expectedTags = ''; - newOverrideRule.tags.forEach((tag) => { - expectedTags = expectedTags + tag; - }); - let expectedMitre = ''; - newOverrideRule.mitre.forEach((mitre) => { - expectedMitre = expectedMitre + mitre.tactic; - mitre.techniques.forEach((technique) => { - expectedMitre = expectedMitre + technique; - }); - }); - const expectedIndexPatterns = [ - 'apm-*-transaction*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ]; - - cy.get(RULE_NAME_HEADER).invoke('text').should('eql', `${newOverrideRule.name} Beta`); - - cy.get(ABOUT_RULE_DESCRIPTION).invoke('text').should('eql', newOverrideRule.description); - - const expectedOverrideSeverities = ['Low', 'Medium', 'High', 'Critical']; - + cy.get(RULE_NAME_HEADER).should('have.text', `${newOverrideRule.name} Beta`); + cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', newOverrideRule.description); cy.get(ABOUT_DETAILS).within(() => { - getDescriptionForTitle('Severity').invoke('text').should('eql', newOverrideRule.severity); - getDescriptionForTitle('Risk score').invoke('text').should('eql', newOverrideRule.riskScore); - getDescriptionForTitle('Risk score override') - .invoke('text') - .should('eql', `${newOverrideRule.riskOverride}signal.rule.risk_score`); - getDescriptionForTitle('Rule name override') - .invoke('text') - .should('eql', newOverrideRule.nameOverride); - getDescriptionForTitle('Reference URLs').invoke('text').should('eql', expectedUrls); - getDescriptionForTitle('False positive examples') - .invoke('text') - .should('eql', expectedFalsePositives); - getDescriptionForTitle('MITRE ATT&CK').invoke('text').should('eql', expectedMitre); - getDescriptionForTitle('Tags').invoke('text').should('eql', expectedTags); - getDescriptionForTitle('Timestamp override') - .invoke('text') - .should('eql', newOverrideRule.timestampOverride); + getDetails(SEVERITY_DETAILS).should('have.text', newOverrideRule.severity); + getDetails(RISK_SCORE_DETAILS).should('have.text', newOverrideRule.riskScore); + getDetails(RISK_SCORE_OVERRIDE_DETAILS).should( + 'have.text', + `${newOverrideRule.riskOverride}signal.rule.risk_score` + ); + getDetails(RULE_NAME_OVERRIDE_DETAILS).should('have.text', newOverrideRule.nameOverride); + getDetails(REFERENCE_URLS_DETAILS).should('have.text', expectedUrls); + getDetails(FALSE_POSITIVES_DETAILS).should('have.text', expectedFalsePositives); + getDetails(MITRE_ATTACK_DETAILS).should('have.text', expectedMitre); + getDetails(TAGS_DETAILS).should('have.text', expectedTags); + getDetails(TIMESTAMP_OVERRIDE_DETAILS).should('have.text', newOverrideRule.timestampOverride); cy.contains(DETAILS_TITLE, 'Severity override') .invoke('index', DETAILS_TITLE) // get index relative to other titles, not all siblings .then((severityOverrideIndex) => { newOverrideRule.severityOverride.forEach((severity, i) => { cy.get(DETAILS_DESCRIPTION) .eq(severityOverrideIndex + i) - .invoke('text') .should( - 'eql', - `${severity.sourceField}:${severity.sourceValue}${expectedOverrideSeverities[i]}` + 'have.text', + `${severity.sourceField}:${severity.sourceValue}${severitiesOverride[i]}` ); }); }); }); - cy.get(RULE_ABOUT_DETAILS_HEADER_TOGGLE).eq(INVESTIGATION_NOTES_TOGGLE).click({ force: true }); - cy.get(ABOUT_INVESTIGATION_NOTES).invoke('text').should('eql', INVESTIGATION_NOTES_MARKDOWN); - + cy.get(ABOUT_INVESTIGATION_NOTES).should('have.text', INVESTIGATION_NOTES_MARKDOWN); cy.get(DEFINITION_DETAILS).within(() => { - getDescriptionForTitle('Index patterns') - .invoke('text') - .should('eql', expectedIndexPatterns.join('')); - getDescriptionForTitle('Custom query') - .invoke('text') - .should('eql', `${newOverrideRule.customQuery} `); - getDescriptionForTitle('Rule type').invoke('text').should('eql', 'Query'); - getDescriptionForTitle('Timeline template').invoke('text').should('eql', 'None'); + getDetails(INDEX_PATTERNS_DETAILS).should('have.text', indexPatterns.join('')); + getDetails(CUSTOM_QUERY_DETAILS).should('have.text', `${newOverrideRule.customQuery} `); + getDetails(RULE_TYPE_DETAILS).should('have.text', 'Query'); + getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', 'None'); + }); + cy.get(SCHEDULE_DETAILS).within(() => { + getDetails(RUNS_EVERY_DETAILS).should( + 'have.text', + `${newOverrideRule.runsEvery.interval}${newOverrideRule.runsEvery.type}` + ); + getDetails(ADDITIONAL_LOOK_BACK_DETAILS).should( + 'have.text', + `${newOverrideRule.lookBack.interval}${newOverrideRule.lookBack.type}` + ); }); - - cy.get('[data-test-subj=schedule] [data-test-subj="listItemColumnStepRuleDescription"]').within( - () => { - getDescriptionForTitle('Runs every') - .invoke('text') - .should('eql', `${newOverrideRule.runsEvery.interval}${newOverrideRule.runsEvery.type}`); - getDescriptionForTitle('Additional look-back time') - .invoke('text') - .should('eql', `${newOverrideRule.lookBack.interval}${newOverrideRule.lookBack.type}`); - } - ); refreshPage(); diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_prebuilt.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_prebuilt.spec.ts index 986a7c7177a79..6088a9dedbd06 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_prebuilt.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_prebuilt.spec.ts @@ -56,7 +56,7 @@ describe('Alerts rules, prebuilt rules', () => { loadPrebuiltDetectionRules(); waitForPrebuiltDetectionRulesToBeLoaded(); - cy.get(ELASTIC_RULES_BTN).invoke('text').should('eql', expectedElasticRulesBtnText); + cy.get(ELASTIC_RULES_BTN).should('have.text', expectedElasticRulesBtnText); changeToThreeHundredRowsPerPage(); waitForRulesToBeLoaded(); @@ -81,7 +81,7 @@ describe('Deleting prebuilt rules', () => { loadPrebuiltDetectionRules(); waitForPrebuiltDetectionRulesToBeLoaded(); - cy.get(ELASTIC_RULES_BTN).invoke('text').should('eql', expectedElasticRulesBtnText); + cy.get(ELASTIC_RULES_BTN).should('have.text', expectedElasticRulesBtnText); changeToThreeHundredRowsPerPage(); waitForRulesToBeLoaded(); @@ -113,16 +113,15 @@ describe('Deleting prebuilt rules', () => { changeToThreeHundredRowsPerPage(); waitForRulesToBeLoaded(); - cy.get(ELASTIC_RULES_BTN) - .invoke('text') - .should('eql', `Elastic rules (${expectedNumberOfRulesAfterDeletion})`); + cy.get(ELASTIC_RULES_BTN).should( + 'have.text', + `Elastic rules (${expectedNumberOfRulesAfterDeletion})` + ); cy.get(RULES_TABLE).then(($table) => { cy.wrap($table.find(RULES_ROW).length).should('eql', expectedNumberOfRulesAfterDeletion); }); cy.get(RELOAD_PREBUILT_RULES_BTN).should('exist'); - cy.get(RELOAD_PREBUILT_RULES_BTN) - .invoke('text') - .should('eql', 'Install 1 Elastic prebuilt rule '); + cy.get(RELOAD_PREBUILT_RULES_BTN).should('have.text', 'Install 1 Elastic prebuilt rule '); reloadDeletedRules(); @@ -135,9 +134,10 @@ describe('Deleting prebuilt rules', () => { cy.get(RULES_TABLE).then(($table) => { cy.wrap($table.find(RULES_ROW).length).should('eql', expectedNumberOfRulesAfterRecovering); }); - cy.get(ELASTIC_RULES_BTN) - .invoke('text') - .should('eql', `Elastic rules (${expectedNumberOfRulesAfterRecovering})`); + cy.get(ELASTIC_RULES_BTN).should( + 'have.text', + `Elastic rules (${expectedNumberOfRulesAfterRecovering})` + ); }); it('Deletes and recovers more than one rule', () => { @@ -152,12 +152,14 @@ describe('Deleting prebuilt rules', () => { waitForRulesToBeLoaded(); cy.get(RELOAD_PREBUILT_RULES_BTN).should('exist'); - cy.get(RELOAD_PREBUILT_RULES_BTN) - .invoke('text') - .should('eql', `Install ${numberOfRulesToBeSelected} Elastic prebuilt rules `); - cy.get(ELASTIC_RULES_BTN) - .invoke('text') - .should('eql', `Elastic rules (${expectedNumberOfRulesAfterDeletion})`); + cy.get(RELOAD_PREBUILT_RULES_BTN).should( + 'have.text', + `Install ${numberOfRulesToBeSelected} Elastic prebuilt rules ` + ); + cy.get(ELASTIC_RULES_BTN).should( + 'have.text', + `Elastic rules (${expectedNumberOfRulesAfterDeletion})` + ); cy.get(RULES_TABLE).then(($table) => { cy.wrap($table.find(RULES_ROW).length).should('eql', expectedNumberOfRulesAfterDeletion); }); @@ -173,8 +175,9 @@ describe('Deleting prebuilt rules', () => { cy.get(RULES_TABLE).then(($table) => { cy.wrap($table.find(RULES_ROW).length).should('eql', expectedNumberOfRulesAfterRecovering); }); - cy.get(ELASTIC_RULES_BTN) - .invoke('text') - .should('eql', `Elastic rules (${expectedNumberOfRulesAfterRecovering})`); + cy.get(ELASTIC_RULES_BTN).should( + 'have.text', + `Elastic rules (${expectedNumberOfRulesAfterRecovering})` + ); }); }); diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_threshold.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_threshold.spec.ts index 5f23d801481c1..0eb4dad76925f 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_threshold.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_threshold.spec.ts @@ -4,7 +4,7 @@ * you may not use this file except in compliance with the Elastic License. */ -import { newThresholdRule } from '../objects/rule'; +import { indexPatterns, newThresholdRule } from '../objects/rule'; import { ALERT_RULE_METHOD, ALERT_RULE_NAME, @@ -18,20 +18,35 @@ import { CUSTOM_RULES_BTN, RISK_SCORE, RULE_NAME, + RULE_SWITCH, RULES_ROW, RULES_TABLE, SEVERITY, } from '../screens/alerts_detection_rules'; import { + ABOUT_DETAILS, ABOUT_INVESTIGATION_NOTES, ABOUT_RULE_DESCRIPTION, + ADDITIONAL_LOOK_BACK_DETAILS, + CUSTOM_QUERY_DETAILS, + FALSE_POSITIVES_DETAILS, + DEFINITION_DETAILS, + getDetails, + INDEX_PATTERNS_DETAILS, INVESTIGATION_NOTES_MARKDOWN, INVESTIGATION_NOTES_TOGGLE, + MITRE_ATTACK_DETAILS, + REFERENCE_URLS_DETAILS, + RISK_SCORE_DETAILS, RULE_ABOUT_DETAILS_HEADER_TOGGLE, RULE_NAME_HEADER, - getDescriptionForTitle, - ABOUT_DETAILS, - DEFINITION_DETAILS, + RULE_TYPE_DETAILS, + RUNS_EVERY_DETAILS, + SCHEDULE_DETAILS, + SEVERITY_DETAILS, + TAGS_DETAILS, + THRESHOLD_DETAILS, + TIMELINE_TEMPLATE_DETAILS, } from '../screens/rule_details'; import { @@ -53,6 +68,7 @@ import { fillDefineThresholdRuleAndContinue, fillScheduleRuleAndContinue, selectThresholdRuleType, + waitForTheRuleToBeExecuted, } from '../tasks/create_new_rule'; import { esArchiverLoad, esArchiverUnload } from '../tasks/es_archiver'; import { loginAndWaitForPageWithoutDateRange } from '../tasks/login'; @@ -60,6 +76,26 @@ import { refreshPage } from '../tasks/security_header'; import { DETECTIONS_URL } from '../urls/navigation'; +let expectedUrls = ''; +newThresholdRule.referenceUrls.forEach((url) => { + expectedUrls = expectedUrls + url; +}); +let expectedFalsePositives = ''; +newThresholdRule.falsePositivesExamples.forEach((falsePositive) => { + expectedFalsePositives = expectedFalsePositives + falsePositive; +}); +let expectedTags = ''; +newThresholdRule.tags.forEach((tag) => { + expectedTags = expectedTags + tag; +}); +let expectedMitre = ''; +newThresholdRule.mitre.forEach((mitre) => { + expectedMitre = expectedMitre + mitre.tactic; + mitre.techniques.forEach((technique) => { + expectedMitre = expectedMitre + technique; + }); +}); + describe('Detection rules, threshold', () => { before(() => { esArchiverLoad('timeline'); @@ -82,7 +118,7 @@ describe('Detection rules, threshold', () => { fillScheduleRuleAndContinue(newThresholdRule); createAndActivateRule(); - cy.get(CUSTOM_RULES_BTN).invoke('text').should('eql', 'Custom rules (1)'); + cy.get(CUSTOM_RULES_BTN).should('have.text', 'Custom rules (1)'); changeToThreeHundredRowsPerPage(); waitForRulesToBeLoaded(); @@ -97,89 +133,46 @@ describe('Detection rules, threshold', () => { cy.get(RULES_TABLE).then(($table) => { cy.wrap($table.find(RULES_ROW).length).should('eql', 1); }); - cy.get(RULE_NAME).invoke('text').should('eql', newThresholdRule.name); - cy.get(RISK_SCORE).invoke('text').should('eql', newThresholdRule.riskScore); - cy.get(SEVERITY).invoke('text').should('eql', newThresholdRule.severity); - cy.get('[data-test-subj="rule-switch"]').should('have.attr', 'aria-checked', 'true'); + cy.get(RULE_NAME).should('have.text', newThresholdRule.name); + cy.get(RISK_SCORE).should('have.text', newThresholdRule.riskScore); + cy.get(SEVERITY).should('have.text', newThresholdRule.severity); + cy.get(RULE_SWITCH).should('have.attr', 'aria-checked', 'true'); goToRuleDetails(); + waitForTheRuleToBeExecuted(); - let expectedUrls = ''; - newThresholdRule.referenceUrls.forEach((url) => { - expectedUrls = expectedUrls + url; - }); - let expectedFalsePositives = ''; - newThresholdRule.falsePositivesExamples.forEach((falsePositive) => { - expectedFalsePositives = expectedFalsePositives + falsePositive; - }); - let expectedTags = ''; - newThresholdRule.tags.forEach((tag) => { - expectedTags = expectedTags + tag; - }); - let expectedMitre = ''; - newThresholdRule.mitre.forEach((mitre) => { - expectedMitre = expectedMitre + mitre.tactic; - mitre.techniques.forEach((technique) => { - expectedMitre = expectedMitre + technique; - }); - }); - const expectedIndexPatterns = [ - 'apm-*-transaction*', - 'auditbeat-*', - 'endgame-*', - 'filebeat-*', - 'logs-*', - 'packetbeat-*', - 'winlogbeat-*', - ]; - - cy.get(RULE_NAME_HEADER).invoke('text').should('eql', `${newThresholdRule.name} Beta`); - - cy.get(ABOUT_RULE_DESCRIPTION).invoke('text').should('eql', newThresholdRule.description); + cy.get(RULE_NAME_HEADER).should('have.text', `${newThresholdRule.name} Beta`); + cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', newThresholdRule.description); cy.get(ABOUT_DETAILS).within(() => { - getDescriptionForTitle('Severity').invoke('text').should('eql', newThresholdRule.severity); - getDescriptionForTitle('Risk score').invoke('text').should('eql', newThresholdRule.riskScore); - getDescriptionForTitle('Reference URLs').invoke('text').should('eql', expectedUrls); - getDescriptionForTitle('False positive examples') - .invoke('text') - .should('eql', expectedFalsePositives); - getDescriptionForTitle('MITRE ATT&CK').invoke('text').should('eql', expectedMitre); - getDescriptionForTitle('Tags').invoke('text').should('eql', expectedTags); + getDetails(SEVERITY_DETAILS).should('have.text', newThresholdRule.severity); + getDetails(RISK_SCORE_DETAILS).should('have.text', newThresholdRule.riskScore); + getDetails(REFERENCE_URLS_DETAILS).should('have.text', expectedUrls); + getDetails(FALSE_POSITIVES_DETAILS).should('have.text', expectedFalsePositives); + getDetails(MITRE_ATTACK_DETAILS).should('have.text', expectedMitre); + getDetails(TAGS_DETAILS).should('have.text', expectedTags); }); - cy.get(RULE_ABOUT_DETAILS_HEADER_TOGGLE).eq(INVESTIGATION_NOTES_TOGGLE).click({ force: true }); - cy.get(ABOUT_INVESTIGATION_NOTES).invoke('text').should('eql', INVESTIGATION_NOTES_MARKDOWN); - + cy.get(ABOUT_INVESTIGATION_NOTES).should('have.text', INVESTIGATION_NOTES_MARKDOWN); cy.get(DEFINITION_DETAILS).within(() => { - getDescriptionForTitle('Index patterns') - .invoke('text') - .should('eql', expectedIndexPatterns.join('')); - getDescriptionForTitle('Custom query') - .invoke('text') - .should('eql', `${newThresholdRule.customQuery} `); - getDescriptionForTitle('Rule type').invoke('text').should('eql', 'Threshold'); - getDescriptionForTitle('Timeline template').invoke('text').should('eql', 'None'); - getDescriptionForTitle('Threshold') - .invoke('text') - .should( - 'eql', - `Results aggregated by ${newThresholdRule.thresholdField} >= ${newThresholdRule.threshold}` - ); + getDetails(INDEX_PATTERNS_DETAILS).should('have.text', indexPatterns.join('')); + getDetails(CUSTOM_QUERY_DETAILS).should('have.text', `${newThresholdRule.customQuery} `); + getDetails(RULE_TYPE_DETAILS).should('have.text', 'Threshold'); + getDetails(TIMELINE_TEMPLATE_DETAILS).should('have.text', 'None'); + getDetails(THRESHOLD_DETAILS).should( + 'have.text', + `Results aggregated by ${newThresholdRule.thresholdField} >= ${newThresholdRule.threshold}` + ); + }); + cy.get(SCHEDULE_DETAILS).within(() => { + getDetails(RUNS_EVERY_DETAILS).should( + 'have.text', + `${newThresholdRule.runsEvery.interval}${newThresholdRule.runsEvery.type}` + ); + getDetails(ADDITIONAL_LOOK_BACK_DETAILS).should( + 'have.text', + `${newThresholdRule.lookBack.interval}${newThresholdRule.lookBack.type}` + ); }); - - cy.get('[data-test-subj=schedule] [data-test-subj="listItemColumnStepRuleDescription"]').within( - () => { - getDescriptionForTitle('Runs every') - .invoke('text') - .should( - 'eql', - `${newThresholdRule.runsEvery.interval}${newThresholdRule.runsEvery.type}` - ); - getDescriptionForTitle('Additional look-back time') - .invoke('text') - .should('eql', `${newThresholdRule.lookBack.interval}${newThresholdRule.lookBack.type}`); - } - ); refreshPage(); diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts_timeline.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_timeline.spec.ts index 2fed23755963b..31d8e4666d91d 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts_timeline.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_timeline.spec.ts @@ -35,7 +35,7 @@ describe('Alerts timeline', () => { .invoke('text') .then((eventId) => { investigateFirstAlertInTimeline(); - cy.get(PROVIDER_BADGE).invoke('text').should('eql', `_id: "${eventId}"`); + cy.get(PROVIDER_BADGE).should('have.text', `_id: "${eventId}"`); }); }); }); diff --git a/x-pack/plugins/security_solution/cypress/objects/rule.ts b/x-pack/plugins/security_solution/cypress/objects/rule.ts index fa1445ba531b1..e84e2b7b1669f 100644 --- a/x-pack/plugins/security_solution/cypress/objects/rule.ts +++ b/x-pack/plugins/security_solution/cypress/objects/rule.ts @@ -229,3 +229,21 @@ export const eqlRule: CustomRule = { runsEvery, lookBack, }; + +export const indexPatterns = [ + 'apm-*-transaction*', + 'auditbeat-*', + 'endgame-*', + 'filebeat-*', + 'logs-*', + 'packetbeat-*', + 'winlogbeat-*', +]; + +export const severitiesOverride = ['Low', 'Medium', 'High', 'Critical']; + +export const editedRule = { + ...existingRule, + severity: 'Medium', + description: 'Edited Rule description', +}; diff --git a/x-pack/plugins/security_solution/cypress/screens/rule_details.ts b/x-pack/plugins/security_solution/cypress/screens/rule_details.ts index 8ca7fd6091611..5a376e95e38dd 100644 --- a/x-pack/plugins/security_solution/cypress/screens/rule_details.ts +++ b/x-pack/plugins/security_solution/cypress/screens/rule_details.ts @@ -4,20 +4,30 @@ * you may not use this file except in compliance with the Elastic License. */ +export const ABOUT_INVESTIGATION_NOTES = '[data-test-subj="stepAboutDetailsNoteContent"]'; + +export const ABOUT_RULE_DESCRIPTION = '[data-test-subj=stepAboutRuleDetailsToggleDescriptionText]'; + export const ABOUT_DETAILS = '[data-test-subj="aboutRule"] [data-test-subj="listItemColumnStepRuleDescription"]'; -export const DETAILS_DESCRIPTION = '.euiDescriptionList__description'; - -export const DETAILS_TITLE = '.euiDescriptionList__title'; +export const ADDITIONAL_LOOK_BACK_DETAILS = 'Additional look-back time'; -export const ABOUT_INVESTIGATION_NOTES = '[data-test-subj="stepAboutDetailsNoteContent"]'; +export const ANOMALY_SCORE_DETAILS = 'Anomaly score'; -export const ABOUT_RULE_DESCRIPTION = '[data-test-subj=stepAboutRuleDetailsToggleDescriptionText]'; +export const CUSTOM_QUERY_DETAILS = 'Custom query'; export const DEFINITION_DETAILS = '[data-test-subj=definitionRule] [data-test-subj="listItemColumnStepRuleDescription"]'; +export const DETAILS_DESCRIPTION = '.euiDescriptionList__description'; + +export const DETAILS_TITLE = '.euiDescriptionList__title'; + +export const FALSE_POSITIVES_DETAILS = 'False positive examples'; + +export const INDEX_PATTERNS_DETAILS = 'Index patterns'; + export const INVESTIGATION_NOTES_MARKDOWN = 'test markdown'; export const INVESTIGATION_NOTES_TOGGLE = 1; @@ -26,14 +36,38 @@ export const MACHINE_LEARNING_JOB_ID = '[data-test-subj="machineLearningJobId"]' export const MACHINE_LEARNING_JOB_STATUS = '[data-test-subj="machineLearningJobStatus"]'; +export const MITRE_ATTACK_DETAILS = 'MITRE ATT&CK'; + export const RULE_ABOUT_DETAILS_HEADER_TOGGLE = '[data-test-subj="stepAboutDetailsToggle"]'; export const RULE_NAME_HEADER = '[data-test-subj="header-page-title"]'; +export const RULE_NAME_OVERRIDE_DETAILS = 'Rule name override'; + +export const RISK_SCORE_DETAILS = 'Risk score'; + +export const RISK_SCORE_OVERRIDE_DETAILS = 'Risk score override'; + +export const REFERENCE_URLS_DETAILS = 'Reference URLs'; + +export const RULE_TYPE_DETAILS = 'Rule type'; + +export const RUNS_EVERY_DETAILS = 'Runs every'; + export const SCHEDULE_DETAILS = '[data-test-subj=schedule] [data-test-subj="listItemColumnStepRuleDescription"]'; export const SCHEDULE_STEP = '[data-test-subj="schedule"] .euiDescriptionList__description'; -export const getDescriptionForTitle = (title: string) => +export const SEVERITY_DETAILS = 'Severity'; + +export const TAGS_DETAILS = 'Tags'; + +export const THRESHOLD_DETAILS = 'Threshold'; + +export const TIMELINE_TEMPLATE_DETAILS = 'Timeline template'; + +export const TIMESTAMP_OVERRIDE_DETAILS = 'Timestamp override'; + +export const getDetails = (title: string) => cy.get(DETAILS_TITLE).contains(title).next(DETAILS_DESCRIPTION); diff --git a/x-pack/plugins/security_solution/cypress/tasks/alerts.ts b/x-pack/plugins/security_solution/cypress/tasks/alerts.ts index 21cc0979c0ad3..7758f51d8f5b8 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/alerts.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/alerts.ts @@ -85,7 +85,8 @@ export const selectNumberOfAlerts = (numberOfAlerts: number) => { export const sortRiskScore = () => { cy.get(ALERT_RISK_SCORE_HEADER).click(); - waitForThePageToBeUpdated(); + cy.get('[data-test-subj="timeline-loading-spinner"]').should('exist'); + cy.get('[data-test-subj="timeline-loading-spinner"]').should('not.exist'); }; export const investigateFirstAlertInTimeline = () => { diff --git a/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts b/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts index 886c48e21c796..6f40c12362bcd 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts @@ -278,8 +278,15 @@ export const selectThresholdRuleType = () => { cy.get(THRESHOLD_TYPE).click({ force: true }); }; -export const waitForTheRuleToBeExecuted = (rule: CustomRule) => { - cy.wait(parseInt(rule.runsEvery.interval, 10) * 1000); +export const waitForTheRuleToBeExecuted = () => { + cy.get('[data-test-subj=ruleStatus]') + .invoke('text') + .then((ruleStatus) => { + if (ruleStatus !== 'succeeded') { + cy.get('[data-test-subj=refreshButton]').click(); + // cy.get('[data-test-subj=ruleStatus]').should('have.text', 'succeeded') + } + }); }; export const selectEqlRuleType = () => { diff --git a/x-pack/plugins/security_solution/public/detections/components/rules/rule_status/index.tsx b/x-pack/plugins/security_solution/public/detections/components/rules/rule_status/index.tsx index 0ddf4d06fb0fc..366bd156e0c1b 100644 --- a/x-pack/plugins/security_solution/public/detections/components/rules/rule_status/index.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/rules/rule_status/index.tsx @@ -69,7 +69,9 @@ const RuleStatusComponent: React.FC = ({ ruleId, ruleEnabled }) <> - {currentStatus?.status ?? getEmptyTagValue()} + + {currentStatus?.status ?? getEmptyTagValue()} + {currentStatus?.status_date != null && currentStatus?.status != null && ( @@ -84,6 +86,7 @@ const RuleStatusComponent: React.FC = ({ ruleId, ruleEnabled }) )} Date: Thu, 17 Sep 2020 13:00:44 +0200 Subject: [PATCH 06/14] fixes type check issue --- x-pack/plugins/security_solution/cypress/tasks/alerts.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/plugins/security_solution/cypress/tasks/alerts.ts b/x-pack/plugins/security_solution/cypress/tasks/alerts.ts index 7758f51d8f5b8..c8c4e11f0125b 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/alerts.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/alerts.ts @@ -25,7 +25,6 @@ import { ALERT_RISK_SCORE_HEADER, } from '../screens/alerts'; import { REFRESH_BUTTON } from '../screens/security_header'; -import { waitForThePageToBeUpdated } from './security_header'; export const closeFirstAlert = () => { cy.get(TIMELINE_CONTEXT_MENU_BTN).first().click({ force: true }); From 9486073801f4eb9aaef4a05613e104f3ed414e2a Mon Sep 17 00:00:00 2001 From: Gloria Hornero Date: Thu, 17 Sep 2020 21:22:05 +0200 Subject: [PATCH 07/14] improves assertions --- .../integration/alerts_detection_rules_threshold.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_threshold.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_threshold.spec.ts index 0eb4dad76925f..646640815ad55 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_threshold.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_threshold.spec.ts @@ -179,7 +179,7 @@ describe('Detection rules, threshold', () => { cy.get(NUMBER_OF_ALERTS) .invoke('text') .then((numberOfAlertsText) => { - cy.wrap(parseInt(numberOfAlertsText, 10)).should('be.below', 20); + cy.wrap(parseInt(numberOfAlertsText, 10)).should('be.below', 100); }); cy.get(ALERT_RULE_NAME).first().should('have.text', newThresholdRule.name); cy.get(ALERT_RULE_VERSION).first().should('have.text', '1'); From 578ce01aea30fa4f22f207c7d209b399d853fe4f Mon Sep 17 00:00:00 2001 From: Gloria Hornero Date: Wed, 23 Sep 2020 19:50:30 +0200 Subject: [PATCH 08/14] removes unused code --- .../cypress/tasks/create_new_rule.ts | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts b/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts index 4dd49ba5bfd68..913f18e98e8a3 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts @@ -203,20 +203,6 @@ export const fillScheduleRuleAndContinue = (rule: CustomRule | MachineLearningRu cy.get(LOOK_BACK_TIME_TYPE).select(rule.lookBack.timeType); }; -export const expectDefineFormToRepopulateAndContinue = (rule: CustomRule) => { - cy.get(DEFINE_EDIT_BUTTON).click(); - cy.get(CUSTOM_QUERY_INPUT).invoke('text').should('eq', rule.customQuery); - cy.get(DEFINE_CONTINUE_BUTTON).should('exist').click({ force: true }); - cy.get(DEFINE_CONTINUE_BUTTON).should('not.exist'); -}; - -export const expectAboutFormToRepopulateAndContinue = (rule: CustomRule) => { - cy.get(ABOUT_EDIT_BUTTON).click(); - cy.get(RULE_NAME_INPUT).invoke('val').should('eq', rule.name); - cy.get(ABOUT_CONTINUE_BTN).should('exist').click({ force: true }); - cy.get(ABOUT_CONTINUE_BTN).should('not.exist'); -}; - export const fillDefineThresholdRuleAndContinue = (rule: ThresholdRule) => { const thresholdField = 0; const threshold = 1; From f9c35555287f9e5dc54dcc77e9faf5122b797af1 Mon Sep 17 00:00:00 2001 From: Gloria Hornero Date: Wed, 23 Sep 2020 21:13:15 +0200 Subject: [PATCH 09/14] changes variables for constants --- .../alerts_detection_rules_custom.spec.ts | 27 ++++++------------- .../alerts_detection_rules_eql.spec.ts | 27 ++++++------------- .../alerts_detection_rules_ml.spec.ts | 27 ++++++------------- .../alerts_detection_rules_override.spec.ts | 27 ++++++------------- .../alerts_detection_rules_threshold.spec.ts | 27 ++++++------------- 5 files changed, 40 insertions(+), 95 deletions(-) diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts index 1e541cf9c3fd1..f55cf9262f2b9 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts @@ -100,25 +100,14 @@ import { refreshPage } from '../tasks/security_header'; import { DETECTIONS_URL } from '../urls/navigation'; -let expectedUrls = ''; -newRule.referenceUrls.forEach((url) => { - expectedUrls = expectedUrls + url; -}); -let expectedFalsePositives = ''; -newRule.falsePositivesExamples.forEach((falsePositive) => { - expectedFalsePositives = expectedFalsePositives + falsePositive; -}); -let expectedTags = ''; -newRule.tags.forEach((tag) => { - expectedTags = expectedTags + tag; -}); -let expectedMitre = ''; -newRule.mitre.forEach((mitre) => { - expectedMitre = expectedMitre + mitre.tactic; - mitre.techniques.forEach((technique) => { - expectedMitre = expectedMitre + technique; - }); -}); +const expectedUrls = newRule.referenceUrls.join(''); +const expectedFalsePositives = newRule.falsePositivesExamples.join(''); +const expectedTags = newRule.tags.join(''); +const expectedMitre = newRule.mitre + .map(function (mitre) { + return mitre.tactic + mitre.techniques.join(''); + }) + .join(''); const expectedNumberOfRules = 1; const expectedEditedtags = editedRule.tags.join(''); const expectedEditedIndexPatterns = diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_eql.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_eql.spec.ts index 2e08fb5e6044c..e2ff51dd544a2 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_eql.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_eql.spec.ts @@ -65,25 +65,14 @@ import { loginAndWaitForPageWithoutDateRange } from '../tasks/login'; import { DETECTIONS_URL } from '../urls/navigation'; -let expectedUrls = ''; -eqlRule.referenceUrls.forEach((url) => { - expectedUrls = expectedUrls + url; -}); -let expectedFalsePositives = ''; -eqlRule.falsePositivesExamples.forEach((falsePositive) => { - expectedFalsePositives = expectedFalsePositives + falsePositive; -}); -let expectedTags = ''; -eqlRule.tags.forEach((tag) => { - expectedTags = expectedTags + tag; -}); -let expectedMitre = ''; -eqlRule.mitre.forEach((mitre) => { - expectedMitre = expectedMitre + mitre.tactic; - mitre.techniques.forEach((technique) => { - expectedMitre = expectedMitre + technique; - }); -}); +const expectedUrls = eqlRule.referenceUrls.join(''); +const expectedFalsePositives = eqlRule.falsePositivesExamples.join(''); +const expectedTags = eqlRule.tags.join(''); +const expectedMitre = eqlRule.mitre + .map(function (mitre) { + return mitre.tactic + mitre.techniques.join(''); + }) + .join(''); const expectedNumberOfRules = 1; describe('Detection rules, EQL', () => { diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_ml.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_ml.spec.ts index 8011a47560ed8..49ec6381cbc89 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_ml.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_ml.spec.ts @@ -62,25 +62,14 @@ import { loginAndWaitForPageWithoutDateRange } from '../tasks/login'; import { DETECTIONS_URL } from '../urls/navigation'; -let expectedUrls = ''; -machineLearningRule.referenceUrls.forEach((url) => { - expectedUrls = expectedUrls + url; -}); -let expectedFalsePositives = ''; -machineLearningRule.falsePositivesExamples.forEach((falsePositive) => { - expectedFalsePositives = expectedFalsePositives + falsePositive; -}); -let expectedTags = ''; -machineLearningRule.tags.forEach((tag) => { - expectedTags = expectedTags + tag; -}); -let expectedMitre = ''; -machineLearningRule.mitre.forEach((mitre) => { - expectedMitre = expectedMitre + mitre.tactic; - mitre.techniques.forEach((technique) => { - expectedMitre = expectedMitre + technique; - }); -}); +const expectedUrls = machineLearningRule.referenceUrls.join(''); +const expectedFalsePositives = machineLearningRule.falsePositivesExamples.join(''); +const expectedTags = machineLearningRule.tags.join(''); +const expectedMitre = machineLearningRule.mitre + .map(function (mitre) { + return mitre.tactic + mitre.techniques.join(''); + }) + .join(''); const expectedNumberOfRules = totalNumberOfPrebuiltRulesInEsArchive + 1; describe('Detection rules, machine learning', () => { diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_override.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_override.spec.ts index 0632a878dfecc..fb82720d85c89 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_override.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_override.spec.ts @@ -80,25 +80,14 @@ import { refreshPage } from '../tasks/security_header'; import { DETECTIONS_URL } from '../urls/navigation'; -let expectedUrls = ''; -newOverrideRule.referenceUrls.forEach((url) => { - expectedUrls = expectedUrls + url; -}); -let expectedFalsePositives = ''; -newOverrideRule.falsePositivesExamples.forEach((falsePositive) => { - expectedFalsePositives = expectedFalsePositives + falsePositive; -}); -let expectedTags = ''; -newOverrideRule.tags.forEach((tag) => { - expectedTags = expectedTags + tag; -}); -let expectedMitre = ''; -newOverrideRule.mitre.forEach((mitre) => { - expectedMitre = expectedMitre + mitre.tactic; - mitre.techniques.forEach((technique) => { - expectedMitre = expectedMitre + technique; - }); -}); +const expectedUrls = newOverrideRule.referenceUrls.join(''); +const expectedFalsePositives = newOverrideRule.falsePositivesExamples.join(''); +const expectedTags = newOverrideRule.tags.join(''); +const expectedMitre = newOverrideRule.mitre + .map(function (mitre) { + return mitre.tactic + mitre.techniques.join(''); + }) + .join(''); describe('Detection rules, override', () => { before(() => { diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_threshold.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_threshold.spec.ts index 646640815ad55..8c484a269b5f7 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_threshold.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_threshold.spec.ts @@ -76,25 +76,14 @@ import { refreshPage } from '../tasks/security_header'; import { DETECTIONS_URL } from '../urls/navigation'; -let expectedUrls = ''; -newThresholdRule.referenceUrls.forEach((url) => { - expectedUrls = expectedUrls + url; -}); -let expectedFalsePositives = ''; -newThresholdRule.falsePositivesExamples.forEach((falsePositive) => { - expectedFalsePositives = expectedFalsePositives + falsePositive; -}); -let expectedTags = ''; -newThresholdRule.tags.forEach((tag) => { - expectedTags = expectedTags + tag; -}); -let expectedMitre = ''; -newThresholdRule.mitre.forEach((mitre) => { - expectedMitre = expectedMitre + mitre.tactic; - mitre.techniques.forEach((technique) => { - expectedMitre = expectedMitre + technique; - }); -}); +const expectedUrls = newThresholdRule.referenceUrls.join(''); +const expectedFalsePositives = newThresholdRule.falsePositivesExamples.join(''); +const expectedTags = newThresholdRule.tags.join(''); +const expectedMitre = newThresholdRule.mitre + .map(function (mitre) { + return mitre.tactic + mitre.techniques.join(''); + }) + .join(''); describe('Detection rules, threshold', () => { before(() => { From 6fe2d60dff5e7a2d887f049cb01457ff7a3aa534 Mon Sep 17 00:00:00 2001 From: Gloria Hornero Date: Wed, 23 Sep 2020 21:29:01 +0200 Subject: [PATCH 10/14] improves 'waitForTheRuleToBeExecuted' test --- .../cypress/screens/create_new_rule.ts | 4 ++++ .../cypress/tasks/create_new_rule.ts | 16 ++++++---------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/x-pack/plugins/security_solution/cypress/screens/create_new_rule.ts b/x-pack/plugins/security_solution/cypress/screens/create_new_rule.ts index 8b5252fb19fc7..61791a1310e67 100644 --- a/x-pack/plugins/security_solution/cypress/screens/create_new_rule.ts +++ b/x-pack/plugins/security_solution/cypress/screens/create_new_rule.ts @@ -79,6 +79,8 @@ export const MITRE_TECHNIQUES_INPUT = export const REFERENCE_URLS_INPUT = '[data-test-subj="detectionEngineStepAboutRuleReferenceUrls"] input'; +export const REFRESH_BUTTON = '[data-test-subj=refreshButton]'; + export const RISK_INPUT = '.euiRangeInput'; export const RISK_MAPPING_OVERRIDE_OPTION = '#risk_score-mapping-override'; @@ -94,6 +96,8 @@ export const RULE_NAME_INPUT = export const RULE_NAME_OVERRIDE = '[data-test-subj="detectionEngineStepAboutRuleRuleNameOverride"]'; +export const RULE_STATUS = '[data-test-subj=ruleStatus]'; + export const RULE_TIMESTAMP_OVERRIDE = '[data-test-subj="detectionEngineStepAboutRuleTimestampOverride"]'; diff --git a/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts b/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts index 913f18e98e8a3..ed648029a77d7 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts @@ -13,7 +13,6 @@ import { } from '../objects/rule'; import { ABOUT_CONTINUE_BTN, - ABOUT_EDIT_BUTTON, ABOUT_EDIT_TAB, ACTIONS_EDIT_TAB, ADD_FALSE_POSITIVE_BTN, @@ -25,7 +24,6 @@ import { CUSTOM_QUERY_INPUT, DEFINE_CONTINUE_BUTTON, DEFINE_EDIT_TAB, - DEFINE_EDIT_BUTTON, FALSE_POSITIVES_INPUT, IMPORT_QUERY_FROM_SAVED_TIMELINE_LINK, INPUT, @@ -40,12 +38,14 @@ import { MITRE_TACTIC_DROPDOWN, MITRE_TECHNIQUES_INPUT, REFERENCE_URLS_INPUT, + REFRESH_BUTTON, RISK_INPUT, RISK_MAPPING_OVERRIDE_OPTION, RISK_OVERRIDE, RULE_DESCRIPTION_INPUT, RULE_NAME_INPUT, RULE_NAME_OVERRIDE, + RULE_STATUS, RULE_TIMESTAMP_OVERRIDE, RUNS_EVERY_INTERVAL, RUNS_EVERY_TIME_TYPE, @@ -265,14 +265,10 @@ export const selectThresholdRuleType = () => { }; export const waitForTheRuleToBeExecuted = () => { - cy.get('[data-test-subj=ruleStatus]') - .invoke('text') - .then((ruleStatus) => { - if (ruleStatus !== 'succeeded') { - cy.get('[data-test-subj=refreshButton]').click(); - // cy.get('[data-test-subj=ruleStatus]').should('have.text', 'succeeded') - } - }); + cy.get(RULE_STATUS).should((ruleStatus) => { + cy.get(REFRESH_BUTTON).click(); + expect(ruleStatus).to.be('succeeded'); + }); }; export const selectEqlRuleType = () => { From 905ee85381cf7cb8837ea17a9039669af66e859e Mon Sep 17 00:00:00 2001 From: Gloria Hornero Date: Wed, 23 Sep 2020 21:36:10 +0200 Subject: [PATCH 11/14] improves readability --- x-pack/plugins/security_solution/cypress/tasks/alerts.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/cypress/tasks/alerts.ts b/x-pack/plugins/security_solution/cypress/tasks/alerts.ts index c8c4e11f0125b..d3475df1c68d4 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/alerts.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/alerts.ts @@ -25,6 +25,7 @@ import { ALERT_RISK_SCORE_HEADER, } from '../screens/alerts'; import { REFRESH_BUTTON } from '../screens/security_header'; +import { TIMELINE_COLUMN_SPINNER } from '../screens/timeline'; export const closeFirstAlert = () => { cy.get(TIMELINE_CONTEXT_MENU_BTN).first().click({ force: true }); @@ -84,8 +85,8 @@ export const selectNumberOfAlerts = (numberOfAlerts: number) => { export const sortRiskScore = () => { cy.get(ALERT_RISK_SCORE_HEADER).click(); - cy.get('[data-test-subj="timeline-loading-spinner"]').should('exist'); - cy.get('[data-test-subj="timeline-loading-spinner"]').should('not.exist'); + cy.get(TIMELINE_COLUMN_SPINNER).should('exist'); + cy.get(TIMELINE_COLUMN_SPINNER).should('not.exist'); }; export const investigateFirstAlertInTimeline = () => { From 492cf986fd5835d520f8977be02e8b10d5dc2e39 Mon Sep 17 00:00:00 2001 From: Gloria Hornero Date: Sat, 26 Sep 2020 19:25:25 +0200 Subject: [PATCH 12/14] fixes jenkins error --- x-pack/plugins/security_solution/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/package.json b/x-pack/plugins/security_solution/package.json index 6d79557fdaa28..4c9e3bc06037e 100644 --- a/x-pack/plugins/security_solution/package.json +++ b/x-pack/plugins/security_solution/package.json @@ -11,7 +11,7 @@ "cypress:open": "cypress open --config-file ./cypress/cypress.json", "cypress:open-as-ci": "node ../../../scripts/functional_tests --config ../../test/security_solution_cypress/visual_config.ts", "cypress:run": "cypress run --browser chrome --headless --spec ./cypress/integration/**/*.spec.ts --config-file ./cypress/cypress.json --reporter ../../node_modules/cypress-multi-reporters --reporter-options configFile=./cypress/reporter_config.json; status=$?; ../../node_modules/.bin/mochawesome-merge ../../../target/kibana-security-solution/cypress/results/mochawesome*.json > ../../../target/kibana-security-solution/cypress/results/output.json; ../../../node_modules/.bin/marge ../../../target/kibana-security-solution/cypress/results/output.json --reportDir ../../../target/kibana-security-solution/cypress/results; mkdir -p ../../../target/junit && cp ../../../target/kibana-security-solution/cypress/results/*.xml ../../../target/junit/ && exit $status;", - "cypress:run-as-ci": "node ../../../scripts/functional_tests --config ../../test/security_solution_cypress/cli_config.ts", + "cypress:run-as-ci": "node --max-old-space-size=2048 ../../../scripts/functional_tests --config ../../test/security_solution_cypress/cli_config.ts", "test:generate": "node scripts/endpoint/resolver_generator" }, "devDependencies": { From 1e7dde82ef16b2405a13a64d03eecba16b2939ef Mon Sep 17 00:00:00 2001 From: Gloria Hornero Date: Sun, 27 Sep 2020 15:58:24 +0200 Subject: [PATCH 13/14] refactor --- .../alerts_detection_rules_custom.spec.ts | 2 +- .../alerts_detection_rules_override.spec.ts | 2 +- .../alerts_detection_rules_threshold.spec.ts | 2 +- .../cypress/screens/create_new_rule.ts | 4 ++-- .../cypress/tasks/create_new_rule.ts | 12 ++++++++---- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts index f55cf9262f2b9..f999c5cecc392 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_custom.spec.ts @@ -167,7 +167,6 @@ describe('Custom detection rules creation', () => { cy.get(RULE_SWITCH).should('have.attr', 'aria-checked', 'true'); goToRuleDetails(); - waitForTheRuleToBeExecuted(); cy.get(RULE_NAME_HEADER).should('have.text', `${newRule.name} Beta`); cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', newRule.description); @@ -199,6 +198,7 @@ describe('Custom detection rules creation', () => { }); refreshPage(); + waitForTheRuleToBeExecuted(); cy.get(NUMBER_OF_ALERTS) .invoke('text') diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_override.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_override.spec.ts index fb82720d85c89..090012de72534 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_override.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_override.spec.ts @@ -131,7 +131,6 @@ describe('Detection rules, override', () => { cy.get(RULE_SWITCH).should('have.attr', 'aria-checked', 'true'); goToRuleDetails(); - waitForTheRuleToBeExecuted(); cy.get(RULE_NAME_HEADER).should('have.text', `${newOverrideRule.name} Beta`); cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', newOverrideRule.description); @@ -181,6 +180,7 @@ describe('Detection rules, override', () => { }); refreshPage(); + waitForTheRuleToBeExecuted(); cy.get(NUMBER_OF_ALERTS) .invoke('text') diff --git a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_threshold.spec.ts b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_threshold.spec.ts index 8c484a269b5f7..5ee7e69e877e3 100644 --- a/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_threshold.spec.ts +++ b/x-pack/plugins/security_solution/cypress/integration/alerts_detection_rules_threshold.spec.ts @@ -128,7 +128,6 @@ describe('Detection rules, threshold', () => { cy.get(RULE_SWITCH).should('have.attr', 'aria-checked', 'true'); goToRuleDetails(); - waitForTheRuleToBeExecuted(); cy.get(RULE_NAME_HEADER).should('have.text', `${newThresholdRule.name} Beta`); cy.get(ABOUT_RULE_DESCRIPTION).should('have.text', newThresholdRule.description); @@ -164,6 +163,7 @@ describe('Detection rules, threshold', () => { }); refreshPage(); + waitForTheRuleToBeExecuted(); cy.get(NUMBER_OF_ALERTS) .invoke('text') diff --git a/x-pack/plugins/security_solution/cypress/screens/create_new_rule.ts b/x-pack/plugins/security_solution/cypress/screens/create_new_rule.ts index 61791a1310e67..e1ab5ff30572f 100644 --- a/x-pack/plugins/security_solution/cypress/screens/create_new_rule.ts +++ b/x-pack/plugins/security_solution/cypress/screens/create_new_rule.ts @@ -79,7 +79,7 @@ export const MITRE_TECHNIQUES_INPUT = export const REFERENCE_URLS_INPUT = '[data-test-subj="detectionEngineStepAboutRuleReferenceUrls"] input'; -export const REFRESH_BUTTON = '[data-test-subj=refreshButton]'; +export const REFRESH_BUTTON = '[data-test-subj="refreshButton"]'; export const RISK_INPUT = '.euiRangeInput'; @@ -96,7 +96,7 @@ export const RULE_NAME_INPUT = export const RULE_NAME_OVERRIDE = '[data-test-subj="detectionEngineStepAboutRuleRuleNameOverride"]'; -export const RULE_STATUS = '[data-test-subj=ruleStatus]'; +export const RULE_STATUS = '[data-test-subj="ruleStatus"]'; export const RULE_TIMESTAMP_OVERRIDE = '[data-test-subj="detectionEngineStepAboutRuleTimestampOverride"]'; diff --git a/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts b/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts index ed648029a77d7..3e6a566a1b72a 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts @@ -265,10 +265,14 @@ export const selectThresholdRuleType = () => { }; export const waitForTheRuleToBeExecuted = () => { - cy.get(RULE_STATUS).should((ruleStatus) => { - cy.get(REFRESH_BUTTON).click(); - expect(ruleStatus).to.be('succeeded'); - }); + cy.get(RULE_STATUS) + .invoke('text') + .then((status) => { + if (status !== 'succeeded') { + cy.get(REFRESH_BUTTON).click(); + } + }); + cy.get(RULE_STATUS).should('have.text', 'succeeded'); }; export const selectEqlRuleType = () => { From 1dec5b24eb07753b49776fe37fd953e1f0ce40bf Mon Sep 17 00:00:00 2001 From: Gloria Hornero Date: Mon, 28 Sep 2020 12:39:57 +0200 Subject: [PATCH 14/14] refactor --- .../cypress/tasks/create_new_rule.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts b/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts index 3e6a566a1b72a..914566a13a9a9 100644 --- a/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts +++ b/x-pack/plugins/security_solution/cypress/tasks/create_new_rule.ts @@ -264,15 +264,12 @@ export const selectThresholdRuleType = () => { cy.get(THRESHOLD_TYPE).click({ force: true }); }; -export const waitForTheRuleToBeExecuted = () => { - cy.get(RULE_STATUS) - .invoke('text') - .then((status) => { - if (status !== 'succeeded') { - cy.get(REFRESH_BUTTON).click(); - } - }); - cy.get(RULE_STATUS).should('have.text', 'succeeded'); +export const waitForTheRuleToBeExecuted = async () => { + let status = ''; + while (status !== 'succeeded') { + cy.get(REFRESH_BUTTON).click(); + status = await cy.get(RULE_STATUS).invoke('text').promisify(); + } }; export const selectEqlRuleType = () => {