From b41857f0434a7a92321dd7117911902e5142e0af Mon Sep 17 00:00:00 2001 From: Jovan Cvetkovic Date: Mon, 23 Jan 2023 19:17:09 +0100 Subject: [PATCH] Feature/add role edit cypress tests (#377) * [FEATURE] Detector must have at least one alert set #288 Signed-off-by: Jovan Cvetkovic * [FEATURE] Implement additional integration test cases #104 Signed-off-by: Jovan Cvetkovic * [FEATURE] Implement additional integration test cases #104 Signed-off-by: Jovan Cvetkovic * [FEATURE] Implement additional integration test cases #104 Signed-off-by: Jovan Cvetkovic Signed-off-by: Jovan Cvetkovic --- cypress.json | 1 + cypress/integration/1_detectors.spec.js | 14 ++ cypress/integration/2_rules.spec.js | 207 +++++++++++++++--------- 3 files changed, 149 insertions(+), 73 deletions(-) diff --git a/cypress.json b/cypress.json index dfbe681fc..46e089817 100644 --- a/cypress.json +++ b/cypress.json @@ -2,6 +2,7 @@ "viewportHeight": 900, "viewportWidth": 1440, "defaultCommandTimeout": 20000, + "baseUrl": "http://localhost:5601", "env": { "opensearch_url": "localhost:9200", "opensearch_dashboards": "http://localhost:5601", diff --git a/cypress/integration/1_detectors.spec.js b/cypress/integration/1_detectors.spec.js index 74dd7119b..9cbb4cac7 100644 --- a/cypress/integration/1_detectors.spec.js +++ b/cypress/integration/1_detectors.spec.js @@ -39,6 +39,16 @@ describe('Detectors', () => { cy.cleanUpTests(); // Create test index cy.createIndex(indexName, sample_index_settings); + cy.request('POST', '_plugins/_security_analytics/rules/_search?prePackaged=true', { + from: 0, + size: 5000, + query: { + nested: { + path: 'rule', + query: { bool: { must: [{ match: { 'rule.category': 'windows' } }] } }, + }, + }, + }); cy.contains(detectorName).should('not.exist'); }); @@ -85,6 +95,10 @@ describe('Detectors', () => { // Open Detection rules accordion cy.get('[data-test-subj="detection-rules-btn"]').click({ force: true, timeout: 5000 }); + cy.contains('table tr', 'Windows', { + timeout: 120000, + }); + // find search, type USB cy.get(`input[placeholder="Search..."]`).ospSearch('USB Device Plugged'); diff --git a/cypress/integration/2_rules.spec.js b/cypress/integration/2_rules.spec.js index 70fe548ba..a29b0d6ee 100644 --- a/cypress/integration/2_rules.spec.js +++ b/cypress/integration/2_rules.spec.js @@ -48,6 +48,86 @@ const YAML_RULE_LINES = [ ...SAMPLE_RULE.detection.replaceAll(' ', '').replaceAll('{backspace}', '').split('\n'), ]; +const checkRulesFlyout = () => { + // Search for the rule + cy.get(`input[placeholder="Search rules"]`).ospSearch(SAMPLE_RULE.name); + + // Click the rule link to open the details flyout + cy.get(`[data-test-subj="rule_link_${SAMPLE_RULE.name}"]`).click({ force: true }); + + // Confirm the flyout contains the expected values + cy.get(`[data-test-subj="rule_flyout_${SAMPLE_RULE.name}"]`) + .click({ force: true }) + .within(() => { + // Validate name + cy.get('[data-test-subj="rule_flyout_rule_name"]').contains(SAMPLE_RULE.name); + + // Validate log type + cy.get('[data-test-subj="rule_flyout_rule_log_type"]').contains(SAMPLE_RULE.logType); + + // Validate description + cy.get('[data-test-subj="rule_flyout_rule_description"]').contains(SAMPLE_RULE.description); + + // Validate author + cy.get('[data-test-subj="rule_flyout_rule_author"]').contains(SAMPLE_RULE.author); + + // Validate source is "custom" + cy.get('[data-test-subj="rule_flyout_rule_source"]').contains('Custom'); + + // Validate severity + cy.get('[data-test-subj="rule_flyout_rule_severity"]').contains(SAMPLE_RULE.severity); + + // Validate tags + SAMPLE_RULE.tags.forEach((tag) => + cy.get('[data-test-subj="rule_flyout_rule_tags"]').contains(tag) + ); + + // Validate references + cy.get('[data-test-subj="rule_flyout_rule_references"]').contains(SAMPLE_RULE.references); + + // Validate false positives + cy.get('[data-test-subj="rule_flyout_rule_false_positives"]').contains( + SAMPLE_RULE.falsePositive + ); + + // Validate status + cy.get('[data-test-subj="rule_flyout_rule_status"]').contains(SAMPLE_RULE.status); + + // Validate detection + SAMPLE_RULE.detectionLine.forEach((line) => + cy.get('[data-test-subj="rule_flyout_rule_detection"]').contains(line) + ); + + cy.get('[data-test-subj="change-editor-type"] label:nth-child(2)').click({ + force: true, + }); + + cy.get('[data-test-subj="rule_flyout_yaml_rule"]') + .get('[class="euiCodeBlock__line"]') + .each((lineElement, lineIndex) => { + if (lineIndex >= YAML_RULE_LINES.length) { + return; + } + let line = lineElement.text().replaceAll('\n', '').trim(); + let expectedLine = YAML_RULE_LINES[lineIndex]; + + // The document ID field is generated when the document is added to the index, + // so this test just checks that the line starts with the ID key. + if (expectedLine.startsWith('id:')) { + expectedLine = 'id:'; + expect(line, `Sigma rule line ${lineIndex}`).to.contain(expectedLine); + } else { + expect(line, `Sigma rule line ${lineIndex}`).to.equal(expectedLine); + } + }); + + // Close the flyout + cy.get('[data-test-subj="close-rule-details-flyout"]').click({ + force: true, + }); + }); +}; + describe('Rules', () => { before(() => cy.cleanUpTests()); beforeEach(() => { @@ -120,83 +200,67 @@ describe('Rules', () => { cy.wait('@getRules'); - // Search for the rule - cy.get(`input[placeholder="Search rules"]`).ospSearch(SAMPLE_RULE.name); + checkRulesFlyout(); + }); - // Click the rule link to open the details flyout + it('...can be edited', () => { + cy.waitForPageLoad('rules', { + contains: 'Rules', + }); + + cy.get(`input[placeholder="Search rules"]`).ospSearch(SAMPLE_RULE.name); cy.get(`[data-test-subj="rule_link_${SAMPLE_RULE.name}"]`).click({ force: true }); - // Confirm the flyout contains the expected values cy.get(`[data-test-subj="rule_flyout_${SAMPLE_RULE.name}"]`) + .find('button') + .contains('Action') .click({ force: true }) - .within(() => { - // Validate name - cy.get('[data-test-subj="rule_flyout_rule_name"]').contains(SAMPLE_RULE.name); - - // Validate log type - cy.get('[data-test-subj="rule_flyout_rule_log_type"]').contains(SAMPLE_RULE.logType); - - // Validate description - cy.get('[data-test-subj="rule_flyout_rule_description"]').contains(SAMPLE_RULE.description); - - // Validate author - cy.get('[data-test-subj="rule_flyout_rule_author"]').contains(SAMPLE_RULE.author); + .then(() => { + // Confirm arrival at detectors page + cy.get('.euiPopover__panel').find('button').contains('Edit').click(); + }); - // Validate source is "custom" - cy.get('[data-test-subj="rule_flyout_rule_source"]').contains('Custom'); + const ruleNameSelector = '[data-test-subj="rule_name_field"]'; + cy.get(ruleNameSelector).clear(); - // Validate severity - cy.get('[data-test-subj="rule_flyout_rule_severity"]').contains(SAMPLE_RULE.severity); + SAMPLE_RULE.name += ' edited'; + cy.get(ruleNameSelector).type(SAMPLE_RULE.name); + cy.get(ruleNameSelector).should('have.value', SAMPLE_RULE.name); - // Validate tags - SAMPLE_RULE.tags.forEach((tag) => - cy.get('[data-test-subj="rule_flyout_rule_tags"]').contains(tag) - ); + // Enter the log type + const logSelector = '[data-test-subj="rule_type_dropdown"]'; + cy.get(logSelector).within(() => cy.get('.euiFormControlLayoutClearButton').click()); + SAMPLE_RULE.logType = 'dns'; + YAML_RULE_LINES[2] = `product: ${SAMPLE_RULE.logType}`; + YAML_RULE_LINES[3] = `title: ${SAMPLE_RULE.name}`; + cy.get(logSelector).type(SAMPLE_RULE.logType).type('{enter}'); + cy.get(logSelector).contains(SAMPLE_RULE.logType, { + matchCase: false, + }); - // Validate references - cy.get('[data-test-subj="rule_flyout_rule_references"]').contains(SAMPLE_RULE.references); + const ruleDescriptionSelector = '[data-test-subj="rule_description_field"]'; + SAMPLE_RULE.description += ' edited'; + YAML_RULE_LINES[4] = `description: ${SAMPLE_RULE.description}`; + cy.get(ruleDescriptionSelector).clear(); + cy.get(ruleDescriptionSelector).type(SAMPLE_RULE.description); + cy.get(ruleDescriptionSelector).should('have.value', SAMPLE_RULE.description); - // Validate false positives - cy.get('[data-test-subj="rule_flyout_rule_false_positives"]').contains( - SAMPLE_RULE.falsePositive - ); + cy.intercept({ + url: '/rules', + }).as('getRules'); - // Validate status - cy.get('[data-test-subj="rule_flyout_rule_status"]').contains(SAMPLE_RULE.status); + // Click "create" button + cy.get('[data-test-subj="submit_rule_form_button"]').click({ + force: true, + }); - // Validate detection - SAMPLE_RULE.detectionLine.forEach((line) => - cy.get('[data-test-subj="rule_flyout_rule_detection"]').contains(line) - ); + cy.waitForPageLoad('rules', { + contains: 'Rules', + }); - cy.get('[data-test-subj="change-editor-type"] label:nth-child(2)').click({ - force: true, - }); + cy.wait('@getRules'); - cy.get('[data-test-subj="rule_flyout_yaml_rule"]') - .get('[class="euiCodeBlock__line"]') - .each((lineElement, lineIndex) => { - if (lineIndex >= YAML_RULE_LINES.length) { - return; - } - let line = lineElement.text().replaceAll('\n', '').trim(); - let expectedLine = YAML_RULE_LINES[lineIndex]; - - // The document ID field is generated when the document is added to the index, - // so this test just checks that the line starts with the ID key. - if (expectedLine.startsWith('id:')) { - expectedLine = 'id:'; - expect(line, `Sigma rule line ${lineIndex}`).to.contain(expectedLine); - } else { - expect(line, `Sigma rule line ${lineIndex}`).to.equal(expectedLine); - } - }); - - // Close the flyout - cy.get('[data-test-subj="close-rule-details-flyout"]').click({ - force: true, - }); - }); + checkRulesFlyout(); }); it('...can be deleted', () => { @@ -209,20 +273,17 @@ describe('Rules', () => { // Click the rule link to open the details flyout cy.get(`[data-test-subj="rule_link_${SAMPLE_RULE.name}"]`).click({ force: true }); - cy.get('.euiButton') + cy.get(`[data-test-subj="rule_flyout_${SAMPLE_RULE.name}"]`) + .find('button') .contains('Action') .click({ force: true }) .then(() => { // Confirm arrival at detectors page - cy.get( - '.euiFlexGroup > :nth-child(3) > .euiButtonEmpty > .euiButtonContent > .euiButtonEmpty__text' - ) - .click({ - force: true, - }) - .then(() => { - cy.get('.euiButton').contains('Delete').click(); - }); + cy.get('.euiPopover__panel') + .find('button') + .contains('Delete') + .click() + .then(() => cy.get('.euiModalFooter > .euiButton').contains('Delete').click()); cy.wait('@deleteRule');