From 3f0425d625ac0ea03724c8246d25869cfdd8952d Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Fri, 20 Jan 2023 10:47:25 -0800 Subject: [PATCH 01/36] Added additional cypress tests for the security analytics plugin. Signed-off-by: AWSHurneyt --- .../1_detectors.spec.js | 308 ++++++++++++ .../2_rules.spec.js | 237 ++++++++++ .../3_alerts.spec.js | 445 ++++++++++++++++++ .../4_findings.spec.js | 178 +++++++ .../5_integrations.spec.js | 142 ++++++ .../rules_spec.js | 201 -------- cypress/utils/commands.js | 2 +- .../commands.js | 125 ++++- .../constants.js | 2 + 9 files changed, 1421 insertions(+), 219 deletions(-) create mode 100644 cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js create mode 100644 cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js create mode 100644 cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js create mode 100644 cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js create mode 100644 cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js new file mode 100644 index 000000000..b40ed8db4 --- /dev/null +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js @@ -0,0 +1,308 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { OPENSEARCH_DASHBOARDS_URL } from '../support/constants'; +import sample_index_settings from '../fixtures/sample_index_settings.json'; + +const testMappings = { + properties: { + 'host-hostname': { + type: 'alias', + path: 'HostName', + }, + 'windows-message': { + type: 'alias', + path: 'Message', + }, + 'winlog-provider_name': { + type: 'alias', + path: 'Provider_Name', + }, + 'winlog-event_data-ServiceName': { + type: 'alias', + path: 'ServiceName', + }, + 'winlog-event_id': { + path: 'EventID', + type: 'alias', + }, + }, +}; + +describe('Detectors', () => { + const indexName = 'cypress-test-windows'; + const detectorName = 'test detector'; + + before(() => { + cy.cleanUpTests(); + + // Create test index + cy.createIndex(indexName, sample_index_settings); + + cy.contains(detectorName).should('not.exist'); + }); + + beforeEach(() => { + // Visit Detectors page + cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/detectors`); + + // Check that correct page is showing + cy.waitForPageLoad('detectors', { + contains: 'Threat detectors', + }); + }); + + it('...can be created', () => { + // Locate Create detector button click to start + cy.contains('Create detector').click({ force: true }); + + // Check to ensure process started + cy.waitForPageLoad('create-detector', { + contains: 'Define detector', + }); + + // Enter a name for the detector in the appropriate input + cy.get(`input[placeholder="Enter a name for the detector."]`).type('test detector{enter}'); + + // Select our pre-seeded data source (check indexName) + cy.get(`[data-test-subj="define-detector-select-data-source"]`).type(`${indexName}{enter}`); + + // Select threat detector type (Windows logs) + cy.get(`input[id="windows"]`).click({ force: true }); + + // Open Detection rules accordion + cy.get('[data-test-subj="detection-rules-btn"]').click({ timeout: 5000 }); + + // find search, type USB + cy.triggerSearchField('Search...', 'USB Device Plugged'); + + // Disable all rules + cy.contains('tr', 'USB Device Plugged', { timeout: 20000 }); + cy.get('th').within(() => { + cy.get('button').first().click({ force: true }); + }); + + // enable single rule + cy.contains('tr', 'USB Device Plugged').within(() => { + cy.get('button').eq(1).click({ force: true }); + }); + + // Click Next button to continue + cy.get('button').contains('Next').click({ force: true }); + + // Check that correct page now showing + cy.contains('Configure field mapping'); + + // Show 50 rows per page + cy.contains('Rows per page').click({ force: true }); + cy.contains('50 rows').click({ force: true }); + + // Show 50 rows per page + cy.contains('Rows per page').click({ force: true }); + cy.contains('50 rows').click({ force: true }); + + // Select appropriate names to map fields to + for (let field_name in testMappings.properties) { + const mappedTo = testMappings.properties[field_name].path; + + cy.contains('tr', field_name).within(() => { + cy.get(`[data-test-subj="detector-field-mappings-select"]`).click().type(mappedTo); + }); + } + + // Continue to next page + cy.get('button').contains('Next').click({ force: true, timeout: 2000 }); + + // Check that correct page now showing + cy.contains('Set up alerts'); + + // Type name of new trigger + cy.get(`input[placeholder="Enter a name for the alert condition."]`).type('test_trigger'); + + // Type in (or select) tags for the alert condition + cy.get(`[data-test-subj="alert-tags-combo-box"]`).type('attack.defense_evasion{enter}'); + + // Select applicable severity levels + cy.get(`[data-test-subj="security-levels-combo-box"]`).click({ force: true }); + cy.contains('1 (Highest)').click({ force: true }); + + // Continue to next page + cy.contains('Next').click({ force: true }); + + // Confirm page is reached + cy.contains('Review and create'); + + // Confirm field mappings registered + cy.contains('Field mapping'); + + // Show 50 rows per page + cy.contains('Rows per page').click({ force: true }); + cy.contains('50 rows').click({ force: true }); + + for (let field in testMappings.properties) { + const mappedTo = testMappings.properties[field].path; + + cy.contains(field); + cy.contains(mappedTo); + } + + // Confirm entries user has made + cy.contains('Detector details'); + cy.contains(detectorName); + cy.contains('windows'); + cy.contains(indexName); + cy.contains('Alert on test_trigger'); + + // Create the detector + cy.get('button').contains('Create').click({ force: true }); + cy.waitForPageLoad('detector-details', { + contains: detectorName, + }); + + // Confirm detector active + cy.contains(detectorName); + cy.contains('Active'); + cy.contains('View Alerts'); + cy.contains('View Findings'); + cy.contains('Actions'); + cy.contains('Detector configuration'); + cy.contains('Field mappings'); + cy.contains('Alert triggers'); + cy.contains('Detector details'); + cy.contains('Created at'); + cy.contains('Last updated time'); + }); + + it('...basic details can be edited', () => { + // Click on detector name + cy.contains(detectorName).click({ force: true }); + cy.waitForPageLoad('detector-details', { + contains: detectorName, + }); + + // Click "Edit" button in detector details + cy.get(`[data-test-subj="edit-detector-basic-details"]`).click({ force: true }); + + // Confirm arrival at "Edit detector details" page + cy.waitForPageLoad('edit-detector-details', { + contains: 'Edit detector details', + }); + + // Change detector name + cy.get(`[data-test-subj="define-detector-detector-name"]`).type('_edited'); + + // Change detector description + cy.get(`[data-test-subj="define-detector-detector-description"]`).type('Edited description'); + + // Change input source + cy.get(`[data-test-subj="define-detector-select-data-source"]`).type( + '{backspace}.opensearch-notifications-config{enter}' + ); + + // Change detector scheduling + cy.get(`[data-test-subj="detector-schedule-number-select"]`).type('{selectall}10'); + cy.get(`[data-test-subj="detector-schedule-unit-select"]`).select('Hours'); + + // Save changes to detector details + cy.get(`[data-test-subj="save-basic-details-edits"]`).click({ force: true }); + + // Confirm taken to detector details page + cy.waitForPageLoad('detector-details', { + contains: detectorName, + }); + + // Verify edits are applied + cy.contains('test detector_edited'); + cy.contains('Every 10 hours'); + cy.contains('Edited description'); + cy.contains('.opensearch-notifications-config'); + }); + + it('...rules can be edited', () => { + // Ensure start on main detectors page + cy.waitForPageLoad('detectors', { + contains: 'Threat detectors', + }); + + // Click on detector name + cy.contains(detectorName).click({ force: true }); + cy.waitForPageLoad('detector-details', { + contains: detectorName, + }); + + // Confirm number of rules before edit + cy.contains('Active rules (1)'); + + // Click "Edit" button in Detector rules panel + cy.get(`[data-test-subj="edit-detector-rules"]`).click({ force: true }); + + // Confirm arrival on "Edit detector rules" page + cy.url().should( + 'include', + 'http://localhost:5601/app/opensearch_security_analytics_dashboards#/edit-detector-rules' + ); + + // Search for specific rule + cy.triggerSearchField('Search...', 'USB Device'); + + // Toggle single search result to unchecked + cy.contains('tr', 'USB Device Plugged').within(() => { + // Of note, timeout can sometimes work instead of wait here, but is very unreliable from case to case. + cy.wait(1000); + cy.get('button').eq(1).click(); + }); + + // Save changes + cy.get(`[data-test-subj="save-detector-rules-edits"]`).click({ force: true }); + + // Confirm 1 rule has been removed from detector + cy.contains('Active rules (0)'); + + // Click "Edit" button in Detector rules panel + cy.get(`[data-test-subj="edit-detector-rules"]`).click({ force: true }); + + // Confirm arrival on "Edit detector rules" page + cy.waitForPageLoad('edit-detector-rules', { + contains: 'Edit detector rules', + }); + + // Search for specific rule + cy.triggerSearchField('Search...', 'USB'); + + // Toggle single search result to checked + cy.contains('tr', 'USB Device Plugged').within(() => { + cy.wait(2000); + cy.get('button').eq(1).click({ force: true }); + }); + + // Save changes + cy.get(`[data-test-subj="save-detector-rules-edits"]`).click({ force: true }); + cy.waitForPageLoad('detector-details', { + contains: detectorName, + }); + + // Confirm 1 rule has been added to detector + cy.contains('Active rules (1)'); + }); + + it('...can be deleted', () => { + // Click on detector to be removed + cy.contains('test detector_edited').click({ force: true }); + + // Confirm page + cy.waitForPageLoad('detector-details', { + contains: 'Detector details', + }); + + // Click "Actions" button, the click "Delete" + cy.contains('Actions').click({ force: true }); + cy.contains('Delete').click({ force: true }); + + // Confirm detector is deleted + cy.contains('There are no existing detectors'); + }); + + after(() => cy.cleanUpTests()); +}); diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js new file mode 100644 index 000000000..eff0cff07 --- /dev/null +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js @@ -0,0 +1,237 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { OPENSEARCH_DASHBOARDS_URL } from '../support/constants'; + +const uniqueId = Cypress._.random(0, 1e6); +const SAMPLE_RULE = { + name: `Cypress test rule ${uniqueId}`, + logType: 'windows', + description: 'This is a rule used to test the rule creation workflow.', + detection: + 'selection:\n Provider_Name: Service Control Manager\nEventID: 7045\nServiceName: ZzNetSvc\n{backspace}{backspace}condition: selection', + detectionLine: [ + 'selection:', + 'Provider_Name: Service Control Manager', + 'EventID: 7045', + 'ServiceName: ZzNetSvc', + 'condition: selection', + ], + severity: 'critical', + tags: ['attack.persistence', 'attack.privilege_escalation', 'attack.t1543.003'], + references: 'https://nohello.com', + falsePositive: 'unknown', + author: 'Cypress Test Runner', + status: 'experimental', +}; + +const YAML_RULE_LINES = [ + `id:`, + `logsource:`, + `product: ${SAMPLE_RULE.logType}`, + `title: ${SAMPLE_RULE.name}`, + `description: ${SAMPLE_RULE.description}`, + `tags:`, + `- ${SAMPLE_RULE.tags[0]}`, + `- ${SAMPLE_RULE.tags[1]}`, + `- ${SAMPLE_RULE.tags[2]}`, + `falsepositives:`, + `- ${SAMPLE_RULE.falsePositive}`, + `level: ${SAMPLE_RULE.severity}`, + `status: ${SAMPLE_RULE.status}`, + `references:`, + `- '${SAMPLE_RULE.references}'`, + `author: ${SAMPLE_RULE.author}`, + `detection:`, + ...SAMPLE_RULE.detection.replaceAll(' ', '').replaceAll('{backspace}', '').split('\n'), +]; + +describe('Rules', () => { + before(() => cy.cleanUpTests()); + beforeEach(() => { + // Visit Rules page + cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/rules`); + + // Check that correct page is showing + cy.waitForPageLoad('rules', { + contains: 'Rules', + }); + }); + + it('...can be created', () => { + // Click "create new rule" button + cy.get('[data-test-subj="create_rule_button"]').click({ + force: true, + }); + + // Enter the name + cy.get('[data-test-subj="rule_name_field"]').type(SAMPLE_RULE.name); + + // Enter the log type + cy.get('[data-test-subj="rule_type_dropdown"]').type(SAMPLE_RULE.logType); + + // Enter the description + cy.get('[data-test-subj="rule_description_field"]').type(SAMPLE_RULE.description); + + // Enter the severity + cy.get('[data-test-subj="rule_severity_dropdown"]').type(SAMPLE_RULE.severity); + + // Enter the tags + SAMPLE_RULE.tags.forEach((tag) => + cy.get('[data-test-subj="rule_tags_dropdown"]').type(`${tag}{enter}{esc}`) + ); + + // Enter the reference + cy.get('[data-test-subj="rule_references_field_0"]').type(SAMPLE_RULE.references); + + // Enter the false positive cases + cy.get('[data-test-subj="rule_false_positives_field_0"]').type(SAMPLE_RULE.falsePositive); + + // Enter the author + cy.get('[data-test-subj="rule_author_field"]').type(SAMPLE_RULE.author); + + // Enter the log type + cy.get('[data-test-subj="rule_status_dropdown"]').type(SAMPLE_RULE.status); + + // Enter the detection + cy.get('[data-test-subj="rule_detection_field"]').type(SAMPLE_RULE.detection); + + // Switch to YAML editor + cy.get('[data-test-subj="change-editor-type"] label:nth-child(2)').click({ + force: true, + }); + + YAML_RULE_LINES.forEach((line) => cy.get('[data-test-subj="rule_yaml_editor"]').contains(line)); + + cy.intercept({ + url: '/rules', + }).as('getRules'); + + // Click "create" button + cy.get('[data-test-subj="submit_rule_form_button"]').click({ + force: true, + }); + + cy.waitForPageLoad('rules', { + contains: 'Rules', + }); + + cy.wait('@getRules'); + + // Search for the rule + cy.triggerSearchField('Search rules', 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, + }); + }); + }); + + it('...can be deleted', () => { + cy.intercept({ + url: '/rules', + }).as('deleteRule'); + + cy.triggerSearchField('Search rules', 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 }); + + cy.get('.euiButton') + .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.wait('@deleteRule'); + + // Search for sample_detector, presumably deleted + cy.triggerSearchField('Search rules', SAMPLE_RULE.name); + // Click the rule link to open the details flyout + cy.get('tbody').contains(SAMPLE_RULE.name).should('not.exist'); + }); + }); + + after(() => cy.cleanUpTests()); +}); diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js new file mode 100644 index 000000000..332328c82 --- /dev/null +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js @@ -0,0 +1,445 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import moment from 'moment'; +import { DETECTOR_TRIGGER_TIMEOUT, OPENSEARCH_DASHBOARDS_URL } from '../support/constants'; +import sample_index_settings from '../fixtures/sample_index_settings.json'; +import sample_alias_mappings from '../fixtures/sample_alias_mappings.json'; +import sample_detector from '../fixtures/sample_detector.json'; +import sample_document from '../fixtures/sample_document.json'; + +const testIndex = 'sample_alerts_spec_cypress_test_index'; +const testDetectorName = 'alerts_spec_cypress_test_detector'; +const testDetectorAlertCondition = `${testDetectorName} alert condition`; + +// Creating a unique detector JSON for this test spec +const testDetector = { + ...sample_detector, + name: testDetectorName, + inputs: [ + { + detector_input: { + ...sample_detector.inputs[0].detector_input, + description: `Description for ${testDetectorName}`, + indices: [testIndex], + }, + }, + ], + triggers: [ + { + ...sample_detector.triggers[0], + name: testDetectorAlertCondition, + }, + ], +}; + +// The exact minutes/seconds for the start and last updated time will be difficult to predict, +// but all of the alert time fields should all contain the date in this format. +const date = moment(moment.now()).format('MM/DD/YY'); + +const docCount = 4; +describe('Alerts', () => { + before(() => { + // Delete any pre-existing test detectors + cy.cleanUpTests() + // Create test index + .then(() => cy.createIndex(testIndex, sample_index_settings)) + + // Create field mappings + .then(() => + cy.createAliasMappings(testIndex, testDetector.detector_type, sample_alias_mappings, true) + ) + + // Create test detector + .then(() => cy.createDetector(testDetector)) + + .then(() => { + // Go to the detectors table page + cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/detectors`); + + // Check that correct page is showing + cy.waitForPageLoad('detectors', { + contains: 'Threat detectors', + }); + + // Filter table to only show the test detector + cy.get(`input[type="search"]`).type(`${testDetector.name}{enter}`); + + // Confirm detector was created + cy.get('tbody > tr').should(($tr) => { + expect($tr, 'detector name').to.contain(testDetector.name); + }); + }); + + // Ingest documents to the test index + for (let i = 0; i < docCount; i++) { + cy.insertDocumentToIndex(testIndex, '', sample_document); + } + + // Wait for the detector to execute + cy.wait(DETECTOR_TRIGGER_TIMEOUT); + }); + + beforeEach(() => { + // Visit Alerts table page + cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/alerts`); + + // Wait for page to load + cy.waitForPageLoad('alerts', { + contains: 'Security alerts', + }); + + // Filter table to only show alerts for the test detector + cy.get(`input[type="search"]`).type(`${testDetector.name}{enter}`); + + // Adjust the date range picker to display alerts from today + cy.get('[class="euiButtonEmpty__text euiQuickSelectPopover__buttonText"]').click({ + force: true, + }); + cy.get('[data-test-subj="superDatePickerCommonlyUsed_Today"]').click({ force: true }); + }); + + it('are generated', () => { + // Refresh the table + cy.get('[data-test-subj="superDatePickerApplyTimeButton"]').click({ force: true }); + + // Confirm there are alerts created + cy.get('tbody > tr') + .filter(`:contains(${testDetectorAlertCondition})`) + .should('have.length', docCount); + }); + + it('contain expected values in table', () => { + // Confirm there is a row containing the expected values + cy.get('tbody > tr').should(($tr) => { + expect($tr, 'start time').to.contain(date); + expect($tr, 'trigger name').to.contain(testDetector.triggers[0].name); + expect($tr, 'detector name').to.contain(testDetector.name); + expect($tr, 'status').to.contain('Active'); + expect($tr, 'severity').to.contain('4 (Low)'); + }); + }); + + it('contain expected values in alert details flyout', () => { + cy.get('tbody > tr') + .first() + .within(() => { + // Click the "View details" button for the first alert + cy.get('[aria-label="View details"]').click({ force: true }); + }); + + // Get the details flyout, and validate its content + cy.get('[data-test-subj="alert-details-flyout"]').within(() => { + // Confirm alert condition name + cy.get('[data-test-subj="text-details-group-content-alert-trigger-name"]').contains( + testDetector.triggers[0].name + ); + + // Confirm alert status + cy.get('[data-test-subj="text-details-group-content-alert-status"]').contains('Active'); + + // Confirm alert severity + cy.get('[data-test-subj="text-details-group-content-alert-severity"]').contains('4 (Low)'); + + // Confirm alert start time is present + cy.get('[data-test-subj="text-details-group-content-start-time"]').contains(date); + + // Confirm alert last updated time is present + cy.get('[data-test-subj="text-details-group-content-last-updated-time"]').contains(date); + + // Confirm alert detector name + cy.get('[data-test-subj="text-details-group-content-detector"]').contains(testDetector.name); + + // Wait for the findings table to finish loading + cy.contains('Findings (1)'); + cy.contains('USB Device Plugged'); + + // Confirm alert findings contain expected values + cy.get('tbody > tr').should(($tr) => { + expect($tr, `timestamp`).to.contain(date); + expect($tr, `rule name`).to.contain('USB Device Plugged'); + expect($tr, `detector name`).to.contain(testDetector.name); + expect($tr, `log type`).to.contain('Windows'); + }); + + // Close the flyout + cy.get('[data-test-subj="alert-details-flyout-close-button"]').click({ force: true }); + }); + + // Confirm flyout has been closed + cy.contains('[data-test-subj="alert-details-flyout"]').should('not.exist'); + }); + + it('contain expected values in finding details flyout', () => { + // Open first alert details flyout + cy.get('tbody > tr') + .first() + .within(() => { + // Click the "View details" button for the first alert + cy.get('[aria-label="View details"]').click({ force: true }); + }); + + cy.get('[data-test-subj="alert-details-flyout"]').within(() => { + // Wait for findings table to finish loading + cy.contains('USB Device Plugged'); + + // Click the details button for the first finding + cy.get('tbody > tr') + .first() + .within(() => { + cy.get('[data-test-subj="finding-details-flyout-button"]').click({ + force: true, + }); + }); + }); + + // Confirm the details flyout contains the expected content + cy.get('[data-test-subj="finding-details-flyout"]').within(() => { + // Confirm finding ID is present + cy.get('[data-test-subj="finding-details-flyout-finding-id"]') + .invoke('text') + .then((text) => expect(text).to.have.length.greaterThan(1)); + + // Confirm finding timestamp + cy.get('[data-test-subj="finding-details-flyout-timestamp"]').contains(date); + + // Confirm finding detector name + cy.get('[data-test-subj="finding-details-flyout-detector-link"]').contains(testDetector.name); + + // Confirm there's only 1 rule details accordion + cy.get('[data-test-subj="finding-details-flyout-rule-accordion-1"]').should('not.exist'); + + // Check the rule details accordion for the expected values + cy.get('[data-test-subj="finding-details-flyout-rule-accordion-0"]').within(() => { + // Confirm the accordion button contains the expected text + cy.get('[data-test-subj="finding-details-flyout-rule-accordion-button"]').contains( + 'USB Device Plugged' + ); + cy.get('[data-test-subj="finding-details-flyout-rule-accordion-button"]').contains( + 'Severity: Low' + ); + + // Confirm the rule name + cy.get('[data-test-subj="finding-details-flyout-USB Device Plugged-details"]').contains( + 'USB Device Plugged' + ); + + // Confirm the rule severity + cy.get('[data-test-subj="finding-details-flyout-rule-severity"]').contains('Low'); + + // Confirm the rule category + cy.get('[data-test-subj="finding-details-flyout-rule-category"]').contains('Windows'); + + // Confirm the rule description + cy.get('[data-test-subj="finding-details-flyout-rule-description"]').contains( + 'Detects plugged USB devices' + ); + + // Confirm the rule tags + ['low', 'windows', 'attack.initial_access', 'attack.t1200'].forEach((tag) => { + cy.get('[data-test-subj="finding-details-flyout-rule-tags"]').contains(tag); + }); + }); + + // Confirm the rule document ID is present + cy.get('[data-test-subj="finding-details-flyout-rule-document-id"]') + .invoke('text') + .then((text) => expect(text).to.not.equal('-')); + + // Confirm the rule index + cy.get('[data-test-subj="finding-details-flyout-rule-document-index"]').contains(testIndex); + + // Confirm the rule document matches + // The EuiCodeEditor used for this component stores each line of the JSON in an array of elements; + // so this test formats the expected document into an array of strings, + // and matches each entry with the corresponding element line. + const document = JSON.stringify( + JSON.parse( + '{"EventTime":"2020-02-04T14:59:39.343541+00:00","HostName":"EC2AMAZ-EPO7HKA","Keywords":"9223372036854775808","SeverityValue":2,"Severity":"INFO","EventID":2003,"SourceName":"Microsoft-Windows-Sysmon","ProviderGuid":"{5770385F-C22A-43E0-BF4C-06F5698FFBD9}","Version":5,"TaskValue":22,"OpcodeValue":0,"RecordNumber":9532,"ExecutionProcessID":1996,"ExecutionThreadID":2616,"Channel":"Microsoft-Windows-Sysmon/Operational","Domain":"NT AUTHORITY","AccountName":"SYSTEM","UserID":"S-1-5-18","AccountType":"User","Message":"Dns query:\\r\\nRuleName: \\r\\nUtcTime: 2020-02-04 14:59:38.349\\r\\nProcessGuid: {b3c285a4-3cda-5dc0-0000-001077270b00}\\r\\nProcessId: 1904\\r\\nQueryName: EC2AMAZ-EPO7HKA\\r\\nQueryStatus: 0\\r\\nQueryResults: 172.31.46.38;\\r\\nImage: C:\\\\Program Files\\\\nxlog\\\\nxlog.exe","Category":"Dns query (rule: DnsQuery)","Opcode":"Info","UtcTime":"2020-02-04 14:59:38.349","ProcessGuid":"{b3c285a4-3cda-5dc0-0000-001077270b00}","ProcessId":"1904","QueryName":"EC2AMAZ-EPO7HKA","QueryStatus":"0","QueryResults":"172.31.46.38;","Image":"C:\\\\Program Files\\\\nxlog\\\\regsvr32.exe","EventReceivedTime":"2020-02-04T14:59:40.780905+00:00","SourceModuleName":"in","SourceModuleType":"im_msvistalog","CommandLine":"eachtest","Initiated":"true","Provider_Name":"Microsoft-Windows-Kernel-General","TargetObject":"\\\\SOFTWARE\\\\Microsoft\\\\Office\\\\Outlook\\\\Security","EventType":"SetValue"}' + ), + null, + 2 + ); + const documentLines = document.split('\n'); + cy.get('[data-test-subj="finding-details-flyout-rule-document"]') + .get('[class="euiCodeBlock__line"]') + .each((lineElement, lineIndex) => { + let line = lineElement.text(); + let expectedLine = documentLines[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.trimStart().startsWith('"id": "')) { + expectedLine = '"id": "'; + expect(line, `document JSON line ${lineIndex}`).to.contain(expectedLine); + } else { + line = line.replaceAll('\n', ''); + expect(line, `document JSON line ${lineIndex}`).to.equal(expectedLine); + } + }); + + // Press the "back" button + cy.get('[data-test-subj="finding-details-flyout-back-button"]').click({ force: true }); + }); + + // Confirm finding details flyout closed + cy.get('[data-test-subj="finding-details-flyout"]').should('not.exist'); + + // Confirm the expected alert details flyout rendered + cy.get('[data-test-subj="alert-details-flyout"]').within(() => { + cy.get('[data-test-subj="text-details-group-content-alert-trigger-name"]').contains( + testDetector.triggers[0].name + ); + }); + }); + + it('can be bulk acknowledged', () => { + // Confirm the "Acknowledge" button is disabled when no alerts are selected + cy.get('[data-test-subj="acknowledge-button"]').should('be.disabled'); + + // Confirm there is alert which is currently "Active" + cy.get('tbody > tr').should(($tr) => { + expect($tr, `status`).to.contain('Active'); + }); + + // Click the checkboxes for the first and last alerts. + cy.get('tbody > tr') + .first() + .within(() => { + cy.get('[class="euiCheckbox__input"]').click({ force: true }); + }); + + // Press the "Acknowledge" button + cy.get('[data-test-subj="acknowledge-button"]').click({ force: true }); + + // Wait for acknowledge API to finish executing + cy.contains('Acknowledged'); + + // Filter the table to show only "Acknowledged" alerts + cy.get('[data-text="Status"]').click({ force: true }); + cy.get('[class="euiFilterSelect__items"]').within(() => { + cy.contains('Acknowledged').click({ force: true }); + }); + + // Confirm there is an "Acknowledged" alert + cy.get('tbody > tr').should(($tr) => { + expect($tr, `alert name`).to.contain(testDetectorAlertCondition); + expect($tr, `status`).to.contain('Acknowledged'); + }); + + // Filter the table to show only "Active" alerts + cy.get('[data-text="Status"]'); + cy.get('[class="euiFilterSelect__items"]').within(() => { + cy.contains('Acknowledged').click({ force: true }); + }); + + // Confirm there are now 2 "Acknowledged" alerts + cy.get('tbody > tr') + .filter(`:contains(${testDetectorAlertCondition})`) + .should('contain', 'Active') + .should('contain', 'Acknowledged'); + }); + + it('can be acknowledged via row button', () => { + // Filter the table to show only "Active" alerts + cy.get('[data-text="Status"]').click({ force: true }); + cy.get('[class="euiFilterSelect__items"]').within(() => { + cy.contains('Active').click({ force: true }); + }); + + cy.get('tbody > tr') + .filter(`:contains(${testDetectorAlertCondition})`) + .should('have.length', 3); + + cy.get('tbody > tr') + // Click the "Acknowledge" icon button in the first row + .first() + .within(() => { + cy.get('[aria-label="Acknowledge"]').click({ force: true }); + }); + + cy.get('tbody > tr') + .filter(`:contains(${testDetectorAlertCondition})`) + .should('have.length', 2); + + // Filter the table to show only "Acknowledged" alerts + cy.get('[data-text="Status"]'); + cy.get('[class="euiFilterSelect__items"]').within(() => { + cy.contains('Active').click({ force: true }); + cy.contains('Acknowledged').click({ force: true }); + }); + + // Confirm there are now 3 "Acknowledged" alerts + cy.get('tbody > tr') + .filter(`:contains(${testDetectorAlertCondition})`) + .should('have.length', 2); + }); + + it('can be acknowledged via flyout button', () => { + // Filter the table to show only "Active" alerts + cy.get('[data-text="Status"]').click({ force: true }); + cy.get('[class="euiFilterSelect__items"]').within(() => { + cy.contains('Active').click({ force: true }); + }); + + cy.get('tbody > tr') + .first() + .within(() => { + // Click the "View details" button for the first alert + cy.get('[aria-label="View details"]').click({ force: true }); + }); + + cy.get('[data-test-subj="alert-details-flyout"]').within(() => { + // Confirm the alert is currently "Active" + cy.get('[data-test-subj="text-details-group-content-alert-status"]').contains('Active'); + + // Click the "Acknowledge" button on the flyout + cy.get('[data-test-subj="alert-details-flyout-acknowledge-button"]').click({ force: true }); + + // Confirm the alert is now "Acknowledged" + cy.get('[data-test-subj="text-details-group-content-alert-status"]').contains('Active'); + + // Confirm the "Acknowledge" button is disabled + cy.get('[data-test-subj="alert-details-flyout-acknowledge-button"]').should('be.disabled'); + }); + }); + + it('detector name hyperlink on finding details flyout redirects to the detector details page', () => { + // Open first alert details flyout + cy.get('tbody > tr') + .first() + .within(() => { + // Click the "View details" button for the first alert + cy.get('[aria-label="View details"]').click({ force: true }); + }); + + cy.get('[data-test-subj="alert-details-flyout"]').within(() => { + // Wait for findings table to finish loading + cy.contains('USB Device Plugged'); + + // Click the details button for the first finding + cy.get('tbody > tr') + .first() + .within(() => { + cy.get('[data-test-subj="finding-details-flyout-button"]').click({ + force: true, + }); + }); + }); + + cy.get('[data-test-subj="finding-details-flyout"]').within(() => { + // Click the detector name hyperlink + cy.get('[data-test-subj="finding-details-flyout-detector-link"]') + // Removing the "target" attribute so the link won't open a new tab. Cypress wouldn't test the new tab. + .invoke('removeAttr', 'target') + .click({ force: true }); + }); + + // Confirm the detector details page is for the expected detector + cy.get('[data-test-subj="detector-details-detector-name"]').contains(testDetector.name); + }); + + after(() => cy.cleanUpTests()); +}); diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js new file mode 100644 index 000000000..e68a9bbe8 --- /dev/null +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js @@ -0,0 +1,178 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { DETECTOR_TRIGGER_TIMEOUT, OPENSEARCH_DASHBOARDS_URL } from '../support/constants'; +import sample_document from '../fixtures/sample_document.json'; +import sample_index_settings from '../fixtures/sample_index_settings.json'; +import sample_field_mappings from '../fixtures/sample_field_mappings.json'; +import sample_detector from '../fixtures/sample_detector.json'; + +describe('Findings', () => { + const ruleTags = ['low', 'windows']; + const indexName = 'cypress-test-windows'; + + before(() => { + cy.cleanUpTests(); + + // Visit Findings page + cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/findings`); + + // create test index, mappings, and detector + cy.createIndex(indexName, sample_index_settings); + cy.createAliasMappings(indexName, 'windows', sample_field_mappings, true); + cy.createDetector(sample_detector); + + // Ingest a new document + cy.insertDocumentToIndex(indexName, '', sample_document); + + // wait for detector interval to pass + cy.wait(DETECTOR_TRIGGER_TIMEOUT); + }); + + beforeEach(() => { + // Visit Alerts table page + cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/findings`); + + // Wait for page to load + cy.waitForPageLoad('findings', { + contains: 'Findings', + }); + }); + + it('displays findings based on recently ingested data', () => { + // Click refresh + cy.get('button').contains('Refresh').click({ force: true }); + + // Check for non-empty findings list + cy.contains('No items found').should('not.exist'); + + // Check for expected findings + cy.contains('sample_detector'); + cy.contains('Windows'); + cy.contains('Low'); + }); + + it('displays finding details flyout when user clicks on View details icon', () => { + // filter table to show only sample_detector findings + cy.triggerSearchField('Search findings', 'sample_detector'); + + // Click View details icon + cy.getTableFirstRow('[data-test-subj="view-details-icon"]').then(($el) => { + cy.get($el).click({ force: true }); + }); + + // Confirm flyout contents + cy.contains('Finding details'); + cy.contains('Rule details'); + + // Close Flyout + cy.get('.euiFlexItem--flexGrowZero > .euiButtonIcon').click({ force: true }); + }); + + it('displays finding details flyout when user clicks on Finding ID', () => { + // filter table to show only sample_detector findings + cy.triggerSearchField('Search findings', 'sample_detector'); + + // Click findingId to trigger Finding details flyout + cy.getTableFirstRow('[data-test-subj="finding-details-flyout-button"]').then(($el) => { + cy.get($el).click({ force: true }); + }); + + // Confirm flyout contents + cy.contains('Finding details'); + cy.contains('Rule details'); + + // Close Flyout + cy.get('.euiFlexItem--flexGrowZero > .euiButtonIcon').click({ force: true }); + }); + + it('allows user to view details about rules that were triggered', () => { + // filter table to show only sample_detector findings + cy.triggerSearchField('Search findings', 'sample_detector'); + + // open Finding details flyout via finding id link. cy.wait essential, timeout insufficient. + cy.get(`[data-test-subj="view-details-icon"]`).eq(0).click({ force: true }); + + // open rule details inside flyout + cy.get('button', { timeout: 1000 }); + cy.get(`[data-test-subj="finding-details-flyout-rule-accordion-0"]`).click({ force: true }); + + // Confirm content + cy.contains('Documents'); + cy.contains('Detects plugged USB devices'); + cy.contains('Low'); + cy.contains('Windows'); + cy.contains(indexName); + + ruleTags.forEach((tag) => { + cy.contains(tag); + }); + }); + + // TODO - upon reaching rules page, trigger appropriate rules detail flyout + // see github issue #124 at https://github.com/opensearch-project/security-analytics-dashboards-plugin/issues/124 + + it('opens rule details flyout when rule name inside accordion drop down is clicked', () => { + // filter table to show only sample_detector findings + cy.triggerSearchField('Search findings', 'sample_detector'); + + // open Finding details flyout via finding id link. cy.wait essential, timeout insufficient. + cy.getTableFirstRow('[data-test-subj="view-details-icon"]').then(($el) => { + cy.get($el).click({ force: true }); + }); + + // Click rule link + cy.get(`[data-test-subj="finding-details-flyout-USB Device Plugged-details"]`).click({ + force: true, + }); + + // Validate flyout appearance + cy.get('[data-test-subj="rule_flyout_USB Device Plugged"]').within(() => { + cy.get('[data-test-subj="rule_flyout_rule_name"]').contains('USB Device Plugged'); + }); + }); + + it('...can delete detector', () => { + // Visit Detectors page + cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/detectors`); + cy.waitForPageLoad('detectors', { + contains: 'Threat detectors', + }); + + // filter table to show only sample_detector findings + cy.triggerSearchField('Search threat detectors', 'sample_detector'); + + // intercept detectors and rules requests + cy.intercept('detectors/_search').as('getDetector'); + cy.intercept('rules/_search?prePackaged=true').as('getPrePackagedRules'); + cy.intercept('rules/_search?prePackaged=false').as('getRules'); + + // Click on detector to be removed + cy.contains('sample_detector').click({ force: true }); + cy.waitForPageLoad('detector-details', { + contains: sample_detector.name, + }); + + // wait for detector details to load before continuing + cy.wait(['@getDetector', '@getPrePackagedRules', '@getRules']).then(() => { + // Click "Actions" button, the click "Delete" + cy.get('button.euiButton') + .contains('Actions') + .click({ force: true }) + .then(() => { + // Confirm arrival at detectors page + cy.get('[data-test-subj="editButton"]').contains('Delete').click({ force: true }); + + // Search for sample_detector, presumably deleted + cy.triggerSearchField('Search threat detectors', 'sample_detector'); + + // Confirm sample_detector no longer exists + cy.contains('There are no existing detectors.'); + }); + }); + }); + + after(() => cy.cleanUpTests()); +}); diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js new file mode 100644 index 000000000..a38ea3ecb --- /dev/null +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js @@ -0,0 +1,142 @@ +/* + * Copyright OpenSearch Contributors + * SPDX-License-Identifier: Apache-2.0 + */ + +import { DETECTOR_TRIGGER_TIMEOUT, OPENSEARCH_DASHBOARDS_URL } from '../support/constants'; +import sample_index_settings from '../fixtures/sample_index_settings.json'; +import sample_dns_settings from '../fixtures/integration_tests/index/create_dns_settings.json'; +import windows_usb_rule_data from '../fixtures/integration_tests/rule/create_windows_usb_rule.json'; +import dns_rule_data from '../fixtures/integration_tests/rule/create_dns_rule.json'; +import usb_detector_data from '../fixtures/integration_tests/detector/create_usb_detector_data.json'; +import usb_detector_data_mappings from '../fixtures/integration_tests/detector/create_usb_detector_mappings_data.json'; +import dns_detector_data_mappings from '../fixtures/integration_tests/detector/create_dns_detector_mappings_data.json'; +import dns_detector_data from '../fixtures/integration_tests/detector/create_dns_detector_data.json'; +import add_windows_index_data from '../fixtures/integration_tests/index/add_windows_index_data.json'; +import add_dns_index_data from '../fixtures/integration_tests/index/add_dns_index_data.json'; + +describe('Integration tests', () => { + const indexName = 'cypress-index-windows'; + const dnsName = 'cypress-index-dns'; + + before(() => { + cy.cleanUpTests(); + + // Create custom rules + cy.createRule(windows_usb_rule_data).then((response) => { + usb_detector_data.inputs[0].detector_input.custom_rules[0].id = response.body.response._id; + usb_detector_data.triggers[0].ids.push(response.body.response._id); + }); + cy.createRule(dns_rule_data).then((response) => { + dns_detector_data.inputs[0].detector_input.custom_rules[0].id = response.body.response._id; + dns_detector_data.triggers[0].ids.push(response.body.response._id); + }); + + // Create test index + cy.createIndex(indexName, sample_index_settings); + cy.createIndex(dnsName, sample_dns_settings); + + // Create detectors + cy.createAliasMappings( + indexName, + usb_detector_data.detector_type, + usb_detector_data_mappings, + true + ).then(() => cy.createDetector(usb_detector_data)); + + cy.createAliasMappings( + dnsName, + dns_detector_data.detector_type, + dns_detector_data_mappings, + true + ).then(() => cy.createDetector(dns_detector_data)); + + // Ingest docs + cy.request( + 'POST', + `${Cypress.env('opensearch')}/${indexName}/_doc/101`, + add_windows_index_data + ); + cy.request('POST', `${Cypress.env('opensearch')}/${dnsName}/_doc/101`, add_dns_index_data); + + // Wait for detector interval to pass + cy.wait(DETECTOR_TRIGGER_TIMEOUT); + }); + + beforeEach(() => { + // Visit Detectors page + cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/detectors`); + + // Wait for page to load + cy.waitForPageLoad('detectors', 'Threat detectors'); + }); + + it('...can navigate to findings page', () => { + cy.intercept({ + method: 'GET', + pathname: '/_plugins/_security_analytics/findings/_search', + }).as('getFindings'); + + // Cypress USB Detector + cy.contains('Cypress USB Detector') + .click() + .then(() => { + cy.contains('View Findings') + .click() + .then(() => { + cy.hash() + .should('match', /findings\/.+$/) + .then((hash) => { + const detectorId = hash.replace('#/findings/', ''); + if (!detectorId) { + throw new Error('Navigating to findings page should contain detector ID'); + } else { + cy.wait('@getFindings').then((interception) => { + const url = new URL(interception.request.url); + // The request query param detectorId should match the hash param from the url + expect(url.searchParams.get('detectorId')).to.eq(detectorId); + }); + + // There should be only one call to the API + cy.get('@getFindings.all').should('have.length', 1); + } + }); + }); + }); + }); + it('...can navigate to alerts page', () => { + cy.intercept({ + method: 'GET', + pathname: '/_plugins/_security_analytics/alerts', + }).as('getAlerts'); + + // Cypress USB Detector + cy.contains('Cypress USB Detector') + .click() + .then(() => { + cy.contains('View Alerts') + .click() + .then(() => { + cy.hash() + .should('match', /alerts\/.+$/) + .then((hash) => { + const detectorId = hash.replace('#/alerts/', ''); + if (!detectorId) { + throw new Error('Navigating to alerts page should contain detector ID'); + } else { + cy.wait('@getAlerts').then((interception) => { + const url = new URL(interception.request.url); + // The request query param detectorId should match the hash param from the url + expect(url.searchParams.get('detector_id')).to.eq(detectorId); + }); + + // There should be only one call to the API + cy.get('@getAlerts.all').should('have.length', 1); + } + }); + }); + }); + }); + + after(() => cy.cleanUpTests()); +}); diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/rules_spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/rules_spec.js index e3c1884b1..e69de29bb 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/rules_spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/rules_spec.js @@ -1,201 +0,0 @@ -/* - * Copyright OpenSearch Contributors - * SPDX-License-Identifier: Apache-2.0 - */ - -import { PLUGIN_NAME, TWENTY_SECONDS_TIMEOUT } from '../../../utils/plugins/security-analytics-dashboards-plugin/constants' -import {BASE_PATH} from "../../../utils/base_constants"; - -const SAMPLE_RULE = { - name: 'Cypress test rule', - logType: 'windows', - description: 'This is a rule used to test the rule creation workflow. Not for production use.', - detection: - 'selection:\n Provider_Name: Service Control Manager\nEventID: 7045\nServiceName: ZzNetSvc\n{backspace}{backspace}condition: selection', - detectionLine: [ - 'selection:', - 'Provider_Name: Service Control Manager', - 'EventID: 7045', - 'ServiceName: ZzNetSvc', - 'condition: selection', - ], - severity: 'critical', - tags: ['attack.persistence', 'attack.privilege_escalation', 'attack.t1543.003'], - references: 'https://nohello.com', - falsePositive: 'unknown', - author: 'Cypress Test Runner', - status: 'experimental', -}; - -describe('Rules', () => { - before(() => { - // Deleting pre-existing test rules - cy.deleteRule(SAMPLE_RULE.name); - }); - beforeEach(() => { - // Visit Rules page - cy.visit(`${BASE_PATH}/app/${PLUGIN_NAME}#/rules`); - }); - - describe('Can be created', () => { - it('manually using UI', () => { - // Click "create new rule" button - cy.get('[data-test-subj="create_rule_button"]', TWENTY_SECONDS_TIMEOUT).click({ - force: true, - }); - - // Enter the name - cy.get('[data-test-subj="rule_name_field"]', TWENTY_SECONDS_TIMEOUT).type(SAMPLE_RULE.name); - - // Enter the log type - cy.get('[data-test-subj="rule_type_dropdown"]', TWENTY_SECONDS_TIMEOUT).select( - SAMPLE_RULE.logType - ); - - // Enter the description - cy.get('[data-test-subj="rule_description_field"]', TWENTY_SECONDS_TIMEOUT).type( - SAMPLE_RULE.description - ); - - // Enter the detection - cy.get('[data-test-subj="rule_detection_field"]', TWENTY_SECONDS_TIMEOUT).type( - SAMPLE_RULE.detection - ); - - // Enter the severity - cy.get('[data-test-subj="rule_severity_dropdown"]', TWENTY_SECONDS_TIMEOUT).select( - SAMPLE_RULE.severity - ); - - // Enter the tags - SAMPLE_RULE.tags.forEach((tag) => - cy - .get('[data-test-subj="rule_tags_dropdown"]', TWENTY_SECONDS_TIMEOUT) - .type(`${tag}{enter}{esc}`) - ); - - // Enter the reference - cy.get('[data-test-subj="rule_references_field_0"]', TWENTY_SECONDS_TIMEOUT).type( - SAMPLE_RULE.references - ); - - // Enter the false positive cases - cy.get('[data-test-subj="rule_false_positive_cases_field_0"]', TWENTY_SECONDS_TIMEOUT).type( - SAMPLE_RULE.falsePositive - ); - - // Enter the author - cy.get('[data-test-subj="rule_author_field"]', TWENTY_SECONDS_TIMEOUT).type( - SAMPLE_RULE.author - ); - - // Enter the log type - cy.get('[data-test-subj="rule_status_dropdown"]', TWENTY_SECONDS_TIMEOUT).select( - SAMPLE_RULE.status - ); - - // Click "create" button - cy.get('[data-test-subj="create_rule_button"]', TWENTY_SECONDS_TIMEOUT).click({ - force: true, - }); - - // Wait for the page to finish loading - cy.wait(5000); - cy.contains('No items found', TWENTY_SECONDS_TIMEOUT).should('not.exist'); - - // Search for the rule - cy.get(`input[type="search"]`, TWENTY_SECONDS_TIMEOUT) - // .focus() - .type(`${SAMPLE_RULE.name}{enter}`); - - // Click the rule link to open the details flyout - cy.get(`[data-test-subj="rule_link_${SAMPLE_RULE.name}"]`, TWENTY_SECONDS_TIMEOUT).click(); - - // Confirm the flyout contains the expected values - cy.get(`[data-test-subj="rule_flyout_${SAMPLE_RULE.name}"]`, TWENTY_SECONDS_TIMEOUT) - .click({ force: true }) - .within(() => { - // Validate name - cy.get('[data-test-subj="rule_flyout_rule_name"]', TWENTY_SECONDS_TIMEOUT).contains( - SAMPLE_RULE.name, - TWENTY_SECONDS_TIMEOUT - ); - - // Validate log type - cy.get('[data-test-subj="rule_flyout_rule_log_type"]', TWENTY_SECONDS_TIMEOUT).contains( - SAMPLE_RULE.logType, - TWENTY_SECONDS_TIMEOUT - ); - - // Validate description - cy.get( - '[data-test-subj="rule_flyout_rule_description"]', - TWENTY_SECONDS_TIMEOUT - ).contains(SAMPLE_RULE.description, TWENTY_SECONDS_TIMEOUT); - - // Validate author - cy.get('[data-test-subj="rule_flyout_rule_author"]', TWENTY_SECONDS_TIMEOUT).contains( - SAMPLE_RULE.author, - TWENTY_SECONDS_TIMEOUT - ); - - // Validate source is "custom" - cy.get('[data-test-subj="rule_flyout_rule_source"]', TWENTY_SECONDS_TIMEOUT).contains( - 'Custom', - TWENTY_SECONDS_TIMEOUT - ); - - // Validate severity - cy.get('[data-test-subj="rule_flyout_rule_severity"]', TWENTY_SECONDS_TIMEOUT).contains( - SAMPLE_RULE.severity, - TWENTY_SECONDS_TIMEOUT - ); - - // Validate tags - SAMPLE_RULE.tags.forEach((tag) => - cy - .get('[data-test-subj="rule_flyout_rule_tags"]', TWENTY_SECONDS_TIMEOUT) - .contains(tag, TWENTY_SECONDS_TIMEOUT) - ); - - // Validate references - cy.get('[data-test-subj="rule_flyout_rule_references"]', TWENTY_SECONDS_TIMEOUT).contains( - SAMPLE_RULE.references, - TWENTY_SECONDS_TIMEOUT - ); - - // Validate false positives - cy.get( - '[data-test-subj="rule_flyout_rule_false_positives"]', - TWENTY_SECONDS_TIMEOUT - ).contains(SAMPLE_RULE.falsePositive, TWENTY_SECONDS_TIMEOUT); - - // Validate status - cy.get('[data-test-subj="rule_flyout_rule_status"]', TWENTY_SECONDS_TIMEOUT).contains( - SAMPLE_RULE.status, - TWENTY_SECONDS_TIMEOUT - ); - - // Validate detection - SAMPLE_RULE.detectionLine.forEach((line) => - cy - .get('[data-test-subj="rule_flyout_rule_detection"]', TWENTY_SECONDS_TIMEOUT) - .contains(line, TWENTY_SECONDS_TIMEOUT) - ); - - // Close the flyout - cy.get('[data-test-subj="euiFlyoutCloseButton"]', TWENTY_SECONDS_TIMEOUT).click({ - force: true, - }); - }); - - // Confirm flyout closed - cy.contains(`[data-test-subj="rule_flyout_${SAMPLE_RULE.name}"]`).should('not.exist'); - }); - }); - - after(() => { - // Deleting test rules - cy.deleteRule(SAMPLE_RULE.name); - }); -}); diff --git a/cypress/utils/commands.js b/cypress/utils/commands.js index 21fdafba1..c3f807819 100644 --- a/cypress/utils/commands.js +++ b/cypress/utils/commands.js @@ -100,7 +100,7 @@ Cypress.Commands.add('deleteAllIndices', () => { cy.log('Deleting all indices'); cy.request( 'DELETE', - `${Cypress.env('openSearchUrl')}/index*,sample*,opensearch_dashboards*` + `${Cypress.env('openSearchUrl')}/index*,sample*,opensearch_dashboards*,test*,cypress*` ); }); diff --git a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js index 995ba6b1a..0a9c10fec 100644 --- a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js +++ b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js @@ -3,24 +3,107 @@ * SPDX-License-Identifier: Apache-2.0 */ -const { NODE_API } = require('./constants'); - -// *********************************************** -// This example commands.js shows you how to -// create various custom commands and overwrite -// existing commands. -// -// For more comprehensive examples of custom -// commands please read more here: -// https://on.cypress.io/custom-commands -// *********************************************** -// -// -// -- This is a parent command -- +const { NODE_API, OPENSEARCH_DASHBOARDS, OPENSEARCH_DASHBOARDS_URL } = require('./constants'); +Cypress.Commands.add('cleanUpTests', () => { + cy.deleteAllCustomRules(); + cy.deleteAllDetectors(); + cy.deleteAllIndices(); +}); + +Cypress.Commands.add('getTableFirstRow', (selector) => { + if (!selector) return cy.get('tbody > tr').first(); + return cy.get('tbody > tr:first').find(selector); +}); + +Cypress.Commands.add('triggerSearchField', (placeholder, text) => { + cy.get(`[placeholder="${placeholder}"]`).type(`{selectall}${text}`).realPress('Enter'); +}); + +Cypress.Commands.add('waitForPageLoad', (url, { timeout = 10000, contains = null }) => { + const fullUrl = `${OPENSEARCH_DASHBOARDS_URL}/${url}`; + Cypress.log({ + message: `Wait for url: ${fullUrl} to be loaded.`, + }); + cy.url({ timeout: timeout }) + .should('include', fullUrl) + .then(() => { + contains && cy.contains(contains); + }); +}); + +Cypress.Commands.add('deleteAllDetectors', () => { + cy.request({ + method: 'DELETE', + url: `${Cypress.env('opensearch')}/.opensearch-sap-detectors-config`, + failOnStatusCode: false, + }); +}); + +Cypress.Commands.add('createDetector', (detectorJSON) => { + cy.request('POST', `${Cypress.env('opensearch')}${NODE_API.DETECTORS_BASE}`, detectorJSON); +}); + +Cypress.Commands.add('updateDetector', (detectorId, detectorJSON) => { + cy.request( + 'PUT', + `${Cypress.env('opensearch')}/${NODE_API.DETECTORS_BASE}/${detectorId}`, + detectorJSON + ); +}); + +Cypress.Commands.add('deleteDetector', (detectorName) => { + const body = { + from: 0, + size: 5000, + query: { + nested: { + path: 'detector', + query: { + bool: { + must: [{ match: { 'detector.name': detectorName } }], + }, + }, + }, + }, + }; + cy.request({ + method: 'POST', + url: `${Cypress.env('opensearch')}${NODE_API.DETECTORS_BASE}/_search`, + failOnStatusCode: false, + body, + }).then((response) => { + if (response.status === 200) { + for (let hit of response.body.hits.hits) { + cy.request('DELETE', `${Cypress.env('opensearch')}${NODE_API.DETECTORS_BASE}/${hit._id}`); + } + } + }); +}); + +Cypress.Commands.add( + 'createAliasMappings', + (indexName, ruleTopic, aliasMappingsBody, partial = true) => { + const body = { + index_name: indexName, + rule_topic: ruleTopic, + partial: partial, + alias_mappings: aliasMappingsBody, + }; + cy.request({ + method: 'POST', + url: `${Cypress.env('opensearch')}${NODE_API.MAPPINGS_BASE}`, + body: body, + }); + } +); Cypress.Commands.add('createRule', (ruleJSON) => { - cy.request('POST', `${Cypress.env('opensearch')}${NODE_API.RULES_BASE}`, ruleJSON); + return cy.request({ + method: 'POST', + url: `${OPENSEARCH_DASHBOARDS}${NODE_API.RULES_BASE}?category=${ruleJSON.category}`, + body: JSON.stringify(ruleJSON), + }); }); Cypress.Commands.add('updateRule', (ruleId, ruleJSON) => { @@ -52,11 +135,19 @@ Cypress.Commands.add('deleteRule', (ruleName) => { for (let hit of response.body.hits.hits) { if (hit._source.title === ruleName) cy.request( - 'DELETE', - `${Cypress.env('opensearch')}${NODE_API.RULES_BASE}/${hit._id}?forced=true` + 'DELETE', + `${Cypress.env('opensearch')}${NODE_API.RULES_BASE}/${hit._id}?forced=true` ); } } }); }); +Cypress.Commands.add('deleteAllCustomRules', () => { + cy.request({ + method: 'DELETE', + url: `${Cypress.env('opensearch')}/.opensearch-sap-custom-rules-config`, + failOnStatusCode: false, + body: { query: { match_all: {} } }, + }); +}); diff --git a/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js b/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js index 1e4011982..e8cf9a4a9 100644 --- a/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js +++ b/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js @@ -13,6 +13,8 @@ export const INDICES = { export const PLUGIN_NAME = 'opensearch_security_analytics_dashboards'; export const BASE_API_PATH = '/_plugins/_security_analytics'; +export const { opensearch_dashboards: OPENSEARCH_DASHBOARDS } = Cypress.env(); +export const OPENSEARCH_DASHBOARDS_URL = `${OPENSEARCH_DASHBOARDS}/app/${PLUGIN_NAME}#`; export const NODE_API = { DETECTORS_BASE: `${BASE_API_PATH}/detectors`, From d72d720eca55a87a02c0a5307c7477f0f4263caa Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Fri, 20 Jan 2023 11:38:33 -0800 Subject: [PATCH 02/36] Fixed imports and added test fixtures. Signed-off-by: AWSHurneyt --- .../detector/create_dns_detector_data.json | 57 +++++++++++++++++++ .../create_dns_detector_mappings_data.json | 16 ++++++ .../detector/create_usb_detector_data.json | 57 +++++++++++++++++++ .../create_usb_detector_mappings_data.json | 28 +++++++++ .../index/add_dns_index_data.json | 5 ++ .../index/add_windows_index_data.json | 39 +++++++++++++ .../index/create_dns_settings.json | 21 +++++++ .../index/create_windows_settings.json | 30 ++++++++++ .../rule/create_dns_rule.json | 26 +++++++++ .../rule/create_windows_usb_rule.json | 26 +++++++++ .../sample_alias_mappings.json | 16 ++++++ .../sample_detector.json | 57 +++++++++++++++++++ .../sample_document.json | 39 +++++++++++++ .../sample_field_mappings.json | 28 +++++++++ .../sample_index_settings.json | 30 ++++++++++ .../1_detectors.spec.js | 4 +- .../2_rules.spec.js | 2 +- .../3_alerts.spec.js | 13 +++-- .../4_findings.spec.js | 13 +++-- .../5_integrations.spec.js | 24 ++++---- .../constants.js | 1 + 21 files changed, 508 insertions(+), 24 deletions(-) create mode 100644 cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/detector/create_dns_detector_data.json create mode 100644 cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/detector/create_dns_detector_mappings_data.json create mode 100644 cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/detector/create_usb_detector_data.json create mode 100644 cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/detector/create_usb_detector_mappings_data.json create mode 100644 cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/index/add_dns_index_data.json create mode 100644 cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/index/add_windows_index_data.json create mode 100644 cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/index/create_dns_settings.json create mode 100644 cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/index/create_windows_settings.json create mode 100644 cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/rule/create_dns_rule.json create mode 100644 cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/rule/create_windows_usb_rule.json create mode 100644 cypress/fixtures/plugins/security-analytics-dashboards-plugin/sample_alias_mappings.json create mode 100644 cypress/fixtures/plugins/security-analytics-dashboards-plugin/sample_detector.json create mode 100644 cypress/fixtures/plugins/security-analytics-dashboards-plugin/sample_document.json create mode 100644 cypress/fixtures/plugins/security-analytics-dashboards-plugin/sample_field_mappings.json create mode 100644 cypress/fixtures/plugins/security-analytics-dashboards-plugin/sample_index_settings.json diff --git a/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/detector/create_dns_detector_data.json b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/detector/create_dns_detector_data.json new file mode 100644 index 000000000..276c56db2 --- /dev/null +++ b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/detector/create_dns_detector_data.json @@ -0,0 +1,57 @@ +{ + "type": "detector", + "detector_type": "dns", + "name": "Cypress DNS Detector", + "enabled": true, + "createdBy": "", + "schedule": { + "period": { + "interval": 1, + "unit": "MINUTES" + } + }, + "inputs": [ + { + "detector_input": { + "description": "Detects DNS names.", + "indices": ["cypress-index-dns"], + "pre_packaged_rules": [], + "custom_rules": [ + { + "id": "25b9c01c-350d-4b95-bed1-836d04a4f325" + } + ] + } + } + ], + "triggers": [ + { + "name": "DNS name alert", + "sev_levels": ["low"], + "tags": ["dns.low"], + "actions": [ + { + "id": "", + "name": "Triggered alert condition: - Severity: 1 (Highest) - Threat detector: Cypress DNS Detector", + "destination_id": "", + "subject_template": { + "source": "Triggered alert condition: - Severity: 1 (Highest) - Threat detector: Cypress DNS Detector", + "lang": "mustache" + }, + "message_template": { + "source": "Triggered alert condition: \nSeverity: 1 (Highest)\nThreat detector: Cypress DNS Detector\nDescription: Detects DNS names.\nDetector data sources:\n\tdns", + "lang": "mustache" + }, + "throttle_enabled": false, + "throttle": { + "value": 10, + "unit": "MINUTES" + } + } + ], + "types": ["dns"], + "severity": "1", + "ids": ["R1ng94QBbw8UQ2Cvqe6h"] + } + ] +} diff --git a/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/detector/create_dns_detector_mappings_data.json b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/detector/create_dns_detector_mappings_data.json new file mode 100644 index 000000000..e4056d577 --- /dev/null +++ b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/detector/create_dns_detector_mappings_data.json @@ -0,0 +1,16 @@ +{ + "properties": { + "dns-answers-type": { + "type": "alias", + "path": "DnsAnswerType" + }, + "dns-question-name": { + "type": "alias", + "path": "DnsQuestionName" + }, + "dns-question-registered_domain": { + "type": "alias", + "path": "DnsQuestionRegisteredDomain" + } + } +} diff --git a/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/detector/create_usb_detector_data.json b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/detector/create_usb_detector_data.json new file mode 100644 index 000000000..07392d280 --- /dev/null +++ b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/detector/create_usb_detector_data.json @@ -0,0 +1,57 @@ +{ + "type": "detector", + "detector_type": "windows", + "name": "Cypress USB Detector", + "enabled": true, + "createdBy": "", + "schedule": { + "period": { + "interval": 1, + "unit": "MINUTES" + } + }, + "inputs": [ + { + "detector_input": { + "description": "Detect USB plugged in.", + "indices": ["cypress-index-windows"], + "pre_packaged_rules": [], + "custom_rules": [ + { + "id": "25b9c01c-350d-4b95-bed1-836d04a4f324" + } + ] + } + } + ], + "triggers": [ + { + "name": "USB plugged in alert", + "sev_levels": ["low"], + "tags": ["windows.usb"], + "actions": [ + { + "id": "", + "name": "Triggered alert condition: - Severity: 1 (Highest) - Threat detector: USB Detector", + "destination_id": "", + "subject_template": { + "source": "Triggered alert condition: - Severity: 1 (Highest) - Threat detector: USB Detector", + "lang": "mustache" + }, + "message_template": { + "source": "Triggered alert condition: \nSeverity: 1 (Highest)\nThreat detector: USB Detector\nDescription: Detect USB plugged in.\nDetector data sources:\n\twindows", + "lang": "mustache" + }, + "throttle_enabled": false, + "throttle": { + "value": 10, + "unit": "MINUTES" + } + } + ], + "types": ["windows"], + "severity": "1", + "ids": ["25b9c01c-350d-4b95-bed1-836d04a4f123"] + } + ] +} diff --git a/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/detector/create_usb_detector_mappings_data.json b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/detector/create_usb_detector_mappings_data.json new file mode 100644 index 000000000..da81361fe --- /dev/null +++ b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/detector/create_usb_detector_mappings_data.json @@ -0,0 +1,28 @@ +{ + "properties": { + "event_uid": { + "type": "alias", + "path": "EventID" + }, + "windows-event_data-CommandLine": { + "type": "alias", + "path": "CommandLine" + }, + "windows-hostname": { + "type": "alias", + "path": "HostName" + }, + "windows-message": { + "type": "alias", + "path": "Message" + }, + "windows-provider-name": { + "type": "alias", + "path": "Provider_Name" + }, + "windows-servicename": { + "type": "alias", + "path": "ServiceName" + } + } +} diff --git a/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/index/add_dns_index_data.json b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/index/add_dns_index_data.json new file mode 100644 index 000000000..35077a0f5 --- /dev/null +++ b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/index/add_dns_index_data.json @@ -0,0 +1,5 @@ +{ + "DnsAnswerType": "QWE", + "DnsQuestionRegisteredDomain": "EC2AMAZ-EPWO7HKA", + "DnsQuestionName": "QWE" +} diff --git a/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/index/add_windows_index_data.json b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/index/add_windows_index_data.json new file mode 100644 index 000000000..c449c7584 --- /dev/null +++ b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/index/add_windows_index_data.json @@ -0,0 +1,39 @@ +{ + "EventTime": "2020-02-04T14:59:39.343541+00:00", + "HostName": "EC2AMAZ-EPO7HKA", + "Keywords": "9223372036854775808", + "SeverityValue": 2, + "Severity": "ERROR", + "EventID": 2003, + "SourceName": "Microsoft-Windows-Sysmon", + "ProviderGuid": "{5770385F-C22A-43E0-BF4C-06F5698FFBD9}", + "Version": 5, + "TaskValue": 22, + "OpcodeValue": 0, + "RecordNumber": 9532, + "ExecutionProcessID": 1996, + "ExecutionThreadID": 2616, + "Channel": "Microsoft-Windows-Sysmon/Operational", + "Domain": "NT AUTHORITY", + "AccountName": "SYSTEM", + "UserID": "S-1-5-18", + "AccountType": "User", + "Message": "Dns query:\r\nRuleName: \r\nUtcTime: 2020-02-04 14:59:38.349\r\nProcessGuid: {b3c285a4-3cda-5dc0-0000-001077270b00}\r\nProcessId: 1904\r\nQueryName: EC2AMAZ-EPO7HKA\r\nQueryStatus: 0\r\nQueryResults: 172.31.46.38;\r\nImage: C:\\Program Files\\nxlog\\nxlog.exe", + "Category": "Dns query (rule: DnsQuery)", + "Opcode": "Info", + "UtcTime": "2020-02-04 14:59:38.349", + "ProcessGuid": "{b3c285a4-3cda-5dc0-0000-001077270b00}", + "ProcessId": "1904", + "QueryName": "EC2AMAZ-EPO7HKA", + "QueryStatus": "0", + "QueryResults": "172.31.46.38;", + "Image": "C:\\Program Files\\nxlog\\regsvr32.exe", + "EventReceivedTime": "2020-02-04T14:59:40.780905+00:00", + "SourceModuleName": "in", + "SourceModuleType": "im_msvistalog", + "CommandLine": "eachtest", + "Initiated": "true", + "Provider_Name": "Service_ws_Control_ws_Manager", + "TargetObject": "\\SOFTWARE\\Microsoft\\Office\\Outlook\\Security", + "EventType": "SetValue" +} diff --git a/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/index/create_dns_settings.json b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/index/create_dns_settings.json new file mode 100644 index 000000000..126659dc6 --- /dev/null +++ b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/index/create_dns_settings.json @@ -0,0 +1,21 @@ +{ + "mappings": { + "properties": { + "DnsAnswerType": { + "type": "text" + }, + "DnsQuestionRegisteredDomain": { + "type": "text" + }, + "DnsQuestionName": { + "type": "text" + } + } + }, + "settings": { + "index": { + "number_of_shards": "1", + "number_of_replicas": "1" + } + } +} diff --git a/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/index/create_windows_settings.json b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/index/create_windows_settings.json new file mode 100644 index 000000000..f794e671e --- /dev/null +++ b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/index/create_windows_settings.json @@ -0,0 +1,30 @@ +{ + "mappings": { + "properties": { + "CommandLine": { + "type": "text" + }, + "EventID": { + "type": "integer" + }, + "HostName": { + "type": "text" + }, + "Message": { + "type": "text" + }, + "Provider_Name": { + "type": "text" + }, + "ServiceName": { + "type": "text" + } + } + }, + "settings": { + "index": { + "number_of_shards": "1", + "number_of_replicas": "1" + } + } +} diff --git a/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/rule/create_dns_rule.json b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/rule/create_dns_rule.json new file mode 100644 index 000000000..ae89e69da --- /dev/null +++ b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/rule/create_dns_rule.json @@ -0,0 +1,26 @@ +{ + "id": "25b9c01c-350d-4b95-bed1-836d04a4f325", + "category": "dns", + "title": "Cypress DNS Rule", + "description": "Detects DNS name as QWE", + "status": "experimental", + "author": "Cypress Tests", + "references": [ + { + "value": "" + } + ], + "tags": [ + { + "value": "dns.low" + } + ], + "log_source": "", + "detection": "selection:\n DnsQuestionName:\n - QWE\n - ASD\n - YXC\ncondition: selection", + "level": "low", + "false_positives": [ + { + "value": "" + } + ] +} diff --git a/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/rule/create_windows_usb_rule.json b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/rule/create_windows_usb_rule.json new file mode 100644 index 000000000..20f59799a --- /dev/null +++ b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/rule/create_windows_usb_rule.json @@ -0,0 +1,26 @@ +{ + "id": "25b9c01c-350d-4b95-bed1-836d04a4f123", + "category": "windows", + "title": "Cypress USB Rule", + "description": "USB plugged-in rule", + "status": "experimental", + "author": "Cypress Tests", + "references": [ + { + "value": "" + } + ], + "tags": [ + { + "value": "windows.usb" + } + ], + "log_source": "", + "detection": "selection:\n EventID:\n - 2003\n - 2100\n - 2102\ncondition: selection", + "level": "low", + "false_positives": [ + { + "value": "" + } + ] +} diff --git a/cypress/fixtures/plugins/security-analytics-dashboards-plugin/sample_alias_mappings.json b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/sample_alias_mappings.json new file mode 100644 index 000000000..cf08cc696 --- /dev/null +++ b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/sample_alias_mappings.json @@ -0,0 +1,16 @@ +{ + "properties": { + "source_ip": { + "type": "alias", + "path": "src_ip" + }, + "windows-event_data-CommandLine": { + "path": "CommandLine", + "type": "alias" + }, + "event_uid": { + "path": "EventID", + "type": "alias" + } + } +} diff --git a/cypress/fixtures/plugins/security-analytics-dashboards-plugin/sample_detector.json b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/sample_detector.json new file mode 100644 index 000000000..67eca1110 --- /dev/null +++ b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/sample_detector.json @@ -0,0 +1,57 @@ +{ + "type": "detector", + "detector_type": "windows", + "name": "sample_detector", + "enabled": true, + "createdBy": "", + "schedule": { + "period": { + "interval": 1, + "unit": "MINUTES" + } + }, + "inputs": [ + { + "detector_input": { + "description": "Description for sample_detector.", + "indices": ["cypress-test-windows"], + "pre_packaged_rules": [ + { + "id": "1a4bd6e3-4c6e-405d-a9a3-53a116e341d4" + } + ], + "custom_rules": [] + } + } + ], + "triggers": [ + { + "name": "sample_alert_condition", + "sev_levels": [], + "tags": [], + "actions": [ + { + "id": "", + "name": "Triggered alert condition: - Severity: 1 (Highest) - Threat detector: sample_detector", + "destination_id": "", + "subject_template": { + "source": "Triggered alert condition: - Severity: 1 (Highest) - Threat detector: sample_detector", + "lang": "mustache" + }, + "message_template": { + "source": "Triggered alert condition: \nSeverity: 1 (Highest)\nThreat detector: sample_detector\nDescription: Description for sample_detector.\nDetector data sources:\n\twindows", + "lang": "mustache" + }, + "throttle_enabled": false, + "throttle": { + "value": 10, + "unit": "MINUTES" + } + } + ], + "types": ["windows"], + "severity": "4", + "ids": ["1a4bd6e3-4c6e-405d-a9a3-53a116e341d4"] + } + ] +} diff --git a/cypress/fixtures/plugins/security-analytics-dashboards-plugin/sample_document.json b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/sample_document.json new file mode 100644 index 000000000..d23b31895 --- /dev/null +++ b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/sample_document.json @@ -0,0 +1,39 @@ +{ + "EventTime": "2020-02-04T14:59:39.343541+00:00", + "HostName": "EC2AMAZ-EPO7HKA", + "Keywords": "9223372036854775808", + "SeverityValue": 2, + "Severity": "INFO", + "EventID": 2003, + "SourceName": "Microsoft-Windows-Sysmon", + "ProviderGuid": "{5770385F-C22A-43E0-BF4C-06F5698FFBD9}", + "Version": 5, + "TaskValue": 22, + "OpcodeValue": 0, + "RecordNumber": 9532, + "ExecutionProcessID": 1996, + "ExecutionThreadID": 2616, + "Channel": "Microsoft-Windows-Sysmon/Operational", + "Domain": "NT AUTHORITY", + "AccountName": "SYSTEM", + "UserID": "S-1-5-18", + "AccountType": "User", + "Message": "Dns query:\r\nRuleName: \r\nUtcTime: 2020-02-04 14:59:38.349\r\nProcessGuid: {b3c285a4-3cda-5dc0-0000-001077270b00}\r\nProcessId: 1904\r\nQueryName: EC2AMAZ-EPO7HKA\r\nQueryStatus: 0\r\nQueryResults: 172.31.46.38;\r\nImage: C:\\Program Files\\nxlog\\nxlog.exe", + "Category": "Dns query (rule: DnsQuery)", + "Opcode": "Info", + "UtcTime": "2020-02-04 14:59:38.349", + "ProcessGuid": "{b3c285a4-3cda-5dc0-0000-001077270b00}", + "ProcessId": "1904", + "QueryName": "EC2AMAZ-EPO7HKA", + "QueryStatus": "0", + "QueryResults": "172.31.46.38;", + "Image": "C:\\Program Files\\nxlog\\regsvr32.exe", + "EventReceivedTime": "2020-02-04T14:59:40.780905+00:00", + "SourceModuleName": "in", + "SourceModuleType": "im_msvistalog", + "CommandLine": "eachtest", + "Initiated": "true", + "Provider_Name": "Microsoft-Windows-Kernel-General", + "TargetObject": "\\SOFTWARE\\Microsoft\\Office\\Outlook\\Security", + "EventType": "SetValue" +} diff --git a/cypress/fixtures/plugins/security-analytics-dashboards-plugin/sample_field_mappings.json b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/sample_field_mappings.json new file mode 100644 index 000000000..6e8d728fe --- /dev/null +++ b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/sample_field_mappings.json @@ -0,0 +1,28 @@ +{ + "properties": { + "windows-hostname": { + "type": "alias", + "path": "HostName" + }, + "windows-message": { + "type": "alias", + "path": "Message" + }, + "windows-provider-name": { + "type": "alias", + "path": "Provider_Name" + }, + "windows-servicename": { + "type": "alias", + "path": "ServiceName" + }, + "windows-event_data-CommandLine": { + "path": "CommandLine", + "type": "alias" + }, + "event_uid": { + "path": "EventID", + "type": "alias" + } + } +} diff --git a/cypress/fixtures/plugins/security-analytics-dashboards-plugin/sample_index_settings.json b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/sample_index_settings.json new file mode 100644 index 000000000..f794e671e --- /dev/null +++ b/cypress/fixtures/plugins/security-analytics-dashboards-plugin/sample_index_settings.json @@ -0,0 +1,30 @@ +{ + "mappings": { + "properties": { + "CommandLine": { + "type": "text" + }, + "EventID": { + "type": "integer" + }, + "HostName": { + "type": "text" + }, + "Message": { + "type": "text" + }, + "Provider_Name": { + "type": "text" + }, + "ServiceName": { + "type": "text" + } + } + }, + "settings": { + "index": { + "number_of_shards": "1", + "number_of_replicas": "1" + } + } +} diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js index b40ed8db4..97faa44d2 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js @@ -3,8 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { OPENSEARCH_DASHBOARDS_URL } from '../support/constants'; -import sample_index_settings from '../fixtures/sample_index_settings.json'; +import {OPENSEARCH_DASHBOARDS_URL} from "../../../utils/plugins/security-analytics-dashboards-plugin/constants"; +import sample_index_settings from '../../../fixtures/plugins/security-analytics-dashboards-plugin/sample_index_settings.json'; const testMappings = { properties: { diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js index eff0cff07..9a89f0dac 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js @@ -3,7 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { OPENSEARCH_DASHBOARDS_URL } from '../support/constants'; +const {OPENSEARCH_DASHBOARDS_URL} = require("../../../utils/plugins/security-analytics-dashboards-plugin/constants"); const uniqueId = Cypress._.random(0, 1e6); const SAMPLE_RULE = { diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js index 332328c82..d8cd66663 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js @@ -4,11 +4,14 @@ */ import moment from 'moment'; -import { DETECTOR_TRIGGER_TIMEOUT, OPENSEARCH_DASHBOARDS_URL } from '../support/constants'; -import sample_index_settings from '../fixtures/sample_index_settings.json'; -import sample_alias_mappings from '../fixtures/sample_alias_mappings.json'; -import sample_detector from '../fixtures/sample_detector.json'; -import sample_document from '../fixtures/sample_document.json'; +import { + DETECTOR_TRIGGER_TIMEOUT, + OPENSEARCH_DASHBOARDS_URL +} from "../../../utils/plugins/security-analytics-dashboards-plugin/constants"; +import sample_index_settings from '../../../fixtures/plugins/security-analytics-dashboards-plugin/sample_index_settings.json'; +import sample_alias_mappings from '../../../fixtures/plugins/security-analytics-dashboards-plugin/sample_alias_mappings.json'; +import sample_detector from '../../../fixtures/plugins/security-analytics-dashboards-plugin/sample_detector.json'; +import sample_document from '../../../fixtures/plugins/security-analytics-dashboards-plugin/sample_document.json'; const testIndex = 'sample_alerts_spec_cypress_test_index'; const testDetectorName = 'alerts_spec_cypress_test_detector'; diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js index e68a9bbe8..f49cf4093 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js @@ -3,11 +3,14 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { DETECTOR_TRIGGER_TIMEOUT, OPENSEARCH_DASHBOARDS_URL } from '../support/constants'; -import sample_document from '../fixtures/sample_document.json'; -import sample_index_settings from '../fixtures/sample_index_settings.json'; -import sample_field_mappings from '../fixtures/sample_field_mappings.json'; -import sample_detector from '../fixtures/sample_detector.json'; +import { + DETECTOR_TRIGGER_TIMEOUT, + OPENSEARCH_DASHBOARDS_URL +} from "../../../utils/plugins/security-analytics-dashboards-plugin/constants"; +import sample_document from '../../../fixtures/plugins/security-analytics-dashboards-plugin/sample_document.json'; +import sample_index_settings from '../../../fixtures/plugins/security-analytics-dashboards-plugin/sample_index_settings.json'; +import sample_field_mappings from '../../../fixtures/plugins/security-analytics-dashboards-plugin/sample_field_mappings.json'; +import sample_detector from '../../../fixtures/plugins/security-analytics-dashboards-plugin/sample_detector.json'; describe('Findings', () => { const ruleTags = ['low', 'windows']; diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js index a38ea3ecb..09c648b82 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js @@ -3,17 +3,19 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { DETECTOR_TRIGGER_TIMEOUT, OPENSEARCH_DASHBOARDS_URL } from '../support/constants'; -import sample_index_settings from '../fixtures/sample_index_settings.json'; -import sample_dns_settings from '../fixtures/integration_tests/index/create_dns_settings.json'; -import windows_usb_rule_data from '../fixtures/integration_tests/rule/create_windows_usb_rule.json'; -import dns_rule_data from '../fixtures/integration_tests/rule/create_dns_rule.json'; -import usb_detector_data from '../fixtures/integration_tests/detector/create_usb_detector_data.json'; -import usb_detector_data_mappings from '../fixtures/integration_tests/detector/create_usb_detector_mappings_data.json'; -import dns_detector_data_mappings from '../fixtures/integration_tests/detector/create_dns_detector_mappings_data.json'; -import dns_detector_data from '../fixtures/integration_tests/detector/create_dns_detector_data.json'; -import add_windows_index_data from '../fixtures/integration_tests/index/add_windows_index_data.json'; -import add_dns_index_data from '../fixtures/integration_tests/index/add_dns_index_data.json'; +import { + DETECTOR_TRIGGER_TIMEOUT, + OPENSEARCH_DASHBOARDS_URL +} from "../../../utils/plugins/security-analytics-dashboards-plugin/constants";import sample_index_settings from '../../../fixtures/plugins/security-analytics-dashboards-plugin/sample_index_settings.json'; +import sample_dns_settings from '../../../fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/index/create_dns_settings.json'; +import windows_usb_rule_data from '../../../fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/rule/create_windows_usb_rule.json'; +import dns_rule_data from '../../../fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/rule/create_dns_rule.json'; +import usb_detector_data from '../../../fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/detector/create_usb_detector_data.json'; +import usb_detector_data_mappings from '../../../fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/detector/create_usb_detector_mappings_data.json'; +import dns_detector_data_mappings from '../../../fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/detector/create_dns_detector_mappings_data.json'; +import dns_detector_data from '../../../fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/detector/create_dns_detector_data.json'; +import add_windows_index_data from '../../../fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/index/add_windows_index_data.json'; +import add_dns_index_data from '../../../fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/index/add_dns_index_data.json'; describe('Integration tests', () => { const indexName = 'cypress-index-windows'; diff --git a/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js b/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js index e8cf9a4a9..3700f1e29 100644 --- a/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js +++ b/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js @@ -4,6 +4,7 @@ */ export const TWENTY_SECONDS_TIMEOUT = { timeout: 20000 }; +export const DETECTOR_TRIGGER_TIMEOUT = 65000; export const INDICES = { DETECTORS_INDEX: '.opensearch-detectors-config', From 77db94d5501bf403d35d8d07e3bd39899010acf2 Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Fri, 20 Jan 2023 12:05:44 -0800 Subject: [PATCH 03/36] Refactored test to use Date instead of moment. Signed-off-by: AWSHurneyt --- .../3_alerts.spec.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js index d8cd66663..184f84be2 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js @@ -3,7 +3,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -import moment from 'moment'; import { DETECTOR_TRIGGER_TIMEOUT, OPENSEARCH_DASHBOARDS_URL @@ -40,7 +39,14 @@ const testDetector = { // The exact minutes/seconds for the start and last updated time will be difficult to predict, // but all of the alert time fields should all contain the date in this format. -const date = moment(moment.now()).format('MM/DD/YY'); + +// Moment is not available in this repository, so refactored this variable to use Date. +// const date = moment(moment.now()).format('MM/DD/YY'); +const now = new Date(Date.now()); +const month = (now.getMonth() + 1) < 10 ? `0${now.getMonth() + 1}` : `${now.getMonth() + 1}`; +const day = now.getDate() < 10 ? `0${now.getDate()}` : `${now.getDate()}`; +const year = `${now.getFullYear()}`.substr(1); +const date = `${month}/${day}/${year}` const docCount = 4; describe('Alerts', () => { From a74efe996b0740ed8592c5445d24762c237370c1 Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Fri, 20 Jan 2023 12:56:58 -0800 Subject: [PATCH 04/36] Fixed eslint errors. Signed-off-by: AWSHurneyt --- .../1_detectors.spec.js | 52 ++++-- .../2_rules.spec.js | 88 +++++++--- .../3_alerts.spec.js | 160 ++++++++++++------ .../4_findings.spec.js | 34 ++-- .../5_integrations.spec.js | 33 +++- cypress/utils/commands.js | 4 +- .../commands.js | 38 ++++- 7 files changed, 293 insertions(+), 116 deletions(-) diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js index 97faa44d2..c3c010c8e 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js @@ -3,7 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -import {OPENSEARCH_DASHBOARDS_URL} from "../../../utils/plugins/security-analytics-dashboards-plugin/constants"; +import { + OPENSEARCH_DASHBOARDS_URL, +} from "../../../utils/plugins/security-analytics-dashboards-plugin/constants"; import sample_index_settings from '../../../fixtures/plugins/security-analytics-dashboards-plugin/sample_index_settings.json'; const testMappings = { @@ -64,10 +66,14 @@ describe('Detectors', () => { }); // Enter a name for the detector in the appropriate input - cy.get(`input[placeholder="Enter a name for the detector."]`).type('test detector{enter}'); + cy.get(`input[placeholder="Enter a name for the detector."]`).type( + 'test detector{enter}' + ); // Select our pre-seeded data source (check indexName) - cy.get(`[data-test-subj="define-detector-select-data-source"]`).type(`${indexName}{enter}`); + cy.get(`[data-test-subj="define-detector-select-data-source"]`).type( + `${indexName}{enter}` + ); // Select threat detector type (Windows logs) cy.get(`input[id="windows"]`).click({ force: true }); @@ -108,7 +114,9 @@ describe('Detectors', () => { const mappedTo = testMappings.properties[field_name].path; cy.contains('tr', field_name).within(() => { - cy.get(`[data-test-subj="detector-field-mappings-select"]`).click().type(mappedTo); + cy.get(`[data-test-subj="detector-field-mappings-select"]`) + .click() + .type(mappedTo); }); } @@ -119,13 +127,19 @@ describe('Detectors', () => { cy.contains('Set up alerts'); // Type name of new trigger - cy.get(`input[placeholder="Enter a name for the alert condition."]`).type('test_trigger'); + cy.get(`input[placeholder="Enter a name for the alert condition."]`).type( + 'test_trigger' + ); // Type in (or select) tags for the alert condition - cy.get(`[data-test-subj="alert-tags-combo-box"]`).type('attack.defense_evasion{enter}'); + cy.get(`[data-test-subj="alert-tags-combo-box"]`).type( + 'attack.defense_evasion{enter}' + ); // Select applicable severity levels - cy.get(`[data-test-subj="security-levels-combo-box"]`).click({ force: true }); + cy.get(`[data-test-subj="security-levels-combo-box"]`).click({ + force: true + }); cy.contains('1 (Highest)').click({ force: true }); // Continue to next page @@ -183,7 +197,9 @@ describe('Detectors', () => { }); // Click "Edit" button in detector details - cy.get(`[data-test-subj="edit-detector-basic-details"]`).click({ force: true }); + cy.get(`[data-test-subj="edit-detector-basic-details"]`).click({ + force: true + }); // Confirm arrival at "Edit detector details" page cy.waitForPageLoad('edit-detector-details', { @@ -194,7 +210,9 @@ describe('Detectors', () => { cy.get(`[data-test-subj="define-detector-detector-name"]`).type('_edited'); // Change detector description - cy.get(`[data-test-subj="define-detector-detector-description"]`).type('Edited description'); + cy.get(`[data-test-subj="define-detector-detector-description"]`).type( + 'Edited description' + ); // Change input source cy.get(`[data-test-subj="define-detector-select-data-source"]`).type( @@ -202,11 +220,15 @@ describe('Detectors', () => { ); // Change detector scheduling - cy.get(`[data-test-subj="detector-schedule-number-select"]`).type('{selectall}10'); + cy.get(`[data-test-subj="detector-schedule-number-select"]`).type( + '{selectall}10' + ); cy.get(`[data-test-subj="detector-schedule-unit-select"]`).select('Hours'); // Save changes to detector details - cy.get(`[data-test-subj="save-basic-details-edits"]`).click({ force: true }); + cy.get(`[data-test-subj="save-basic-details-edits"]`).click({ + force: true + }); // Confirm taken to detector details page cy.waitForPageLoad('detector-details', { @@ -255,7 +277,9 @@ describe('Detectors', () => { }); // Save changes - cy.get(`[data-test-subj="save-detector-rules-edits"]`).click({ force: true }); + cy.get(`[data-test-subj="save-detector-rules-edits"]`).click({ + force: true + }); // Confirm 1 rule has been removed from detector cy.contains('Active rules (0)'); @@ -278,7 +302,9 @@ describe('Detectors', () => { }); // Save changes - cy.get(`[data-test-subj="save-detector-rules-edits"]`).click({ force: true }); + cy.get(`[data-test-subj="save-detector-rules-edits"]`).click({ + force: true + }); cy.waitForPageLoad('detector-details', { contains: detectorName, }); diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js index 9a89f0dac..d8c11c662 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js @@ -3,7 +3,9 @@ * SPDX-License-Identifier: Apache-2.0 */ -const {OPENSEARCH_DASHBOARDS_URL} = require("../../../utils/plugins/security-analytics-dashboards-plugin/constants"); +const { + OPENSEARCH_DASHBOARDS_URL, +} = require("../../../utils/plugins/security-analytics-dashboards-plugin/constants"); const uniqueId = Cypress._.random(0, 1e6); const SAMPLE_RULE = { @@ -20,7 +22,11 @@ const SAMPLE_RULE = { 'condition: selection', ], severity: 'critical', - tags: ['attack.persistence', 'attack.privilege_escalation', 'attack.t1543.003'], + tags: [ + 'attack.persistence', + 'attack.privilege_escalation', + 'attack.t1543.003' + ], references: 'https://nohello.com', falsePositive: 'unknown', author: 'Cypress Test Runner', @@ -45,7 +51,9 @@ const YAML_RULE_LINES = [ `- '${SAMPLE_RULE.references}'`, `author: ${SAMPLE_RULE.author}`, `detection:`, - ...SAMPLE_RULE.detection.replaceAll(' ', '').replaceAll('{backspace}', '').split('\n'), + ...SAMPLE_RULE.detection.replaceAll(' ', '') + .replaceAll('{backspace}', '') + .split('\n'), ]; describe('Rules', () => { @@ -73,10 +81,14 @@ describe('Rules', () => { cy.get('[data-test-subj="rule_type_dropdown"]').type(SAMPLE_RULE.logType); // Enter the description - cy.get('[data-test-subj="rule_description_field"]').type(SAMPLE_RULE.description); + cy.get('[data-test-subj="rule_description_field"]').type( + SAMPLE_RULE.description + ); // Enter the severity - cy.get('[data-test-subj="rule_severity_dropdown"]').type(SAMPLE_RULE.severity); + cy.get('[data-test-subj="rule_severity_dropdown"]').type( + SAMPLE_RULE.severity + ); // Enter the tags SAMPLE_RULE.tags.forEach((tag) => @@ -84,10 +96,14 @@ describe('Rules', () => { ); // Enter the reference - cy.get('[data-test-subj="rule_references_field_0"]').type(SAMPLE_RULE.references); + cy.get('[data-test-subj="rule_references_field_0"]').type( + SAMPLE_RULE.references + ); // Enter the false positive cases - cy.get('[data-test-subj="rule_false_positives_field_0"]').type(SAMPLE_RULE.falsePositive); + cy.get('[data-test-subj="rule_false_positives_field_0"]').type( + SAMPLE_RULE.falsePositive + ); // Enter the author cy.get('[data-test-subj="rule_author_field"]').type(SAMPLE_RULE.author); @@ -96,14 +112,18 @@ describe('Rules', () => { cy.get('[data-test-subj="rule_status_dropdown"]').type(SAMPLE_RULE.status); // Enter the detection - cy.get('[data-test-subj="rule_detection_field"]').type(SAMPLE_RULE.detection); + cy.get('[data-test-subj="rule_detection_field"]').type( + SAMPLE_RULE.detection + ); // Switch to YAML editor cy.get('[data-test-subj="change-editor-type"] label:nth-child(2)').click({ force: true, }); - YAML_RULE_LINES.forEach((line) => cy.get('[data-test-subj="rule_yaml_editor"]').contains(line)); + YAML_RULE_LINES.forEach((line) => cy.get( + '[data-test-subj="rule_yaml_editor"]').contains(line) + ); cy.intercept({ url: '/rules', @@ -124,29 +144,41 @@ describe('Rules', () => { cy.triggerSearchField('Search rules', 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 }); + 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); + 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); + 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); + 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); + 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); + cy.get('[data-test-subj="rule_flyout_rule_severity"]').contains( + SAMPLE_RULE.severity + ); // Validate tags SAMPLE_RULE.tags.forEach((tag) => @@ -154,7 +186,9 @@ describe('Rules', () => { ); // Validate references - cy.get('[data-test-subj="rule_flyout_rule_references"]').contains(SAMPLE_RULE.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( @@ -162,15 +196,19 @@ describe('Rules', () => { ); // Validate status - cy.get('[data-test-subj="rule_flyout_rule_status"]').contains(SAMPLE_RULE.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="change-editor-type"] label:nth-child(2)' + ).click({ + force: true }); cy.get('[data-test-subj="rule_flyout_yaml_rule"]') @@ -186,9 +224,13 @@ describe('Rules', () => { // 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); + expect(line, `Sigma rule line ${lineIndex}`).to.contain( + expectedLine + ); } else { - expect(line, `Sigma rule line ${lineIndex}`).to.equal(expectedLine); + expect(line, `Sigma rule line ${lineIndex}`).to.equal( + expectedLine + ); } }); @@ -207,7 +249,9 @@ describe('Rules', () => { cy.triggerSearchField('Search rules', 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 }); + cy.get(`[data-test-subj="rule_link_${SAMPLE_RULE.name}"]`).click({ + force: true + }); cy.get('.euiButton') .contains('Action') diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js index 184f84be2..95b11fc95 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js @@ -5,8 +5,8 @@ import { DETECTOR_TRIGGER_TIMEOUT, - OPENSEARCH_DASHBOARDS_URL -} from "../../../utils/plugins/security-analytics-dashboards-plugin/constants"; + OPENSEARCH_DASHBOARDS_URL, +} from '../../../utils/plugins/security-analytics-dashboards-plugin/constants'; import sample_index_settings from '../../../fixtures/plugins/security-analytics-dashboards-plugin/sample_index_settings.json'; import sample_alias_mappings from '../../../fixtures/plugins/security-analytics-dashboards-plugin/sample_alias_mappings.json'; import sample_detector from '../../../fixtures/plugins/security-analytics-dashboards-plugin/sample_detector.json'; @@ -43,10 +43,11 @@ const testDetector = { // Moment is not available in this repository, so refactored this variable to use Date. // const date = moment(moment.now()).format('MM/DD/YY'); const now = new Date(Date.now()); -const month = (now.getMonth() + 1) < 10 ? `0${now.getMonth() + 1}` : `${now.getMonth() + 1}`; +const month = ( + now.getMonth() + 1) < 10 ? `0${now.getMonth() + 1}` : `${now.getMonth() + 1}`; const day = now.getDate() < 10 ? `0${now.getDate()}` : `${now.getDate()}`; const year = `${now.getFullYear()}`.substr(1); -const date = `${month}/${day}/${year}` +const date = `${month}/${day}/${year}`; const docCount = 4; describe('Alerts', () => { @@ -58,7 +59,12 @@ describe('Alerts', () => { // Create field mappings .then(() => - cy.createAliasMappings(testIndex, testDetector.detector_type, sample_alias_mappings, true) + cy.createAliasMappings( + testIndex, + testDetector.detector_type, + sample_alias_mappings, + true + ) ) // Create test detector @@ -104,15 +110,19 @@ describe('Alerts', () => { cy.get(`input[type="search"]`).type(`${testDetector.name}{enter}`); // Adjust the date range picker to display alerts from today - cy.get('[class="euiButtonEmpty__text euiQuickSelectPopover__buttonText"]').click({ - force: true, - }); - cy.get('[data-test-subj="superDatePickerCommonlyUsed_Today"]').click({ force: true }); + cy.get( + '[class="euiButtonEmpty__text euiQuickSelectPopover__buttonText"]' + ).click({ force: true }); + cy.get( + '[data-test-subj="superDatePickerCommonlyUsed_Today"]' + ).click({ force: true }); }); it('are generated', () => { // Refresh the table - cy.get('[data-test-subj="superDatePickerApplyTimeButton"]').click({ force: true }); + cy.get( + '[data-test-subj="superDatePickerApplyTimeButton"]' + ).click({ force: true }); // Confirm there are alerts created cy.get('tbody > tr') @@ -142,24 +152,34 @@ describe('Alerts', () => { // Get the details flyout, and validate its content cy.get('[data-test-subj="alert-details-flyout"]').within(() => { // Confirm alert condition name - cy.get('[data-test-subj="text-details-group-content-alert-trigger-name"]').contains( - testDetector.triggers[0].name - ); + cy.get( + '[data-test-subj="text-details-group-content-alert-trigger-name"]' + ).contains(testDetector.triggers[0].name); // Confirm alert status - cy.get('[data-test-subj="text-details-group-content-alert-status"]').contains('Active'); + cy.get( + '[data-test-subj="text-details-group-content-alert-status"]' + ).contains('Active'); // Confirm alert severity - cy.get('[data-test-subj="text-details-group-content-alert-severity"]').contains('4 (Low)'); + cy.get( + '[data-test-subj="text-details-group-content-alert-severity"]' + ).contains('4 (Low)'); // Confirm alert start time is present - cy.get('[data-test-subj="text-details-group-content-start-time"]').contains(date); + cy.get( + '[data-test-subj="text-details-group-content-start-time"]' + ).contains(date); // Confirm alert last updated time is present - cy.get('[data-test-subj="text-details-group-content-last-updated-time"]').contains(date); + cy.get( + '[data-test-subj="text-details-group-content-last-updated-time"]' + ).contains(date); // Confirm alert detector name - cy.get('[data-test-subj="text-details-group-content-detector"]').contains(testDetector.name); + cy.get( + '[data-test-subj="text-details-group-content-detector"]' + ).contains(testDetector.name); // Wait for the findings table to finish loading cy.contains('Findings (1)'); @@ -174,7 +194,9 @@ describe('Alerts', () => { }); // Close the flyout - cy.get('[data-test-subj="alert-details-flyout-close-button"]').click({ force: true }); + cy.get( + '[data-test-subj="alert-details-flyout-close-button"]' + ).click({ force: true }); }); // Confirm flyout has been closed @@ -212,44 +234,60 @@ describe('Alerts', () => { .then((text) => expect(text).to.have.length.greaterThan(1)); // Confirm finding timestamp - cy.get('[data-test-subj="finding-details-flyout-timestamp"]').contains(date); + cy.get( + '[data-test-subj="finding-details-flyout-timestamp"]' + ).contains(date); // Confirm finding detector name - cy.get('[data-test-subj="finding-details-flyout-detector-link"]').contains(testDetector.name); + cy.get( + '[data-test-subj="finding-details-flyout-detector-link"]' + ).contains(testDetector.name); // Confirm there's only 1 rule details accordion - cy.get('[data-test-subj="finding-details-flyout-rule-accordion-1"]').should('not.exist'); + cy.get( + '[data-test-subj="finding-details-flyout-rule-accordion-1"]' + ).should('not.exist'); // Check the rule details accordion for the expected values - cy.get('[data-test-subj="finding-details-flyout-rule-accordion-0"]').within(() => { + cy.get( + '[data-test-subj="finding-details-flyout-rule-accordion-0"]' + ).within(() => { // Confirm the accordion button contains the expected text - cy.get('[data-test-subj="finding-details-flyout-rule-accordion-button"]').contains( - 'USB Device Plugged' - ); - cy.get('[data-test-subj="finding-details-flyout-rule-accordion-button"]').contains( - 'Severity: Low' - ); + cy.get( + '[data-test-subj="finding-details-flyout-rule-accordion-button"]' + ).contains('USB Device Plugged'); + cy.get( + '[data-test-subj="finding-details-flyout-rule-accordion-button"]' + ).contains('Severity: Low'); // Confirm the rule name - cy.get('[data-test-subj="finding-details-flyout-USB Device Plugged-details"]').contains( - 'USB Device Plugged' - ); + cy.get( + '[data-test-subj="finding-details-flyout-USB Device Plugged-details"]' + ).contains('USB Device Plugged'); // Confirm the rule severity - cy.get('[data-test-subj="finding-details-flyout-rule-severity"]').contains('Low'); + cy.get( + '[data-test-subj="finding-details-flyout-rule-severity"]' + ).contains('Low'); // Confirm the rule category - cy.get('[data-test-subj="finding-details-flyout-rule-category"]').contains('Windows'); + cy.get( + '[data-test-subj="finding-details-flyout-rule-category"]' + ).contains('Windows'); // Confirm the rule description - cy.get('[data-test-subj="finding-details-flyout-rule-description"]').contains( - 'Detects plugged USB devices' - ); + cy.get( + '[data-test-subj="finding-details-flyout-rule-description"]' + ).contains('Detects plugged USB devices'); // Confirm the rule tags - ['low', 'windows', 'attack.initial_access', 'attack.t1200'].forEach((tag) => { - cy.get('[data-test-subj="finding-details-flyout-rule-tags"]').contains(tag); - }); + ['low', 'windows', 'attack.initial_access', 'attack.t1200'].forEach( + (tag) => { + cy.get( + '[data-test-subj="finding-details-flyout-rule-tags"]' + ).contains(tag); + } + ); }); // Confirm the rule document ID is present @@ -258,7 +296,9 @@ describe('Alerts', () => { .then((text) => expect(text).to.not.equal('-')); // Confirm the rule index - cy.get('[data-test-subj="finding-details-flyout-rule-document-index"]').contains(testIndex); + cy.get( + '[data-test-subj="finding-details-flyout-rule-document-index"]' + ).contains(testIndex); // Confirm the rule document matches // The EuiCodeEditor used for this component stores each line of the JSON in an array of elements; @@ -282,15 +322,21 @@ describe('Alerts', () => { // so this test just checks that the line starts with the ID key. if (expectedLine.trimStart().startsWith('"id": "')) { expectedLine = '"id": "'; - expect(line, `document JSON line ${lineIndex}`).to.contain(expectedLine); + expect(line, `document JSON line ${lineIndex}`).to.contain( + expectedLine + ); } else { line = line.replaceAll('\n', ''); - expect(line, `document JSON line ${lineIndex}`).to.equal(expectedLine); + expect(line, `document JSON line ${lineIndex}`).to.equal( + expectedLine + ); } }); // Press the "back" button - cy.get('[data-test-subj="finding-details-flyout-back-button"]').click({ force: true }); + cy.get('[data-test-subj="finding-details-flyout-back-button"]').click({ + force: true + }); }); // Confirm finding details flyout closed @@ -298,8 +344,10 @@ describe('Alerts', () => { // Confirm the expected alert details flyout rendered cy.get('[data-test-subj="alert-details-flyout"]').within(() => { - cy.get('[data-test-subj="text-details-group-content-alert-trigger-name"]').contains( - testDetector.triggers[0].name + cy.get( + '[data-test-subj="text-details-group-content-alert-trigger-name"]' + ).contains( + testDetector.triggers[0].name ); }); }); @@ -402,16 +450,24 @@ describe('Alerts', () => { cy.get('[data-test-subj="alert-details-flyout"]').within(() => { // Confirm the alert is currently "Active" - cy.get('[data-test-subj="text-details-group-content-alert-status"]').contains('Active'); + cy.get( + '[data-test-subj="text-details-group-content-alert-status"]' + ).contains('Active'); // Click the "Acknowledge" button on the flyout - cy.get('[data-test-subj="alert-details-flyout-acknowledge-button"]').click({ force: true }); + cy.get( + '[data-test-subj="alert-details-flyout-acknowledge-button"]' + ).click({ force: true }); // Confirm the alert is now "Acknowledged" - cy.get('[data-test-subj="text-details-group-content-alert-status"]').contains('Active'); + cy.get( + '[data-test-subj="text-details-group-content-alert-status"]' + ).contains('Active'); // Confirm the "Acknowledge" button is disabled - cy.get('[data-test-subj="alert-details-flyout-acknowledge-button"]').should('be.disabled'); + cy.get( + '[data-test-subj="alert-details-flyout-acknowledge-button"]' + ).should('be.disabled'); }); }); @@ -447,7 +503,9 @@ describe('Alerts', () => { }); // Confirm the detector details page is for the expected detector - cy.get('[data-test-subj="detector-details-detector-name"]').contains(testDetector.name); + cy.get('[data-test-subj="detector-details-detector-name"]').contains( + testDetector.name + ); }); after(() => cy.cleanUpTests()); diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js index f49cf4093..46640fce7 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js @@ -5,8 +5,8 @@ import { DETECTOR_TRIGGER_TIMEOUT, - OPENSEARCH_DASHBOARDS_URL -} from "../../../utils/plugins/security-analytics-dashboards-plugin/constants"; + OPENSEARCH_DASHBOARDS_URL, +} from '../../../utils/plugins/security-analytics-dashboards-plugin/constants'; import sample_document from '../../../fixtures/plugins/security-analytics-dashboards-plugin/sample_document.json'; import sample_index_settings from '../../../fixtures/plugins/security-analytics-dashboards-plugin/sample_index_settings.json'; import sample_field_mappings from '../../../fixtures/plugins/security-analytics-dashboards-plugin/sample_field_mappings.json'; @@ -71,7 +71,9 @@ describe('Findings', () => { cy.contains('Rule details'); // Close Flyout - cy.get('.euiFlexItem--flexGrowZero > .euiButtonIcon').click({ force: true }); + cy.get( + '.euiFlexItem--flexGrowZero > .euiButtonIcon' + ).click({ force: true }); }); it('displays finding details flyout when user clicks on Finding ID', () => { @@ -79,7 +81,9 @@ describe('Findings', () => { cy.triggerSearchField('Search findings', 'sample_detector'); // Click findingId to trigger Finding details flyout - cy.getTableFirstRow('[data-test-subj="finding-details-flyout-button"]').then(($el) => { + cy.getTableFirstRow( + '[data-test-subj="finding-details-flyout-button"]' + ).then(($el) => { cy.get($el).click({ force: true }); }); @@ -88,7 +92,9 @@ describe('Findings', () => { cy.contains('Rule details'); // Close Flyout - cy.get('.euiFlexItem--flexGrowZero > .euiButtonIcon').click({ force: true }); + cy.get( + '.euiFlexItem--flexGrowZero > .euiButtonIcon' + ).click({ force: true }); }); it('allows user to view details about rules that were triggered', () => { @@ -100,7 +106,9 @@ describe('Findings', () => { // open rule details inside flyout cy.get('button', { timeout: 1000 }); - cy.get(`[data-test-subj="finding-details-flyout-rule-accordion-0"]`).click({ force: true }); + cy.get( + `[data-test-subj="finding-details-flyout-rule-accordion-0"]` + ).click({ force: true }); // Confirm content cy.contains('Documents'); @@ -127,13 +135,15 @@ describe('Findings', () => { }); // Click rule link - cy.get(`[data-test-subj="finding-details-flyout-USB Device Plugged-details"]`).click({ - force: true, - }); + cy.get( + `[data-test-subj="finding-details-flyout-USB Device Plugged-details"]` + ).click({ force: true }); // Validate flyout appearance cy.get('[data-test-subj="rule_flyout_USB Device Plugged"]').within(() => { - cy.get('[data-test-subj="rule_flyout_rule_name"]').contains('USB Device Plugged'); + cy.get('[data-test-subj="rule_flyout_rule_name"]').contains( + 'USB Device Plugged' + ); }); }); @@ -166,7 +176,9 @@ describe('Findings', () => { .click({ force: true }) .then(() => { // Confirm arrival at detectors page - cy.get('[data-test-subj="editButton"]').contains('Delete').click({ force: true }); + cy.get('[data-test-subj="editButton"]') + .contains('Delete') + .click({ force: true }); // Search for sample_detector, presumably deleted cy.triggerSearchField('Search threat detectors', 'sample_detector'); diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js index 09c648b82..d2ec8d687 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js @@ -5,8 +5,9 @@ import { DETECTOR_TRIGGER_TIMEOUT, - OPENSEARCH_DASHBOARDS_URL -} from "../../../utils/plugins/security-analytics-dashboards-plugin/constants";import sample_index_settings from '../../../fixtures/plugins/security-analytics-dashboards-plugin/sample_index_settings.json'; + OPENSEARCH_DASHBOARDS_URL, +} from "../../../utils/plugins/security-analytics-dashboards-plugin/constants"; +import sample_index_settings from '../../../fixtures/plugins/security-analytics-dashboards-plugin/sample_index_settings.json'; import sample_dns_settings from '../../../fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/index/create_dns_settings.json'; import windows_usb_rule_data from '../../../fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/rule/create_windows_usb_rule.json'; import dns_rule_data from '../../../fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/rule/create_dns_rule.json'; @@ -26,11 +27,13 @@ describe('Integration tests', () => { // Create custom rules cy.createRule(windows_usb_rule_data).then((response) => { - usb_detector_data.inputs[0].detector_input.custom_rules[0].id = response.body.response._id; + usb_detector_data.inputs[0].detector_input.custom_rules[0].id = + response.body.response._id; usb_detector_data.triggers[0].ids.push(response.body.response._id); }); cy.createRule(dns_rule_data).then((response) => { - dns_detector_data.inputs[0].detector_input.custom_rules[0].id = response.body.response._id; + dns_detector_data.inputs[0].detector_input.custom_rules[0].id = + response.body.response._id; dns_detector_data.triggers[0].ids.push(response.body.response._id); }); @@ -59,7 +62,11 @@ describe('Integration tests', () => { `${Cypress.env('opensearch')}/${indexName}/_doc/101`, add_windows_index_data ); - cy.request('POST', `${Cypress.env('opensearch')}/${dnsName}/_doc/101`, add_dns_index_data); + cy.request( + 'POST', + `${Cypress.env('opensearch')}/${dnsName}/_doc/101`, + add_dns_index_data + ); // Wait for detector interval to pass cy.wait(DETECTOR_TRIGGER_TIMEOUT); @@ -91,12 +98,16 @@ describe('Integration tests', () => { .then((hash) => { const detectorId = hash.replace('#/findings/', ''); if (!detectorId) { - throw new Error('Navigating to findings page should contain detector ID'); + throw new Error( + 'Navigating to findings page should contain detector ID' + ); } else { cy.wait('@getFindings').then((interception) => { const url = new URL(interception.request.url); // The request query param detectorId should match the hash param from the url - expect(url.searchParams.get('detectorId')).to.eq(detectorId); + expect(url.searchParams.get('detectorId')).to.eq( + detectorId + ); }); // There should be only one call to the API @@ -124,12 +135,16 @@ describe('Integration tests', () => { .then((hash) => { const detectorId = hash.replace('#/alerts/', ''); if (!detectorId) { - throw new Error('Navigating to alerts page should contain detector ID'); + throw new Error( + 'Navigating to alerts page should contain detector ID' + ); } else { cy.wait('@getAlerts').then((interception) => { const url = new URL(interception.request.url); // The request query param detectorId should match the hash param from the url - expect(url.searchParams.get('detector_id')).to.eq(detectorId); + expect(url.searchParams.get('detector_id')).to.eq( + detectorId + ); }); // There should be only one call to the API diff --git a/cypress/utils/commands.js b/cypress/utils/commands.js index c3f807819..91085d7a4 100644 --- a/cypress/utils/commands.js +++ b/cypress/utils/commands.js @@ -100,7 +100,9 @@ Cypress.Commands.add('deleteAllIndices', () => { cy.log('Deleting all indices'); cy.request( 'DELETE', - `${Cypress.env('openSearchUrl')}/index*,sample*,opensearch_dashboards*,test*,cypress*` + `${Cypress.env( + 'openSearchUrl' + )}/index*,sample*,opensearch_dashboards*,test*,cypress*` ); }); diff --git a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js index 0a9c10fec..84cb7ef9c 100644 --- a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js +++ b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js @@ -17,10 +17,14 @@ Cypress.Commands.add('getTableFirstRow', (selector) => { }); Cypress.Commands.add('triggerSearchField', (placeholder, text) => { - cy.get(`[placeholder="${placeholder}"]`).type(`{selectall}${text}`).realPress('Enter'); + cy.get(`[placeholder="${placeholder}"]`).type( + `{selectall}${text}` + ).realPress('Enter'); }); -Cypress.Commands.add('waitForPageLoad', (url, { timeout = 10000, contains = null }) => { +Cypress.Commands.add('' + + 'waitForPageLoad', + (url, { timeout = 10000, contains = null }) => { const fullUrl = `${OPENSEARCH_DASHBOARDS_URL}/${url}`; Cypress.log({ message: `Wait for url: ${fullUrl} to be loaded.`, @@ -30,7 +34,8 @@ Cypress.Commands.add('waitForPageLoad', (url, { timeout = 10000, contains = null .then(() => { contains && cy.contains(contains); }); -}); +} +); Cypress.Commands.add('deleteAllDetectors', () => { cy.request({ @@ -41,7 +46,11 @@ Cypress.Commands.add('deleteAllDetectors', () => { }); Cypress.Commands.add('createDetector', (detectorJSON) => { - cy.request('POST', `${Cypress.env('opensearch')}${NODE_API.DETECTORS_BASE}`, detectorJSON); + cy.request( + 'POST', + `${Cypress.env('opensearch')}${NODE_API.DETECTORS_BASE}`, + detectorJSON + ); }); Cypress.Commands.add('updateDetector', (detectorId, detectorJSON) => { @@ -75,7 +84,10 @@ Cypress.Commands.add('deleteDetector', (detectorName) => { }).then((response) => { if (response.status === 200) { for (let hit of response.body.hits.hits) { - cy.request('DELETE', `${Cypress.env('opensearch')}${NODE_API.DETECTORS_BASE}/${hit._id}`); + cy.request( + 'DELETE', + `${Cypress.env('opensearch')}${NODE_API.DETECTORS_BASE}/${hit._id}` + ); } } }); @@ -96,7 +108,7 @@ Cypress.Commands.add( body: body, }); } -); + ); Cypress.Commands.add('createRule', (ruleJSON) => { return cy.request({ @@ -107,7 +119,11 @@ Cypress.Commands.add('createRule', (ruleJSON) => { }); Cypress.Commands.add('updateRule', (ruleId, ruleJSON) => { - cy.request('PUT', `${Cypress.env('opensearch')}/${NODE_API.RULES_BASE}/${ruleId}`, ruleJSON); + cy.request( + 'PUT', + `${Cypress.env('opensearch')}/${NODE_API.RULES_BASE}/${ruleId}`, + ruleJSON + ); }); Cypress.Commands.add('deleteRule', (ruleName) => { @@ -127,7 +143,9 @@ Cypress.Commands.add('deleteRule', (ruleName) => { }; cy.request({ method: 'POST', - url: `${Cypress.env('opensearch')}${NODE_API.RULES_BASE}/_search?pre_packaged=false`, + url: `${Cypress.env('opensearch')}${ + NODE_API.RULES_BASE + }/_search?pre_packaged=false`, failOnStatusCode: false, body, }).then((response) => { @@ -136,7 +154,9 @@ Cypress.Commands.add('deleteRule', (ruleName) => { if (hit._source.title === ruleName) cy.request( 'DELETE', - `${Cypress.env('opensearch')}${NODE_API.RULES_BASE}/${hit._id}?forced=true` + `${Cypress.env('opensearch')}${NODE_API.RULES_BASE}/${ + hit._id + }?forced=true` ); } } From e158ef7a433a782c9656e2fa5c27b38b51912189 Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Fri, 20 Jan 2023 13:19:25 -0800 Subject: [PATCH 05/36] Fixed eslint errors. Signed-off-by: AWSHurneyt --- .../1_detectors.spec.js | 30 +++-- .../2_rules.spec.js | 57 ++++----- .../3_alerts.spec.js | 108 +++++++++--------- .../4_findings.spec.js | 28 ++--- .../5_integrations.spec.js | 20 ++-- cypress/utils/commands.js | 2 +- .../commands.js | 90 ++++++++------- 7 files changed, 168 insertions(+), 167 deletions(-) diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js index c3c010c8e..4548bb851 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js @@ -3,9 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { - OPENSEARCH_DASHBOARDS_URL, -} from "../../../utils/plugins/security-analytics-dashboards-plugin/constants"; +import { OPENSEARCH_DASHBOARDS_URL } from '../../../utils/plugins/security-analytics-dashboards-plugin/constants'; import sample_index_settings from '../../../fixtures/plugins/security-analytics-dashboards-plugin/sample_index_settings.json'; const testMappings = { @@ -67,12 +65,12 @@ describe('Detectors', () => { // Enter a name for the detector in the appropriate input cy.get(`input[placeholder="Enter a name for the detector."]`).type( - 'test detector{enter}' + 'test detector{enter}' ); // Select our pre-seeded data source (check indexName) cy.get(`[data-test-subj="define-detector-select-data-source"]`).type( - `${indexName}{enter}` + `${indexName}{enter}` ); // Select threat detector type (Windows logs) @@ -115,8 +113,8 @@ describe('Detectors', () => { cy.contains('tr', field_name).within(() => { cy.get(`[data-test-subj="detector-field-mappings-select"]`) - .click() - .type(mappedTo); + .click() + .type(mappedTo); }); } @@ -128,17 +126,17 @@ describe('Detectors', () => { // Type name of new trigger cy.get(`input[placeholder="Enter a name for the alert condition."]`).type( - 'test_trigger' + 'test_trigger' ); // Type in (or select) tags for the alert condition cy.get(`[data-test-subj="alert-tags-combo-box"]`).type( - 'attack.defense_evasion{enter}' + 'attack.defense_evasion{enter}' ); // Select applicable severity levels cy.get(`[data-test-subj="security-levels-combo-box"]`).click({ - force: true + force: true, }); cy.contains('1 (Highest)').click({ force: true }); @@ -198,7 +196,7 @@ describe('Detectors', () => { // Click "Edit" button in detector details cy.get(`[data-test-subj="edit-detector-basic-details"]`).click({ - force: true + force: true, }); // Confirm arrival at "Edit detector details" page @@ -211,7 +209,7 @@ describe('Detectors', () => { // Change detector description cy.get(`[data-test-subj="define-detector-detector-description"]`).type( - 'Edited description' + 'Edited description' ); // Change input source @@ -221,13 +219,13 @@ describe('Detectors', () => { // Change detector scheduling cy.get(`[data-test-subj="detector-schedule-number-select"]`).type( - '{selectall}10' + '{selectall}10' ); cy.get(`[data-test-subj="detector-schedule-unit-select"]`).select('Hours'); // Save changes to detector details cy.get(`[data-test-subj="save-basic-details-edits"]`).click({ - force: true + force: true, }); // Confirm taken to detector details page @@ -278,7 +276,7 @@ describe('Detectors', () => { // Save changes cy.get(`[data-test-subj="save-detector-rules-edits"]`).click({ - force: true + force: true, }); // Confirm 1 rule has been removed from detector @@ -303,7 +301,7 @@ describe('Detectors', () => { // Save changes cy.get(`[data-test-subj="save-detector-rules-edits"]`).click({ - force: true + force: true, }); cy.waitForPageLoad('detector-details', { contains: detectorName, diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js index d8c11c662..7b554c838 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js @@ -4,8 +4,8 @@ */ const { - OPENSEARCH_DASHBOARDS_URL, -} = require("../../../utils/plugins/security-analytics-dashboards-plugin/constants"); + OPENSEARCH_DASHBOARDS_URL, +} = require('../../../utils/plugins/security-analytics-dashboards-plugin/constants'); const uniqueId = Cypress._.random(0, 1e6); const SAMPLE_RULE = { @@ -23,9 +23,9 @@ const SAMPLE_RULE = { ], severity: 'critical', tags: [ - 'attack.persistence', - 'attack.privilege_escalation', - 'attack.t1543.003' + 'attack.persistence', + 'attack.privilege_escalation', + 'attack.t1543.003', ], references: 'https://nohello.com', falsePositive: 'unknown', @@ -51,9 +51,10 @@ const YAML_RULE_LINES = [ `- '${SAMPLE_RULE.references}'`, `author: ${SAMPLE_RULE.author}`, `detection:`, - ...SAMPLE_RULE.detection.replaceAll(' ', '') - .replaceAll('{backspace}', '') - .split('\n'), + ...SAMPLE_RULE.detection + .replaceAll(' ', '') + .replaceAll('{backspace}', '') + .split('\n'), ]; describe('Rules', () => { @@ -82,12 +83,12 @@ describe('Rules', () => { // Enter the description cy.get('[data-test-subj="rule_description_field"]').type( - SAMPLE_RULE.description + SAMPLE_RULE.description ); // Enter the severity cy.get('[data-test-subj="rule_severity_dropdown"]').type( - SAMPLE_RULE.severity + SAMPLE_RULE.severity ); // Enter the tags @@ -97,12 +98,12 @@ describe('Rules', () => { // Enter the reference cy.get('[data-test-subj="rule_references_field_0"]').type( - SAMPLE_RULE.references + SAMPLE_RULE.references ); // Enter the false positive cases cy.get('[data-test-subj="rule_false_positives_field_0"]').type( - SAMPLE_RULE.falsePositive + SAMPLE_RULE.falsePositive ); // Enter the author @@ -113,7 +114,7 @@ describe('Rules', () => { // Enter the detection cy.get('[data-test-subj="rule_detection_field"]').type( - SAMPLE_RULE.detection + SAMPLE_RULE.detection ); // Switch to YAML editor @@ -121,8 +122,8 @@ describe('Rules', () => { force: true, }); - YAML_RULE_LINES.forEach((line) => cy.get( - '[data-test-subj="rule_yaml_editor"]').contains(line) + YAML_RULE_LINES.forEach((line) => + cy.get('[data-test-subj="rule_yaml_editor"]').contains(line) ); cy.intercept({ @@ -145,7 +146,7 @@ describe('Rules', () => { // Click the rule link to open the details flyout cy.get(`[data-test-subj="rule_link_${SAMPLE_RULE.name}"]`).click({ - force: true + force: true, }); // Confirm the flyout contains the expected values @@ -154,22 +155,22 @@ describe('Rules', () => { .within(() => { // Validate name cy.get('[data-test-subj="rule_flyout_rule_name"]').contains( - SAMPLE_RULE.name + SAMPLE_RULE.name ); // Validate log type cy.get('[data-test-subj="rule_flyout_rule_log_type"]').contains( - SAMPLE_RULE.logType + SAMPLE_RULE.logType ); // Validate description cy.get('[data-test-subj="rule_flyout_rule_description"]').contains( - SAMPLE_RULE.description + SAMPLE_RULE.description ); // Validate author cy.get('[data-test-subj="rule_flyout_rule_author"]').contains( - SAMPLE_RULE.author + SAMPLE_RULE.author ); // Validate source is "custom" @@ -177,7 +178,7 @@ describe('Rules', () => { // Validate severity cy.get('[data-test-subj="rule_flyout_rule_severity"]').contains( - SAMPLE_RULE.severity + SAMPLE_RULE.severity ); // Validate tags @@ -187,7 +188,7 @@ describe('Rules', () => { // Validate references cy.get('[data-test-subj="rule_flyout_rule_references"]').contains( - SAMPLE_RULE.references + SAMPLE_RULE.references ); // Validate false positives @@ -197,7 +198,7 @@ describe('Rules', () => { // Validate status cy.get('[data-test-subj="rule_flyout_rule_status"]').contains( - SAMPLE_RULE.status + SAMPLE_RULE.status ); // Validate detection @@ -206,9 +207,9 @@ describe('Rules', () => { ); cy.get( - '[data-test-subj="change-editor-type"] label:nth-child(2)' + '[data-test-subj="change-editor-type"] label:nth-child(2)' ).click({ - force: true + force: true, }); cy.get('[data-test-subj="rule_flyout_yaml_rule"]') @@ -225,11 +226,11 @@ describe('Rules', () => { if (expectedLine.startsWith('id:')) { expectedLine = 'id:'; expect(line, `Sigma rule line ${lineIndex}`).to.contain( - expectedLine + expectedLine ); } else { expect(line, `Sigma rule line ${lineIndex}`).to.equal( - expectedLine + expectedLine ); } }); @@ -250,7 +251,7 @@ describe('Rules', () => { // Click the rule link to open the details flyout cy.get(`[data-test-subj="rule_link_${SAMPLE_RULE.name}"]`).click({ - force: true + force: true, }); cy.get('.euiButton') diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js index 95b11fc95..47664fcbe 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js @@ -43,8 +43,8 @@ const testDetector = { // Moment is not available in this repository, so refactored this variable to use Date. // const date = moment(moment.now()).format('MM/DD/YY'); const now = new Date(Date.now()); -const month = ( - now.getMonth() + 1) < 10 ? `0${now.getMonth() + 1}` : `${now.getMonth() + 1}`; +const month = + now.getMonth() + 1 < 10 ? `0${now.getMonth() + 1}` : `${now.getMonth() + 1}`; const day = now.getDate() < 10 ? `0${now.getDate()}` : `${now.getDate()}`; const year = `${now.getFullYear()}`.substr(1); const date = `${month}/${day}/${year}`; @@ -60,10 +60,10 @@ describe('Alerts', () => { // Create field mappings .then(() => cy.createAliasMappings( - testIndex, - testDetector.detector_type, - sample_alias_mappings, - true + testIndex, + testDetector.detector_type, + sample_alias_mappings, + true ) ) @@ -111,18 +111,18 @@ describe('Alerts', () => { // Adjust the date range picker to display alerts from today cy.get( - '[class="euiButtonEmpty__text euiQuickSelectPopover__buttonText"]' - ).click({ force: true }); - cy.get( - '[data-test-subj="superDatePickerCommonlyUsed_Today"]' + '[class="euiButtonEmpty__text euiQuickSelectPopover__buttonText"]' ).click({ force: true }); + cy.get('[data-test-subj="superDatePickerCommonlyUsed_Today"]').click({ + force: true, + }); }); it('are generated', () => { // Refresh the table - cy.get( - '[data-test-subj="superDatePickerApplyTimeButton"]' - ).click({ force: true }); + cy.get('[data-test-subj="superDatePickerApplyTimeButton"]').click({ + force: true, + }); // Confirm there are alerts created cy.get('tbody > tr') @@ -153,33 +153,33 @@ describe('Alerts', () => { cy.get('[data-test-subj="alert-details-flyout"]').within(() => { // Confirm alert condition name cy.get( - '[data-test-subj="text-details-group-content-alert-trigger-name"]' + '[data-test-subj="text-details-group-content-alert-trigger-name"]' ).contains(testDetector.triggers[0].name); // Confirm alert status cy.get( - '[data-test-subj="text-details-group-content-alert-status"]' + '[data-test-subj="text-details-group-content-alert-status"]' ).contains('Active'); // Confirm alert severity cy.get( - '[data-test-subj="text-details-group-content-alert-severity"]' + '[data-test-subj="text-details-group-content-alert-severity"]' ).contains('4 (Low)'); // Confirm alert start time is present cy.get( - '[data-test-subj="text-details-group-content-start-time"]' + '[data-test-subj="text-details-group-content-start-time"]' ).contains(date); // Confirm alert last updated time is present cy.get( - '[data-test-subj="text-details-group-content-last-updated-time"]' + '[data-test-subj="text-details-group-content-last-updated-time"]' ).contains(date); // Confirm alert detector name - cy.get( - '[data-test-subj="text-details-group-content-detector"]' - ).contains(testDetector.name); + cy.get('[data-test-subj="text-details-group-content-detector"]').contains( + testDetector.name + ); // Wait for the findings table to finish loading cy.contains('Findings (1)'); @@ -194,9 +194,9 @@ describe('Alerts', () => { }); // Close the flyout - cy.get( - '[data-test-subj="alert-details-flyout-close-button"]' - ).click({ force: true }); + cy.get('[data-test-subj="alert-details-flyout-close-button"]').click({ + force: true, + }); }); // Confirm flyout has been closed @@ -234,60 +234,60 @@ describe('Alerts', () => { .then((text) => expect(text).to.have.length.greaterThan(1)); // Confirm finding timestamp - cy.get( - '[data-test-subj="finding-details-flyout-timestamp"]' - ).contains(date); + cy.get('[data-test-subj="finding-details-flyout-timestamp"]').contains( + date + ); // Confirm finding detector name cy.get( - '[data-test-subj="finding-details-flyout-detector-link"]' + '[data-test-subj="finding-details-flyout-detector-link"]' ).contains(testDetector.name); // Confirm there's only 1 rule details accordion cy.get( - '[data-test-subj="finding-details-flyout-rule-accordion-1"]' + '[data-test-subj="finding-details-flyout-rule-accordion-1"]' ).should('not.exist'); // Check the rule details accordion for the expected values cy.get( - '[data-test-subj="finding-details-flyout-rule-accordion-0"]' + '[data-test-subj="finding-details-flyout-rule-accordion-0"]' ).within(() => { // Confirm the accordion button contains the expected text cy.get( - '[data-test-subj="finding-details-flyout-rule-accordion-button"]' + '[data-test-subj="finding-details-flyout-rule-accordion-button"]' ).contains('USB Device Plugged'); cy.get( - '[data-test-subj="finding-details-flyout-rule-accordion-button"]' + '[data-test-subj="finding-details-flyout-rule-accordion-button"]' ).contains('Severity: Low'); // Confirm the rule name cy.get( - '[data-test-subj="finding-details-flyout-USB Device Plugged-details"]' + '[data-test-subj="finding-details-flyout-USB Device Plugged-details"]' ).contains('USB Device Plugged'); // Confirm the rule severity cy.get( - '[data-test-subj="finding-details-flyout-rule-severity"]' + '[data-test-subj="finding-details-flyout-rule-severity"]' ).contains('Low'); // Confirm the rule category cy.get( - '[data-test-subj="finding-details-flyout-rule-category"]' + '[data-test-subj="finding-details-flyout-rule-category"]' ).contains('Windows'); // Confirm the rule description cy.get( - '[data-test-subj="finding-details-flyout-rule-description"]' + '[data-test-subj="finding-details-flyout-rule-description"]' ).contains('Detects plugged USB devices'); // Confirm the rule tags ['low', 'windows', 'attack.initial_access', 'attack.t1200'].forEach( - (tag) => { - cy.get( - '[data-test-subj="finding-details-flyout-rule-tags"]' - ).contains(tag); - } - ); + (tag) => { + cy.get( + '[data-test-subj="finding-details-flyout-rule-tags"]' + ).contains(tag); + } + ); }); // Confirm the rule document ID is present @@ -297,7 +297,7 @@ describe('Alerts', () => { // Confirm the rule index cy.get( - '[data-test-subj="finding-details-flyout-rule-document-index"]' + '[data-test-subj="finding-details-flyout-rule-document-index"]' ).contains(testIndex); // Confirm the rule document matches @@ -323,19 +323,19 @@ describe('Alerts', () => { if (expectedLine.trimStart().startsWith('"id": "')) { expectedLine = '"id": "'; expect(line, `document JSON line ${lineIndex}`).to.contain( - expectedLine + expectedLine ); } else { line = line.replaceAll('\n', ''); expect(line, `document JSON line ${lineIndex}`).to.equal( - expectedLine + expectedLine ); } }); // Press the "back" button cy.get('[data-test-subj="finding-details-flyout-back-button"]').click({ - force: true + force: true, }); }); @@ -345,10 +345,8 @@ describe('Alerts', () => { // Confirm the expected alert details flyout rendered cy.get('[data-test-subj="alert-details-flyout"]').within(() => { cy.get( - '[data-test-subj="text-details-group-content-alert-trigger-name"]' - ).contains( - testDetector.triggers[0].name - ); + '[data-test-subj="text-details-group-content-alert-trigger-name"]' + ).contains(testDetector.triggers[0].name); }); }); @@ -451,22 +449,22 @@ describe('Alerts', () => { cy.get('[data-test-subj="alert-details-flyout"]').within(() => { // Confirm the alert is currently "Active" cy.get( - '[data-test-subj="text-details-group-content-alert-status"]' + '[data-test-subj="text-details-group-content-alert-status"]' ).contains('Active'); // Click the "Acknowledge" button on the flyout cy.get( - '[data-test-subj="alert-details-flyout-acknowledge-button"]' + '[data-test-subj="alert-details-flyout-acknowledge-button"]' ).click({ force: true }); // Confirm the alert is now "Acknowledged" cy.get( - '[data-test-subj="text-details-group-content-alert-status"]' + '[data-test-subj="text-details-group-content-alert-status"]' ).contains('Active'); // Confirm the "Acknowledge" button is disabled cy.get( - '[data-test-subj="alert-details-flyout-acknowledge-button"]' + '[data-test-subj="alert-details-flyout-acknowledge-button"]' ).should('be.disabled'); }); }); @@ -504,7 +502,7 @@ describe('Alerts', () => { // Confirm the detector details page is for the expected detector cy.get('[data-test-subj="detector-details-detector-name"]').contains( - testDetector.name + testDetector.name ); }); diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js index 46640fce7..7e84302be 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js @@ -71,9 +71,9 @@ describe('Findings', () => { cy.contains('Rule details'); // Close Flyout - cy.get( - '.euiFlexItem--flexGrowZero > .euiButtonIcon' - ).click({ force: true }); + cy.get('.euiFlexItem--flexGrowZero > .euiButtonIcon').click({ + force: true, + }); }); it('displays finding details flyout when user clicks on Finding ID', () => { @@ -82,7 +82,7 @@ describe('Findings', () => { // Click findingId to trigger Finding details flyout cy.getTableFirstRow( - '[data-test-subj="finding-details-flyout-button"]' + '[data-test-subj="finding-details-flyout-button"]' ).then(($el) => { cy.get($el).click({ force: true }); }); @@ -92,9 +92,9 @@ describe('Findings', () => { cy.contains('Rule details'); // Close Flyout - cy.get( - '.euiFlexItem--flexGrowZero > .euiButtonIcon' - ).click({ force: true }); + cy.get('.euiFlexItem--flexGrowZero > .euiButtonIcon').click({ + force: true, + }); }); it('allows user to view details about rules that were triggered', () => { @@ -106,9 +106,9 @@ describe('Findings', () => { // open rule details inside flyout cy.get('button', { timeout: 1000 }); - cy.get( - `[data-test-subj="finding-details-flyout-rule-accordion-0"]` - ).click({ force: true }); + cy.get(`[data-test-subj="finding-details-flyout-rule-accordion-0"]`).click({ + force: true, + }); // Confirm content cy.contains('Documents'); @@ -136,13 +136,13 @@ describe('Findings', () => { // Click rule link cy.get( - `[data-test-subj="finding-details-flyout-USB Device Plugged-details"]` + `[data-test-subj="finding-details-flyout-USB Device Plugged-details"]` ).click({ force: true }); // Validate flyout appearance cy.get('[data-test-subj="rule_flyout_USB Device Plugged"]').within(() => { cy.get('[data-test-subj="rule_flyout_rule_name"]').contains( - 'USB Device Plugged' + 'USB Device Plugged' ); }); }); @@ -177,8 +177,8 @@ describe('Findings', () => { .then(() => { // Confirm arrival at detectors page cy.get('[data-test-subj="editButton"]') - .contains('Delete') - .click({ force: true }); + .contains('Delete') + .click({ force: true }); // Search for sample_detector, presumably deleted cy.triggerSearchField('Search threat detectors', 'sample_detector'); diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js index d2ec8d687..e7942b13f 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js @@ -6,7 +6,7 @@ import { DETECTOR_TRIGGER_TIMEOUT, OPENSEARCH_DASHBOARDS_URL, -} from "../../../utils/plugins/security-analytics-dashboards-plugin/constants"; +} from '../../../utils/plugins/security-analytics-dashboards-plugin/constants'; import sample_index_settings from '../../../fixtures/plugins/security-analytics-dashboards-plugin/sample_index_settings.json'; import sample_dns_settings from '../../../fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/index/create_dns_settings.json'; import windows_usb_rule_data from '../../../fixtures/plugins/security-analytics-dashboards-plugin/integration_tests/rule/create_windows_usb_rule.json'; @@ -28,12 +28,12 @@ describe('Integration tests', () => { // Create custom rules cy.createRule(windows_usb_rule_data).then((response) => { usb_detector_data.inputs[0].detector_input.custom_rules[0].id = - response.body.response._id; + response.body.response._id; usb_detector_data.triggers[0].ids.push(response.body.response._id); }); cy.createRule(dns_rule_data).then((response) => { dns_detector_data.inputs[0].detector_input.custom_rules[0].id = - response.body.response._id; + response.body.response._id; dns_detector_data.triggers[0].ids.push(response.body.response._id); }); @@ -63,9 +63,9 @@ describe('Integration tests', () => { add_windows_index_data ); cy.request( - 'POST', - `${Cypress.env('opensearch')}/${dnsName}/_doc/101`, - add_dns_index_data + 'POST', + `${Cypress.env('opensearch')}/${dnsName}/_doc/101`, + add_dns_index_data ); // Wait for detector interval to pass @@ -99,14 +99,14 @@ describe('Integration tests', () => { const detectorId = hash.replace('#/findings/', ''); if (!detectorId) { throw new Error( - 'Navigating to findings page should contain detector ID' + 'Navigating to findings page should contain detector ID' ); } else { cy.wait('@getFindings').then((interception) => { const url = new URL(interception.request.url); // The request query param detectorId should match the hash param from the url expect(url.searchParams.get('detectorId')).to.eq( - detectorId + detectorId ); }); @@ -136,14 +136,14 @@ describe('Integration tests', () => { const detectorId = hash.replace('#/alerts/', ''); if (!detectorId) { throw new Error( - 'Navigating to alerts page should contain detector ID' + 'Navigating to alerts page should contain detector ID' ); } else { cy.wait('@getAlerts').then((interception) => { const url = new URL(interception.request.url); // The request query param detectorId should match the hash param from the url expect(url.searchParams.get('detector_id')).to.eq( - detectorId + detectorId ); }); diff --git a/cypress/utils/commands.js b/cypress/utils/commands.js index 91085d7a4..61ca1e79d 100644 --- a/cypress/utils/commands.js +++ b/cypress/utils/commands.js @@ -101,7 +101,7 @@ Cypress.Commands.add('deleteAllIndices', () => { cy.request( 'DELETE', `${Cypress.env( - 'openSearchUrl' + 'openSearchUrl' )}/index*,sample*,opensearch_dashboards*,test*,cypress*` ); }); diff --git a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js index 84cb7ef9c..684cd6b6b 100644 --- a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js +++ b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js @@ -3,7 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -const { NODE_API, OPENSEARCH_DASHBOARDS, OPENSEARCH_DASHBOARDS_URL } = require('./constants'); +const { + NODE_API, + OPENSEARCH_DASHBOARDS, + OPENSEARCH_DASHBOARDS_URL, +} = require('./constants'); Cypress.Commands.add('cleanUpTests', () => { cy.deleteAllCustomRules(); @@ -17,24 +21,24 @@ Cypress.Commands.add('getTableFirstRow', (selector) => { }); Cypress.Commands.add('triggerSearchField', (placeholder, text) => { - cy.get(`[placeholder="${placeholder}"]`).type( - `{selectall}${text}` - ).realPress('Enter'); + cy.get(`[placeholder="${placeholder}"]`) + .type(`{selectall}${text}`) + .realPress('Enter'); }); -Cypress.Commands.add('' + - 'waitForPageLoad', - (url, { timeout = 10000, contains = null }) => { - const fullUrl = `${OPENSEARCH_DASHBOARDS_URL}/${url}`; - Cypress.log({ - message: `Wait for url: ${fullUrl} to be loaded.`, - }); - cy.url({ timeout: timeout }) +Cypress.Commands.add( + '' + 'waitForPageLoad', + (url, { timeout = 10000, contains = null }) => { + const fullUrl = `${OPENSEARCH_DASHBOARDS_URL}/${url}`; + Cypress.log({ + message: `Wait for url: ${fullUrl} to be loaded.`, + }); + cy.url({ timeout: timeout }) .should('include', fullUrl) .then(() => { contains && cy.contains(contains); }); -} + } ); Cypress.Commands.add('deleteAllDetectors', () => { @@ -47,17 +51,17 @@ Cypress.Commands.add('deleteAllDetectors', () => { Cypress.Commands.add('createDetector', (detectorJSON) => { cy.request( - 'POST', - `${Cypress.env('opensearch')}${NODE_API.DETECTORS_BASE}`, - detectorJSON + 'POST', + `${Cypress.env('opensearch')}${NODE_API.DETECTORS_BASE}`, + detectorJSON ); }); Cypress.Commands.add('updateDetector', (detectorId, detectorJSON) => { cy.request( - 'PUT', - `${Cypress.env('opensearch')}/${NODE_API.DETECTORS_BASE}/${detectorId}`, - detectorJSON + 'PUT', + `${Cypress.env('opensearch')}/${NODE_API.DETECTORS_BASE}/${detectorId}`, + detectorJSON ); }); @@ -85,8 +89,8 @@ Cypress.Commands.add('deleteDetector', (detectorName) => { if (response.status === 200) { for (let hit of response.body.hits.hits) { cy.request( - 'DELETE', - `${Cypress.env('opensearch')}${NODE_API.DETECTORS_BASE}/${hit._id}` + 'DELETE', + `${Cypress.env('opensearch')}${NODE_API.DETECTORS_BASE}/${hit._id}` ); } } @@ -94,21 +98,21 @@ Cypress.Commands.add('deleteDetector', (detectorName) => { }); Cypress.Commands.add( - 'createAliasMappings', - (indexName, ruleTopic, aliasMappingsBody, partial = true) => { - const body = { - index_name: indexName, - rule_topic: ruleTopic, - partial: partial, - alias_mappings: aliasMappingsBody, - }; - cy.request({ - method: 'POST', - url: `${Cypress.env('opensearch')}${NODE_API.MAPPINGS_BASE}`, - body: body, - }); - } - ); + 'createAliasMappings', + (indexName, ruleTopic, aliasMappingsBody, partial = true) => { + const body = { + index_name: indexName, + rule_topic: ruleTopic, + partial: partial, + alias_mappings: aliasMappingsBody, + }; + cy.request({ + method: 'POST', + url: `${Cypress.env('opensearch')}${NODE_API.MAPPINGS_BASE}`, + body: body, + }); + } +); Cypress.Commands.add('createRule', (ruleJSON) => { return cy.request({ @@ -120,9 +124,9 @@ Cypress.Commands.add('createRule', (ruleJSON) => { Cypress.Commands.add('updateRule', (ruleId, ruleJSON) => { cy.request( - 'PUT', - `${Cypress.env('opensearch')}/${NODE_API.RULES_BASE}/${ruleId}`, - ruleJSON + 'PUT', + `${Cypress.env('opensearch')}/${NODE_API.RULES_BASE}/${ruleId}`, + ruleJSON ); }); @@ -153,10 +157,10 @@ Cypress.Commands.add('deleteRule', (ruleName) => { for (let hit of response.body.hits.hits) { if (hit._source.title === ruleName) cy.request( - 'DELETE', - `${Cypress.env('opensearch')}${NODE_API.RULES_BASE}/${ - hit._id - }?forced=true` + 'DELETE', + `${Cypress.env('opensearch')}${NODE_API.RULES_BASE}/${ + hit._id + }?forced=true` ); } } From 884e5c11e5d713bfae984a0efc7bf7b06fa90812 Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Fri, 20 Jan 2023 13:19:59 -0800 Subject: [PATCH 06/36] Added additional cypress tests for the security analytics plugin. Signed-off-by: AWSHurneyt --- site/js/dashboard.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/site/js/dashboard.js b/site/js/dashboard.js index c8245dcd9..63076adc1 100644 --- a/site/js/dashboard.js +++ b/site/js/dashboard.js @@ -119,7 +119,11 @@ const plugins = { name: 'securityAnalyticsDashboards', default: { videos: [ - 'rules_spec.js', + '1_detectors.spec.js', + '2_rules.spec.js', + '3_alerts.spec.js', + '4_findings.spec.js', + '5_integrations.spec.js', ], }, }, From bb660aaccf4d7facbd486ffe708b4a902e0fe27d Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Fri, 20 Jan 2023 13:30:18 -0800 Subject: [PATCH 07/36] Fixed cy.createIndex call. Signed-off-by: AWSHurneyt --- .../security-analytics-dashboards-plugin/1_detectors.spec.js | 2 +- .../security-analytics-dashboards-plugin/3_alerts.spec.js | 2 +- .../security-analytics-dashboards-plugin/4_findings.spec.js | 2 +- .../5_integrations.spec.js | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js index 4548bb851..d6f65f2cc 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js @@ -39,7 +39,7 @@ describe('Detectors', () => { cy.cleanUpTests(); // Create test index - cy.createIndex(indexName, sample_index_settings); + cy.createIndex(indexName, null, sample_index_settings); cy.contains(detectorName).should('not.exist'); }); diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js index 47664fcbe..e2a7def25 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js @@ -55,7 +55,7 @@ describe('Alerts', () => { // Delete any pre-existing test detectors cy.cleanUpTests() // Create test index - .then(() => cy.createIndex(testIndex, sample_index_settings)) + .then(() => cy.createIndex(testIndex, null, sample_index_settings)) // Create field mappings .then(() => diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js index 7e84302be..81a9ad8db 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js @@ -23,7 +23,7 @@ describe('Findings', () => { cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/findings`); // create test index, mappings, and detector - cy.createIndex(indexName, sample_index_settings); + cy.createIndex(indexName, null, sample_index_settings); cy.createAliasMappings(indexName, 'windows', sample_field_mappings, true); cy.createDetector(sample_detector); diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js index e7942b13f..b6c31fa12 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js @@ -38,8 +38,8 @@ describe('Integration tests', () => { }); // Create test index - cy.createIndex(indexName, sample_index_settings); - cy.createIndex(dnsName, sample_dns_settings); + cy.createIndex(indexName, null, sample_index_settings); + cy.createIndex(dnsName, null, sample_dns_settings); // Create detectors cy.createAliasMappings( From 0876580f21bc24edda319cb4a1956e9026abb97c Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Fri, 20 Jan 2023 13:36:46 -0800 Subject: [PATCH 08/36] Fixed import. Signed-off-by: AWSHurneyt --- .../security-analytics-dashboards-plugin/commands.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js index 684cd6b6b..713e52c2b 100644 --- a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js +++ b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js @@ -3,11 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -const { - NODE_API, - OPENSEARCH_DASHBOARDS, - OPENSEARCH_DASHBOARDS_URL, -} = require('./constants'); +const { NODE_API, OPENSEARCH_DASHBOARDS, OPENSEARCH_DASHBOARDS_URL } = require('../../../../cypress/utils/plugins/security-analytics-dashboards-plugin/constants'); Cypress.Commands.add('cleanUpTests', () => { cy.deleteAllCustomRules(); From b51b4b1c2a0dccc48603a9acd058755c951ecf15 Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Fri, 20 Jan 2023 13:37:32 -0800 Subject: [PATCH 09/36] Fixed eslint errors. Signed-off-by: AWSHurneyt --- .../security-analytics-dashboards-plugin/commands.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js index 713e52c2b..f3fe55391 100644 --- a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js +++ b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js @@ -3,7 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -const { NODE_API, OPENSEARCH_DASHBOARDS, OPENSEARCH_DASHBOARDS_URL } = require('../../../../cypress/utils/plugins/security-analytics-dashboards-plugin/constants'); +const { + NODE_API, + OPENSEARCH_DASHBOARDS, + OPENSEARCH_DASHBOARDS_URL, +} = require('../../../../cypress/utils/plugins/security-analytics-dashboards-plugin/constants'); Cypress.Commands.add('cleanUpTests', () => { cy.deleteAllCustomRules(); From 27b05a639dd1507f2913edc02434b3df9a538f24 Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Fri, 20 Jan 2023 15:26:50 -0800 Subject: [PATCH 10/36] Fixed import. Signed-off-by: AWSHurneyt --- .../plugins/security-analytics-dashboards-plugin/commands.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js index f3fe55391..684cd6b6b 100644 --- a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js +++ b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js @@ -7,7 +7,7 @@ const { NODE_API, OPENSEARCH_DASHBOARDS, OPENSEARCH_DASHBOARDS_URL, -} = require('../../../../cypress/utils/plugins/security-analytics-dashboards-plugin/constants'); +} = require('./constants'); Cypress.Commands.add('cleanUpTests', () => { cy.deleteAllCustomRules(); From 5591bc1900b0e93fee7089f9e5d189d7e552216e Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Fri, 20 Jan 2023 15:27:14 -0800 Subject: [PATCH 11/36] Fixed call to Cypress.env(). Signed-off-by: AWSHurneyt --- .../plugins/security-analytics-dashboards-plugin/constants.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js b/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js index 3700f1e29..cd4545128 100644 --- a/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js +++ b/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js @@ -14,7 +14,7 @@ export const INDICES = { export const PLUGIN_NAME = 'opensearch_security_analytics_dashboards'; export const BASE_API_PATH = '/_plugins/_security_analytics'; -export const { opensearch_dashboards: OPENSEARCH_DASHBOARDS } = Cypress.env(); +export const { opensearch_dashboards: OPENSEARCH_DASHBOARDS } = Cypress.env('openSearchUrl'); export const OPENSEARCH_DASHBOARDS_URL = `${OPENSEARCH_DASHBOARDS}/app/${PLUGIN_NAME}#`; export const NODE_API = { From 11185c277345bbad46cd82dec05fd38e93712b1b Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Fri, 20 Jan 2023 15:29:13 -0800 Subject: [PATCH 12/36] Fixed eslint errors. Signed-off-by: AWSHurneyt --- .../plugins/security-analytics-dashboards-plugin/constants.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js b/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js index cd4545128..744217499 100644 --- a/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js +++ b/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js @@ -14,7 +14,8 @@ export const INDICES = { export const PLUGIN_NAME = 'opensearch_security_analytics_dashboards'; export const BASE_API_PATH = '/_plugins/_security_analytics'; -export const { opensearch_dashboards: OPENSEARCH_DASHBOARDS } = Cypress.env('openSearchUrl'); +export const { opensearch_dashboards: OPENSEARCH_DASHBOARDS } = + Cypress.env('openSearchUrl'); export const OPENSEARCH_DASHBOARDS_URL = `${OPENSEARCH_DASHBOARDS}/app/${PLUGIN_NAME}#`; export const NODE_API = { From 2b980e1003a7b8f769b4e1667c490f9f051e0720 Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Fri, 20 Jan 2023 16:02:47 -0800 Subject: [PATCH 13/36] Fixed call to Cypress.env(). Signed-off-by: AWSHurneyt --- .../commands.js | 20 +++++++++---------- .../constants.js | 6 ++++-- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js index 684cd6b6b..12497809c 100644 --- a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js +++ b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js @@ -44,7 +44,7 @@ Cypress.Commands.add( Cypress.Commands.add('deleteAllDetectors', () => { cy.request({ method: 'DELETE', - url: `${Cypress.env('opensearch')}/.opensearch-sap-detectors-config`, + url: `${OPENSEARCH_DASHBOARDS}/.opensearch-sap-detectors-config`, failOnStatusCode: false, }); }); @@ -52,7 +52,7 @@ Cypress.Commands.add('deleteAllDetectors', () => { Cypress.Commands.add('createDetector', (detectorJSON) => { cy.request( 'POST', - `${Cypress.env('opensearch')}${NODE_API.DETECTORS_BASE}`, + `${OPENSEARCH_DASHBOARDS}${NODE_API.DETECTORS_BASE}`, detectorJSON ); }); @@ -60,7 +60,7 @@ Cypress.Commands.add('createDetector', (detectorJSON) => { Cypress.Commands.add('updateDetector', (detectorId, detectorJSON) => { cy.request( 'PUT', - `${Cypress.env('opensearch')}/${NODE_API.DETECTORS_BASE}/${detectorId}`, + `${OPENSEARCH_DASHBOARDS}/${NODE_API.DETECTORS_BASE}/${detectorId}`, detectorJSON ); }); @@ -82,7 +82,7 @@ Cypress.Commands.add('deleteDetector', (detectorName) => { }; cy.request({ method: 'POST', - url: `${Cypress.env('opensearch')}${NODE_API.DETECTORS_BASE}/_search`, + url: `${OPENSEARCH_DASHBOARDS}${NODE_API.DETECTORS_BASE}/_search`, failOnStatusCode: false, body, }).then((response) => { @@ -90,7 +90,7 @@ Cypress.Commands.add('deleteDetector', (detectorName) => { for (let hit of response.body.hits.hits) { cy.request( 'DELETE', - `${Cypress.env('opensearch')}${NODE_API.DETECTORS_BASE}/${hit._id}` + `${OPENSEARCH_DASHBOARDS}${NODE_API.DETECTORS_BASE}/${hit._id}` ); } } @@ -108,7 +108,7 @@ Cypress.Commands.add( }; cy.request({ method: 'POST', - url: `${Cypress.env('opensearch')}${NODE_API.MAPPINGS_BASE}`, + url: `${OPENSEARCH_DASHBOARDS}${NODE_API.MAPPINGS_BASE}`, body: body, }); } @@ -125,7 +125,7 @@ Cypress.Commands.add('createRule', (ruleJSON) => { Cypress.Commands.add('updateRule', (ruleId, ruleJSON) => { cy.request( 'PUT', - `${Cypress.env('opensearch')}/${NODE_API.RULES_BASE}/${ruleId}`, + `${OPENSEARCH_DASHBOARDS}/${NODE_API.RULES_BASE}/${ruleId}`, ruleJSON ); }); @@ -147,7 +147,7 @@ Cypress.Commands.add('deleteRule', (ruleName) => { }; cy.request({ method: 'POST', - url: `${Cypress.env('opensearch')}${ + url: `${OPENSEARCH_DASHBOARDS}${ NODE_API.RULES_BASE }/_search?pre_packaged=false`, failOnStatusCode: false, @@ -158,7 +158,7 @@ Cypress.Commands.add('deleteRule', (ruleName) => { if (hit._source.title === ruleName) cy.request( 'DELETE', - `${Cypress.env('opensearch')}${NODE_API.RULES_BASE}/${ + `${OPENSEARCH_DASHBOARDS}${NODE_API.RULES_BASE}/${ hit._id }?forced=true` ); @@ -170,7 +170,7 @@ Cypress.Commands.add('deleteRule', (ruleName) => { Cypress.Commands.add('deleteAllCustomRules', () => { cy.request({ method: 'DELETE', - url: `${Cypress.env('opensearch')}/.opensearch-sap-custom-rules-config`, + url: `${OPENSEARCH_DASHBOARDS}/.opensearch-sap-custom-rules-config`, failOnStatusCode: false, body: { query: { match_all: {} } }, }); diff --git a/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js b/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js index 744217499..968e0bd93 100644 --- a/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js +++ b/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js @@ -14,8 +14,10 @@ export const INDICES = { export const PLUGIN_NAME = 'opensearch_security_analytics_dashboards'; export const BASE_API_PATH = '/_plugins/_security_analytics'; -export const { opensearch_dashboards: OPENSEARCH_DASHBOARDS } = - Cypress.env('openSearchUrl'); + +// OPENSEARCH_DASHBOARDS constant differs here from in the plugin as the Cypress env is configured differently. +export const OPENSEARCH_DASHBOARDS = Cypress.env('openSearchUrl'); + export const OPENSEARCH_DASHBOARDS_URL = `${OPENSEARCH_DASHBOARDS}/app/${PLUGIN_NAME}#`; export const NODE_API = { From cc4c6b45afb4488907750417673972c83244a68b Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Fri, 20 Jan 2023 16:03:09 -0800 Subject: [PATCH 14/36] Fixed eslint errors. Signed-off-by: AWSHurneyt --- .../security-analytics-dashboards-plugin/commands.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js index 12497809c..f5ee221f6 100644 --- a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js +++ b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js @@ -147,9 +147,7 @@ Cypress.Commands.add('deleteRule', (ruleName) => { }; cy.request({ method: 'POST', - url: `${OPENSEARCH_DASHBOARDS}${ - NODE_API.RULES_BASE - }/_search?pre_packaged=false`, + url: `${OPENSEARCH_DASHBOARDS}${NODE_API.RULES_BASE}/_search?pre_packaged=false`, failOnStatusCode: false, body, }).then((response) => { @@ -158,9 +156,7 @@ Cypress.Commands.add('deleteRule', (ruleName) => { if (hit._source.title === ruleName) cy.request( 'DELETE', - `${OPENSEARCH_DASHBOARDS}${NODE_API.RULES_BASE}/${ - hit._id - }?forced=true` + `${OPENSEARCH_DASHBOARDS}${NODE_API.RULES_BASE}/${hit._id}?forced=true` ); } } From 98f89eceeea92dcfb1206a00342448adc90c74f8 Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Fri, 20 Jan 2023 16:45:15 -0800 Subject: [PATCH 15/36] Fixed call to Cypress.env(). Signed-off-by: AWSHurneyt --- .../commands.js | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js index f5ee221f6..56ffef5da 100644 --- a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js +++ b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js @@ -44,7 +44,7 @@ Cypress.Commands.add( Cypress.Commands.add('deleteAllDetectors', () => { cy.request({ method: 'DELETE', - url: `${OPENSEARCH_DASHBOARDS}/.opensearch-sap-detectors-config`, + url: `${OPENSEARCH_DASHBOARDS_URL}/.opensearch-sap-detectors-config`, failOnStatusCode: false, }); }); @@ -52,7 +52,7 @@ Cypress.Commands.add('deleteAllDetectors', () => { Cypress.Commands.add('createDetector', (detectorJSON) => { cy.request( 'POST', - `${OPENSEARCH_DASHBOARDS}${NODE_API.DETECTORS_BASE}`, + `${OPENSEARCH_DASHBOARDS_URL}${NODE_API.DETECTORS_BASE}`, detectorJSON ); }); @@ -60,7 +60,7 @@ Cypress.Commands.add('createDetector', (detectorJSON) => { Cypress.Commands.add('updateDetector', (detectorId, detectorJSON) => { cy.request( 'PUT', - `${OPENSEARCH_DASHBOARDS}/${NODE_API.DETECTORS_BASE}/${detectorId}`, + `${OPENSEARCH_DASHBOARDS_URL}/${NODE_API.DETECTORS_BASE}/${detectorId}`, detectorJSON ); }); @@ -82,7 +82,7 @@ Cypress.Commands.add('deleteDetector', (detectorName) => { }; cy.request({ method: 'POST', - url: `${OPENSEARCH_DASHBOARDS}${NODE_API.DETECTORS_BASE}/_search`, + url: `${OPENSEARCH_DASHBOARDS_URL}${NODE_API.DETECTORS_BASE}/_search`, failOnStatusCode: false, body, }).then((response) => { @@ -90,7 +90,7 @@ Cypress.Commands.add('deleteDetector', (detectorName) => { for (let hit of response.body.hits.hits) { cy.request( 'DELETE', - `${OPENSEARCH_DASHBOARDS}${NODE_API.DETECTORS_BASE}/${hit._id}` + `${OPENSEARCH_DASHBOARDS_URL}${NODE_API.DETECTORS_BASE}/${hit._id}` ); } } @@ -108,7 +108,7 @@ Cypress.Commands.add( }; cy.request({ method: 'POST', - url: `${OPENSEARCH_DASHBOARDS}${NODE_API.MAPPINGS_BASE}`, + url: `${OPENSEARCH_DASHBOARDS_URL}${NODE_API.MAPPINGS_BASE}`, body: body, }); } @@ -117,7 +117,7 @@ Cypress.Commands.add( Cypress.Commands.add('createRule', (ruleJSON) => { return cy.request({ method: 'POST', - url: `${OPENSEARCH_DASHBOARDS}${NODE_API.RULES_BASE}?category=${ruleJSON.category}`, + url: `${OPENSEARCH_DASHBOARDS_URL}${NODE_API.RULES_BASE}?category=${ruleJSON.category}`, body: JSON.stringify(ruleJSON), }); }); @@ -125,7 +125,7 @@ Cypress.Commands.add('createRule', (ruleJSON) => { Cypress.Commands.add('updateRule', (ruleId, ruleJSON) => { cy.request( 'PUT', - `${OPENSEARCH_DASHBOARDS}/${NODE_API.RULES_BASE}/${ruleId}`, + `${OPENSEARCH_DASHBOARDS_URL}/${NODE_API.RULES_BASE}/${ruleId}`, ruleJSON ); }); @@ -147,7 +147,7 @@ Cypress.Commands.add('deleteRule', (ruleName) => { }; cy.request({ method: 'POST', - url: `${OPENSEARCH_DASHBOARDS}${NODE_API.RULES_BASE}/_search?pre_packaged=false`, + url: `${OPENSEARCH_DASHBOARDS_URL}${NODE_API.RULES_BASE}/_search?pre_packaged=false`, failOnStatusCode: false, body, }).then((response) => { @@ -156,7 +156,7 @@ Cypress.Commands.add('deleteRule', (ruleName) => { if (hit._source.title === ruleName) cy.request( 'DELETE', - `${OPENSEARCH_DASHBOARDS}${NODE_API.RULES_BASE}/${hit._id}?forced=true` + `${OPENSEARCH_DASHBOARDS_URL}${NODE_API.RULES_BASE}/${hit._id}?forced=true` ); } } @@ -166,7 +166,7 @@ Cypress.Commands.add('deleteRule', (ruleName) => { Cypress.Commands.add('deleteAllCustomRules', () => { cy.request({ method: 'DELETE', - url: `${OPENSEARCH_DASHBOARDS}/.opensearch-sap-custom-rules-config`, + url: `${OPENSEARCH_DASHBOARDS_URL}/.opensearch-sap-custom-rules-config`, failOnStatusCode: false, body: { query: { match_all: {} } }, }); From 70efaeb22f96854db5bb75dfade6d079e5c79e3a Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Fri, 20 Jan 2023 16:45:59 -0800 Subject: [PATCH 16/36] Fixed eslint errors. Signed-off-by: AWSHurneyt --- .../security-analytics-dashboards-plugin/commands.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js index 56ffef5da..c19c37099 100644 --- a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js +++ b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js @@ -3,11 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -const { - NODE_API, - OPENSEARCH_DASHBOARDS, - OPENSEARCH_DASHBOARDS_URL, -} = require('./constants'); +const { NODE_API, OPENSEARCH_DASHBOARDS_URL } = require('./constants'); Cypress.Commands.add('cleanUpTests', () => { cy.deleteAllCustomRules(); From e5c947d719d0b2e434bcb7014b36ca04159d0f55 Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Fri, 20 Jan 2023 16:54:25 -0800 Subject: [PATCH 17/36] Fixed call to Cypress.env(). Signed-off-by: AWSHurneyt --- .../commands.js | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js index c19c37099..f5ee221f6 100644 --- a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js +++ b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js @@ -3,7 +3,11 @@ * SPDX-License-Identifier: Apache-2.0 */ -const { NODE_API, OPENSEARCH_DASHBOARDS_URL } = require('./constants'); +const { + NODE_API, + OPENSEARCH_DASHBOARDS, + OPENSEARCH_DASHBOARDS_URL, +} = require('./constants'); Cypress.Commands.add('cleanUpTests', () => { cy.deleteAllCustomRules(); @@ -40,7 +44,7 @@ Cypress.Commands.add( Cypress.Commands.add('deleteAllDetectors', () => { cy.request({ method: 'DELETE', - url: `${OPENSEARCH_DASHBOARDS_URL}/.opensearch-sap-detectors-config`, + url: `${OPENSEARCH_DASHBOARDS}/.opensearch-sap-detectors-config`, failOnStatusCode: false, }); }); @@ -48,7 +52,7 @@ Cypress.Commands.add('deleteAllDetectors', () => { Cypress.Commands.add('createDetector', (detectorJSON) => { cy.request( 'POST', - `${OPENSEARCH_DASHBOARDS_URL}${NODE_API.DETECTORS_BASE}`, + `${OPENSEARCH_DASHBOARDS}${NODE_API.DETECTORS_BASE}`, detectorJSON ); }); @@ -56,7 +60,7 @@ Cypress.Commands.add('createDetector', (detectorJSON) => { Cypress.Commands.add('updateDetector', (detectorId, detectorJSON) => { cy.request( 'PUT', - `${OPENSEARCH_DASHBOARDS_URL}/${NODE_API.DETECTORS_BASE}/${detectorId}`, + `${OPENSEARCH_DASHBOARDS}/${NODE_API.DETECTORS_BASE}/${detectorId}`, detectorJSON ); }); @@ -78,7 +82,7 @@ Cypress.Commands.add('deleteDetector', (detectorName) => { }; cy.request({ method: 'POST', - url: `${OPENSEARCH_DASHBOARDS_URL}${NODE_API.DETECTORS_BASE}/_search`, + url: `${OPENSEARCH_DASHBOARDS}${NODE_API.DETECTORS_BASE}/_search`, failOnStatusCode: false, body, }).then((response) => { @@ -86,7 +90,7 @@ Cypress.Commands.add('deleteDetector', (detectorName) => { for (let hit of response.body.hits.hits) { cy.request( 'DELETE', - `${OPENSEARCH_DASHBOARDS_URL}${NODE_API.DETECTORS_BASE}/${hit._id}` + `${OPENSEARCH_DASHBOARDS}${NODE_API.DETECTORS_BASE}/${hit._id}` ); } } @@ -104,7 +108,7 @@ Cypress.Commands.add( }; cy.request({ method: 'POST', - url: `${OPENSEARCH_DASHBOARDS_URL}${NODE_API.MAPPINGS_BASE}`, + url: `${OPENSEARCH_DASHBOARDS}${NODE_API.MAPPINGS_BASE}`, body: body, }); } @@ -113,7 +117,7 @@ Cypress.Commands.add( Cypress.Commands.add('createRule', (ruleJSON) => { return cy.request({ method: 'POST', - url: `${OPENSEARCH_DASHBOARDS_URL}${NODE_API.RULES_BASE}?category=${ruleJSON.category}`, + url: `${OPENSEARCH_DASHBOARDS}${NODE_API.RULES_BASE}?category=${ruleJSON.category}`, body: JSON.stringify(ruleJSON), }); }); @@ -121,7 +125,7 @@ Cypress.Commands.add('createRule', (ruleJSON) => { Cypress.Commands.add('updateRule', (ruleId, ruleJSON) => { cy.request( 'PUT', - `${OPENSEARCH_DASHBOARDS_URL}/${NODE_API.RULES_BASE}/${ruleId}`, + `${OPENSEARCH_DASHBOARDS}/${NODE_API.RULES_BASE}/${ruleId}`, ruleJSON ); }); @@ -143,7 +147,7 @@ Cypress.Commands.add('deleteRule', (ruleName) => { }; cy.request({ method: 'POST', - url: `${OPENSEARCH_DASHBOARDS_URL}${NODE_API.RULES_BASE}/_search?pre_packaged=false`, + url: `${OPENSEARCH_DASHBOARDS}${NODE_API.RULES_BASE}/_search?pre_packaged=false`, failOnStatusCode: false, body, }).then((response) => { @@ -152,7 +156,7 @@ Cypress.Commands.add('deleteRule', (ruleName) => { if (hit._source.title === ruleName) cy.request( 'DELETE', - `${OPENSEARCH_DASHBOARDS_URL}${NODE_API.RULES_BASE}/${hit._id}?forced=true` + `${OPENSEARCH_DASHBOARDS}${NODE_API.RULES_BASE}/${hit._id}?forced=true` ); } } @@ -162,7 +166,7 @@ Cypress.Commands.add('deleteRule', (ruleName) => { Cypress.Commands.add('deleteAllCustomRules', () => { cy.request({ method: 'DELETE', - url: `${OPENSEARCH_DASHBOARDS_URL}/.opensearch-sap-custom-rules-config`, + url: `${OPENSEARCH_DASHBOARDS}/.opensearch-sap-custom-rules-config`, failOnStatusCode: false, body: { query: { match_all: {} } }, }); From 6d9e79d095d5a07b216d4c8306c0b86d619ce30f Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Fri, 20 Jan 2023 17:52:18 -0800 Subject: [PATCH 18/36] Fixed call to Cypress.env(). Signed-off-by: AWSHurneyt --- .../plugins/security-analytics-dashboards-plugin/constants.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js b/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js index 968e0bd93..7cf47892d 100644 --- a/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js +++ b/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js @@ -3,6 +3,8 @@ * SPDX-License-Identifier: Apache-2.0 */ +import { BASE_PATH } from '../../../../cypress/utils/base_constants'; + export const TWENTY_SECONDS_TIMEOUT = { timeout: 20000 }; export const DETECTOR_TRIGGER_TIMEOUT = 65000; @@ -16,7 +18,7 @@ export const PLUGIN_NAME = 'opensearch_security_analytics_dashboards'; export const BASE_API_PATH = '/_plugins/_security_analytics'; // OPENSEARCH_DASHBOARDS constant differs here from in the plugin as the Cypress env is configured differently. -export const OPENSEARCH_DASHBOARDS = Cypress.env('openSearchUrl'); +export const OPENSEARCH_DASHBOARDS = BASE_PATH; export const OPENSEARCH_DASHBOARDS_URL = `${OPENSEARCH_DASHBOARDS}/app/${PLUGIN_NAME}#`; From 4ace5d78da39dc8df0f7f2a77a98053b09fa2ef3 Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Mon, 30 Jan 2023 15:44:48 -0800 Subject: [PATCH 19/36] Fixed expected URL. Signed-off-by: AWSHurneyt --- .../plugins/security-analytics-dashboards-plugin/constants.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js b/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js index 7cf47892d..28a8946a9 100644 --- a/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js +++ b/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js @@ -20,7 +20,9 @@ export const BASE_API_PATH = '/_plugins/_security_analytics'; // OPENSEARCH_DASHBOARDS constant differs here from in the plugin as the Cypress env is configured differently. export const OPENSEARCH_DASHBOARDS = BASE_PATH; -export const OPENSEARCH_DASHBOARDS_URL = `${OPENSEARCH_DASHBOARDS}/app/${PLUGIN_NAME}#`; +export const OPENSEARCH_DASHBOARDS_URL = Cypress.env('SECURITY_ENABLED') + ? `${OPENSEARCH_DASHBOARDS}/app/${PLUGIN_NAME}?security_tenant=private#` + : `${OPENSEARCH_DASHBOARDS}/app/${PLUGIN_NAME}#`; export const NODE_API = { DETECTORS_BASE: `${BASE_API_PATH}/detectors`, From e5345e7a4c10c38f4d125aaef5bd1e72aca2cc09 Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Mon, 30 Jan 2023 16:15:20 -0800 Subject: [PATCH 20/36] Fixed waitForPageLoad helper method. Signed-off-by: AWSHurneyt --- .../plugins/security-analytics-dashboards-plugin/commands.js | 2 +- .../plugins/security-analytics-dashboards-plugin/constants.js | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js index f5ee221f6..c0048a587 100644 --- a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js +++ b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js @@ -34,7 +34,7 @@ Cypress.Commands.add( message: `Wait for url: ${fullUrl} to be loaded.`, }); cy.url({ timeout: timeout }) - .should('include', fullUrl) + .should('match', new RegExp(`(.*)#/${url}`)) .then(() => { contains && cy.contains(contains); }); diff --git a/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js b/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js index 28a8946a9..7cf47892d 100644 --- a/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js +++ b/cypress/utils/plugins/security-analytics-dashboards-plugin/constants.js @@ -20,9 +20,7 @@ export const BASE_API_PATH = '/_plugins/_security_analytics'; // OPENSEARCH_DASHBOARDS constant differs here from in the plugin as the Cypress env is configured differently. export const OPENSEARCH_DASHBOARDS = BASE_PATH; -export const OPENSEARCH_DASHBOARDS_URL = Cypress.env('SECURITY_ENABLED') - ? `${OPENSEARCH_DASHBOARDS}/app/${PLUGIN_NAME}?security_tenant=private#` - : `${OPENSEARCH_DASHBOARDS}/app/${PLUGIN_NAME}#`; +export const OPENSEARCH_DASHBOARDS_URL = `${OPENSEARCH_DASHBOARDS}/app/${PLUGIN_NAME}#`; export const NODE_API = { DETECTORS_BASE: `${BASE_API_PATH}/detectors`, From ae6a78c602f03253010e71c2bd83f7f7a4896936 Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Mon, 30 Jan 2023 18:18:43 -0800 Subject: [PATCH 21/36] Replaced call to realPress. Signed-off-by: AWSHurneyt --- .../plugins/security-analytics-dashboards-plugin/commands.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js index c0048a587..8c1173d7c 100644 --- a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js +++ b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js @@ -21,9 +21,7 @@ Cypress.Commands.add('getTableFirstRow', (selector) => { }); Cypress.Commands.add('triggerSearchField', (placeholder, text) => { - cy.get(`[placeholder="${placeholder}"]`) - .type(`{selectall}${text}`) - .realPress('Enter'); + cy.get(`[placeholder="${placeholder}"]`).type(`{selectall}${text}{enter}`); }); Cypress.Commands.add( From 578df55eb48a5ee26f5759a85f4dcae80acd5404 Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Tue, 7 Feb 2023 17:45:21 -0800 Subject: [PATCH 22/36] Fixed failing tests. Signed-off-by: AWSHurneyt --- .../2_rules.spec.js | 9 +-- .../3_alerts.spec.js | 11 ++- .../4_findings.spec.js | 17 +--- .../5_integrations.spec.js | 12 +-- .../alerting-dashboards-plugin/commands.js | 2 +- .../commands.js | 79 +++++++++++++++++-- 6 files changed, 88 insertions(+), 42 deletions(-) diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js index 7b554c838..c331a60d7 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js @@ -139,8 +139,6 @@ describe('Rules', () => { contains: 'Rules', }); - cy.wait('@getRules'); - // Search for the rule cy.triggerSearchField('Search rules', SAMPLE_RULE.name); @@ -243,10 +241,6 @@ describe('Rules', () => { }); it('...can be deleted', () => { - cy.intercept({ - url: '/rules', - }).as('deleteRule'); - cy.triggerSearchField('Search rules', SAMPLE_RULE.name); // Click the rule link to open the details flyout @@ -269,10 +263,9 @@ describe('Rules', () => { cy.get('.euiButton').contains('Delete').click(); }); - cy.wait('@deleteRule'); - // Search for sample_detector, presumably deleted cy.triggerSearchField('Search rules', SAMPLE_RULE.name); + // Click the rule link to open the details flyout cy.get('tbody').contains(SAMPLE_RULE.name).should('not.exist'); }); diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js index e2a7def25..1b2bc9e91 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js @@ -46,7 +46,7 @@ const now = new Date(Date.now()); const month = now.getMonth() + 1 < 10 ? `0${now.getMonth() + 1}` : `${now.getMonth() + 1}`; const day = now.getDate() < 10 ? `0${now.getDate()}` : `${now.getDate()}`; -const year = `${now.getFullYear()}`.substr(1); +const year = `${now.getFullYear()}`.substr(2); const date = `${month}/${day}/${year}`; const docCount = 4; @@ -377,6 +377,7 @@ describe('Alerts', () => { cy.get('[class="euiFilterSelect__items"]').within(() => { cy.contains('Acknowledged').click({ force: true }); }); + cy.get('[data-text="Status"]').click({ force: true }); // Confirm there is an "Acknowledged" alert cy.get('tbody > tr').should(($tr) => { @@ -385,10 +386,11 @@ describe('Alerts', () => { }); // Filter the table to show only "Active" alerts - cy.get('[data-text="Status"]'); + cy.get('[data-text="Status"]').click({ force: true }); cy.get('[class="euiFilterSelect__items"]').within(() => { cy.contains('Acknowledged').click({ force: true }); }); + cy.get('[data-text="Status"]').click({ force: true }); // Confirm there are now 2 "Acknowledged" alerts cy.get('tbody > tr') @@ -403,6 +405,7 @@ describe('Alerts', () => { cy.get('[class="euiFilterSelect__items"]').within(() => { cy.contains('Active').click({ force: true }); }); + cy.get('[data-text="Status"]').click({ force: true }); cy.get('tbody > tr') .filter(`:contains(${testDetectorAlertCondition})`) @@ -420,11 +423,12 @@ describe('Alerts', () => { .should('have.length', 2); // Filter the table to show only "Acknowledged" alerts - cy.get('[data-text="Status"]'); + cy.get('[data-text="Status"]').click({ force: true }); cy.get('[class="euiFilterSelect__items"]').within(() => { cy.contains('Active').click({ force: true }); cy.contains('Acknowledged').click({ force: true }); }); + cy.get('[data-text="Status"]').click({ force: true }); // Confirm there are now 3 "Acknowledged" alerts cy.get('tbody > tr') @@ -438,6 +442,7 @@ describe('Alerts', () => { cy.get('[class="euiFilterSelect__items"]').within(() => { cy.contains('Active').click({ force: true }); }); + cy.get('[data-text="Status"]').click({ force: true }); cy.get('tbody > tr') .first() diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js index 81a9ad8db..289f34f20 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js @@ -157,19 +157,11 @@ describe('Findings', () => { // filter table to show only sample_detector findings cy.triggerSearchField('Search threat detectors', 'sample_detector'); - // intercept detectors and rules requests - cy.intercept('detectors/_search').as('getDetector'); - cy.intercept('rules/_search?prePackaged=true').as('getPrePackagedRules'); - cy.intercept('rules/_search?prePackaged=false').as('getRules'); - // Click on detector to be removed cy.contains('sample_detector').click({ force: true }); - cy.waitForPageLoad('detector-details', { - contains: sample_detector.name, - }); - // wait for detector details to load before continuing - cy.wait(['@getDetector', '@getPrePackagedRules', '@getRules']).then(() => { + // Wait for detector details to load before continuing + cy.contains('Detector details').then(() => { // Click "Actions" button, the click "Delete" cy.get('button.euiButton') .contains('Actions') @@ -180,11 +172,8 @@ describe('Findings', () => { .contains('Delete') .click({ force: true }); - // Search for sample_detector, presumably deleted - cy.triggerSearchField('Search threat detectors', 'sample_detector'); - // Confirm sample_detector no longer exists - cy.contains('There are no existing detectors.'); + cy.contains('sample_detector').should('not.exist'); }); }); }); diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js index b6c31fa12..b4fc2a56e 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js @@ -57,16 +57,8 @@ describe('Integration tests', () => { ).then(() => cy.createDetector(dns_detector_data)); // Ingest docs - cy.request( - 'POST', - `${Cypress.env('opensearch')}/${indexName}/_doc/101`, - add_windows_index_data - ); - cy.request( - 'POST', - `${Cypress.env('opensearch')}/${dnsName}/_doc/101`, - add_dns_index_data - ); + cy.insertDocumentToIndex(indexName, '101', add_windows_index_data); + cy.insertDocumentToIndex(dnsName, '101', add_dns_index_data); // Wait for detector interval to pass cy.wait(DETECTOR_TRIGGER_TIMEOUT); diff --git a/cypress/utils/plugins/alerting-dashboards-plugin/commands.js b/cypress/utils/plugins/alerting-dashboards-plugin/commands.js index 16174b455..962566271 100644 --- a/cypress/utils/plugins/alerting-dashboards-plugin/commands.js +++ b/cypress/utils/plugins/alerting-dashboards-plugin/commands.js @@ -121,7 +121,7 @@ Cypress.Commands.add( 'insertDocumentToIndex', (indexName, documentId, documentBody) => { cy.request( - 'PUT', + 'POST', `${Cypress.env('openSearchUrl')}/${indexName}/_doc/${documentId}`, documentBody ); diff --git a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js index 8c1173d7c..53cc6d69e 100644 --- a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js +++ b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js @@ -21,7 +21,11 @@ Cypress.Commands.add('getTableFirstRow', (selector) => { }); Cypress.Commands.add('triggerSearchField', (placeholder, text) => { - cy.get(`[placeholder="${placeholder}"]`).type(`{selectall}${text}{enter}`); + cy.get(`input[type="search"]`) + .first() + .focus() + .type(`{selectall}${text}{enter}`) + .trigger('search'); }); Cypress.Commands.add( @@ -48,11 +52,14 @@ Cypress.Commands.add('deleteAllDetectors', () => { }); Cypress.Commands.add('createDetector', (detectorJSON) => { - cy.request( - 'POST', - `${OPENSEARCH_DASHBOARDS}${NODE_API.DETECTORS_BASE}`, - detectorJSON - ); + cy.request({ + method: 'POST', + url: `${OPENSEARCH_DASHBOARDS}${NODE_API.DETECTORS_BASE}`, + body: detectorJSON, + headers: { + 'osd-xsrf': true, + }, + }); }); Cypress.Commands.add('updateDetector', (detectorId, detectorJSON) => { @@ -108,6 +115,9 @@ Cypress.Commands.add( method: 'POST', url: `${OPENSEARCH_DASHBOARDS}${NODE_API.MAPPINGS_BASE}`, body: body, + headers: { + 'osd-xsrf': true, + }, }); } ); @@ -117,6 +127,9 @@ Cypress.Commands.add('createRule', (ruleJSON) => { method: 'POST', url: `${OPENSEARCH_DASHBOARDS}${NODE_API.RULES_BASE}?category=${ruleJSON.category}`, body: JSON.stringify(ruleJSON), + headers: { + 'osd-xsrf': true, + }, }); }); @@ -148,6 +161,9 @@ Cypress.Commands.add('deleteRule', (ruleName) => { url: `${OPENSEARCH_DASHBOARDS}${NODE_API.RULES_BASE}/_search?pre_packaged=false`, failOnStatusCode: false, body, + headers: { + 'osd-xsrf': true, + }, }).then((response) => { if (response.status === 200) { for (let hit of response.body.hits.hits) { @@ -169,3 +185,54 @@ Cypress.Commands.add('deleteAllCustomRules', () => { body: { query: { match_all: {} } }, }); }); + +Cypress.Commands.add('updateDetector', (detectorId, detectorJSON) => { + cy.request( + 'PUT', + `${Cypress.env('opensearch')}/${NODE_API.DETECTORS_BASE}/${detectorId}`, + detectorJSON + ); +}); + +Cypress.Commands.add('deleteAllDetectors', () => { + cy.request({ + method: 'DELETE', + url: `${Cypress.env('opensearch')}/.opensearch-sap-detectors-config`, + failOnStatusCode: false, + }).as('deleteAllDetectors'); +}); + +Cypress.Commands.add( + 'ospSearch', + { + prevSubject: true, + }, + (subject, text) => { + return cy.get(subject).clear().ospType(text).realPress('Enter'); + } +); + +Cypress.Commands.add( + 'ospClear', + { + prevSubject: true, + }, + (subject) => { + return cy + .get(subject) + .wait(100) + .type('{selectall}{backspace}') + .clear({ force: true }) + .invoke('val', ''); + } +); + +Cypress.Commands.add( + 'ospType', + { + prevSubject: true, + }, + (subject, text) => { + return cy.get(subject).wait(10).focus().realType(text); + } +); From 957abb270c7eb19e900919959d346bbafe0eb188 Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Tue, 7 Feb 2023 17:52:46 -0800 Subject: [PATCH 23/36] Replaced existing test file. Signed-off-by: AWSHurneyt --- .../plugins/security-analytics-dashboards-plugin/rules_spec.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 cypress/integration/plugins/security-analytics-dashboards-plugin/rules_spec.js diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/rules_spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/rules_spec.js deleted file mode 100644 index e69de29bb..000000000 From eecca0c292238fae33e091f526f57afa7d9ea4b0 Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Tue, 7 Feb 2023 18:15:48 -0800 Subject: [PATCH 24/36] Fixed es lint errors. Signed-off-by: AWSHurneyt --- cypress/support/index.js | 2 +- cypress/utils/constants.js | 2 +- .../plugins/index-management-dashboards-plugin/commands.js | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/cypress/support/index.js b/cypress/support/index.js index 52ddcfe1d..820eab096 100644 --- a/cypress/support/index.js +++ b/cypress/support/index.js @@ -27,7 +27,7 @@ import '../utils/plugins/anomaly-detection-dashboards-plugin/commands'; import '../utils/plugins/security/commands'; import '../utils/plugins/security-dashboards-plugin/commands'; import '../utils/plugins/alerting-dashboards-plugin/commands'; -import '../utils/plugins/security-analytics-dashboards-plugin/commands' +import '../utils/plugins/security-analytics-dashboards-plugin/commands'; // Alternatively you can use CommonJS syntax: // require('./commands') diff --git a/cypress/utils/constants.js b/cypress/utils/constants.js index afa8afbe2..cba77e578 100644 --- a/cypress/utils/constants.js +++ b/cypress/utils/constants.js @@ -14,4 +14,4 @@ export * from './plugins/query-workbench-dashboards/constants'; export * from './plugins/security/constants'; export * from './plugins/notifications-dashboards/constants'; export * from './plugins/security-dashboards-plugin/constants'; -export * from './plugins/security-analytics-dashboards-plugin/constants' +export * from './plugins/security-analytics-dashboards-plugin/constants'; diff --git a/cypress/utils/plugins/index-management-dashboards-plugin/commands.js b/cypress/utils/plugins/index-management-dashboards-plugin/commands.js index 388e71f9c..3f4ef9999 100644 --- a/cypress/utils/plugins/index-management-dashboards-plugin/commands.js +++ b/cypress/utils/plugins/index-management-dashboards-plugin/commands.js @@ -144,7 +144,6 @@ Cypress.Commands.add('addIndexAlias', (alias, index) => { }); }); - Cypress.Commands.add('removeIndexAlias', (alias) => { cy.request({ url: `${Cypress.env('openSearchUrl')}/_aliases`, From 7ee4c28b4b700254886513fec1280f02fc779473 Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Tue, 7 Feb 2023 18:24:51 -0800 Subject: [PATCH 25/36] Adjusted security-analytics-release-e2e-workflow to run cypress tests for PRs to all branches. Signed-off-by: AWSHurneyt --- .../workflows/security-analytics-release-e2e-workflow.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/security-analytics-release-e2e-workflow.yml b/.github/workflows/security-analytics-release-e2e-workflow.yml index dd708bb75..810ca280f 100644 --- a/.github/workflows/security-analytics-release-e2e-workflow.yml +++ b/.github/workflows/security-analytics-release-e2e-workflow.yml @@ -1,10 +1,7 @@ name: Security Analytics Release tests workflow in Bundled OpenSearch Dashboards on: pull_request: - branches: - - main - - dev-* - - 2.x + branches: [ '**' ] jobs: changes: runs-on: ubuntu-latest From e6d55d1a43952e9edb5316d2bd448e41747ef252 Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Wed, 8 Feb 2023 10:37:08 -0800 Subject: [PATCH 26/36] Refactored security analytics cypress tests to no longer use the custom waitForPageLoad command. Signed-off-by: AWSHurneyt --- .../1_detectors.spec.js | 50 +++++++------------ .../2_rules.spec.js | 8 +-- .../3_alerts.spec.js | 8 +-- .../4_findings.spec.js | 8 +-- .../5_integrations.spec.js | 2 +- .../commands.js | 15 ------ 6 files changed, 24 insertions(+), 67 deletions(-) diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js index d6f65f2cc..33b8f59cb 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js @@ -49,9 +49,7 @@ describe('Detectors', () => { cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/detectors`); // Check that correct page is showing - cy.waitForPageLoad('detectors', { - contains: 'Threat detectors', - }); + cy.contains('Threat detectors'); }); it('...can be created', () => { @@ -59,9 +57,7 @@ describe('Detectors', () => { cy.contains('Create detector').click({ force: true }); // Check to ensure process started - cy.waitForPageLoad('create-detector', { - contains: 'Define detector', - }); + cy.contains('Define detector'); // Enter a name for the detector in the appropriate input cy.get(`input[placeholder="Enter a name for the detector."]`).type( @@ -169,9 +165,8 @@ describe('Detectors', () => { // Create the detector cy.get('button').contains('Create').click({ force: true }); - cy.waitForPageLoad('detector-details', { - contains: detectorName, - }); + cy.contains('Detector details'); + cy.contains(detectorName); // Confirm detector active cy.contains(detectorName); @@ -190,9 +185,8 @@ describe('Detectors', () => { it('...basic details can be edited', () => { // Click on detector name cy.contains(detectorName).click({ force: true }); - cy.waitForPageLoad('detector-details', { - contains: detectorName, - }); + cy.contains('Detector details'); + cy.contains(detectorName); // Click "Edit" button in detector details cy.get(`[data-test-subj="edit-detector-basic-details"]`).click({ @@ -200,9 +194,7 @@ describe('Detectors', () => { }); // Confirm arrival at "Edit detector details" page - cy.waitForPageLoad('edit-detector-details', { - contains: 'Edit detector details', - }); + cy.contains('Edit detector details'); // Change detector name cy.get(`[data-test-subj="define-detector-detector-name"]`).type('_edited'); @@ -229,9 +221,8 @@ describe('Detectors', () => { }); // Confirm taken to detector details page - cy.waitForPageLoad('detector-details', { - contains: detectorName, - }); + cy.contains('Detector details'); + cy.contains(detectorName); // Verify edits are applied cy.contains('test detector_edited'); @@ -242,15 +233,12 @@ describe('Detectors', () => { it('...rules can be edited', () => { // Ensure start on main detectors page - cy.waitForPageLoad('detectors', { - contains: 'Threat detectors', - }); + cy.contains('Threat detectors'); // Click on detector name cy.contains(detectorName).click({ force: true }); - cy.waitForPageLoad('detector-details', { - contains: detectorName, - }); + cy.contains('Detector details'); + cy.contains(detectorName); // Confirm number of rules before edit cy.contains('Active rules (1)'); @@ -286,9 +274,7 @@ describe('Detectors', () => { cy.get(`[data-test-subj="edit-detector-rules"]`).click({ force: true }); // Confirm arrival on "Edit detector rules" page - cy.waitForPageLoad('edit-detector-rules', { - contains: 'Edit detector rules', - }); + cy.contains('Edit detector rules'); // Search for specific rule cy.triggerSearchField('Search...', 'USB'); @@ -303,9 +289,8 @@ describe('Detectors', () => { cy.get(`[data-test-subj="save-detector-rules-edits"]`).click({ force: true, }); - cy.waitForPageLoad('detector-details', { - contains: detectorName, - }); + cy.contains('Detector details'); + cy.contains(detectorName); // Confirm 1 rule has been added to detector cy.contains('Active rules (1)'); @@ -316,9 +301,8 @@ describe('Detectors', () => { cy.contains('test detector_edited').click({ force: true }); // Confirm page - cy.waitForPageLoad('detector-details', { - contains: 'Detector details', - }); + cy.contains('Detector details'); + cy.contains(detectorName); // Click "Actions" button, the click "Delete" cy.contains('Actions').click({ force: true }); diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js index c331a60d7..fed95485b 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js @@ -64,9 +64,7 @@ describe('Rules', () => { cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/rules`); // Check that correct page is showing - cy.waitForPageLoad('rules', { - contains: 'Rules', - }); + cy.contains('Rules'); }); it('...can be created', () => { @@ -135,9 +133,7 @@ describe('Rules', () => { force: true, }); - cy.waitForPageLoad('rules', { - contains: 'Rules', - }); + cy.contains('Rules'); // Search for the rule cy.triggerSearchField('Search rules', SAMPLE_RULE.name); diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js index 1b2bc9e91..25d01331c 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/3_alerts.spec.js @@ -75,9 +75,7 @@ describe('Alerts', () => { cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/detectors`); // Check that correct page is showing - cy.waitForPageLoad('detectors', { - contains: 'Threat detectors', - }); + cy.contains('Threat detectors'); // Filter table to only show the test detector cy.get(`input[type="search"]`).type(`${testDetector.name}{enter}`); @@ -102,9 +100,7 @@ describe('Alerts', () => { cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/alerts`); // Wait for page to load - cy.waitForPageLoad('alerts', { - contains: 'Security alerts', - }); + cy.contains('Security alerts'); // Filter table to only show alerts for the test detector cy.get(`input[type="search"]`).type(`${testDetector.name}{enter}`); diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js index 289f34f20..948d4c07c 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/4_findings.spec.js @@ -39,9 +39,7 @@ describe('Findings', () => { cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/findings`); // Wait for page to load - cy.waitForPageLoad('findings', { - contains: 'Findings', - }); + cy.contains('Findings'); }); it('displays findings based on recently ingested data', () => { @@ -150,9 +148,7 @@ describe('Findings', () => { it('...can delete detector', () => { // Visit Detectors page cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/detectors`); - cy.waitForPageLoad('detectors', { - contains: 'Threat detectors', - }); + cy.contains('Threat detectors'); // filter table to show only sample_detector findings cy.triggerSearchField('Search threat detectors', 'sample_detector'); diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js index b4fc2a56e..cf4914c6f 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/5_integrations.spec.js @@ -69,7 +69,7 @@ describe('Integration tests', () => { cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/detectors`); // Wait for page to load - cy.waitForPageLoad('detectors', 'Threat detectors'); + cy.contains('Threat detectors'); }); it('...can navigate to findings page', () => { diff --git a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js index 53cc6d69e..8b7cc3729 100644 --- a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js +++ b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js @@ -28,21 +28,6 @@ Cypress.Commands.add('triggerSearchField', (placeholder, text) => { .trigger('search'); }); -Cypress.Commands.add( - '' + 'waitForPageLoad', - (url, { timeout = 10000, contains = null }) => { - const fullUrl = `${OPENSEARCH_DASHBOARDS_URL}/${url}`; - Cypress.log({ - message: `Wait for url: ${fullUrl} to be loaded.`, - }); - cy.url({ timeout: timeout }) - .should('match', new RegExp(`(.*)#/${url}`)) - .then(() => { - contains && cy.contains(contains); - }); - } -); - Cypress.Commands.add('deleteAllDetectors', () => { cy.request({ method: 'DELETE', From 6fd92ae83f37714f42c56a91522359fe86db3477 Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Wed, 8 Feb 2023 11:29:39 -0800 Subject: [PATCH 27/36] Removed unused import. Signed-off-by: AWSHurneyt --- .../security-analytics-dashboards-plugin/commands.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js index 8b7cc3729..d9a0c1fc8 100644 --- a/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js +++ b/cypress/utils/plugins/security-analytics-dashboards-plugin/commands.js @@ -3,11 +3,7 @@ * SPDX-License-Identifier: Apache-2.0 */ -const { - NODE_API, - OPENSEARCH_DASHBOARDS, - OPENSEARCH_DASHBOARDS_URL, -} = require('./constants'); +const { NODE_API, OPENSEARCH_DASHBOARDS } = require('./constants'); Cypress.Commands.add('cleanUpTests', () => { cy.deleteAllCustomRules(); From 618d2e54863f3ca1472dc3c89e2deca762b20d24 Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Wed, 8 Feb 2023 11:30:09 -0800 Subject: [PATCH 28/36] Refactored failing tests. Signed-off-by: AWSHurneyt --- .../1_detectors.spec.js | 6 ++++++ .../security-analytics-dashboards-plugin/2_rules.spec.js | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js index 33b8f59cb..681d09881 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js @@ -41,6 +41,12 @@ describe('Detectors', () => { // Create test index cy.createIndex(indexName, null, sample_index_settings); + // Visit Detectors page + cy.visit(`${OPENSEARCH_DASHBOARDS_URL}/detectors`); + + // Check that correct page is showing + cy.contains('Threat detectors'); + cy.contains(detectorName).should('not.exist'); }); diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js index fed95485b..3b578ac3f 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js @@ -91,7 +91,10 @@ describe('Rules', () => { // Enter the tags SAMPLE_RULE.tags.forEach((tag) => - cy.get('[data-test-subj="rule_tags_dropdown"]').type(`${tag}{enter}{esc}`) + cy + .get('[data-test-subj="rule_tags_dropdown"]') + .type(`${tag}{enter}{esc}`) + .blur() ); // Enter the reference From 5c9bf2d29e8cb92f4ef0032a66d6215c7f6d7d2e Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Wed, 8 Feb 2023 14:37:39 -0800 Subject: [PATCH 29/36] Refactored failing tests. Signed-off-by: AWSHurneyt --- .../1_detectors.spec.js | 4 +++- .../security-analytics-dashboards-plugin/2_rules.spec.js | 7 ++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js index 681d09881..a4245e444 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js @@ -203,7 +203,9 @@ describe('Detectors', () => { cy.contains('Edit detector details'); // Change detector name - cy.get(`[data-test-subj="define-detector-detector-name"]`).type('_edited'); + cy.get(`[data-test-subj="define-detector-detector-name"]`) + .clear() + .type(`${detectorName}_edited`); // Change detector description cy.get(`[data-test-subj="define-detector-detector-description"]`).type( diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js index 3b578ac3f..67acdf78a 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/2_rules.spec.js @@ -86,15 +86,12 @@ describe('Rules', () => { // Enter the severity cy.get('[data-test-subj="rule_severity_dropdown"]').type( - SAMPLE_RULE.severity + `${SAMPLE_RULE.severity}{downarrow}{enter}` ); // Enter the tags SAMPLE_RULE.tags.forEach((tag) => - cy - .get('[data-test-subj="rule_tags_dropdown"]') - .type(`${tag}{enter}{esc}`) - .blur() + cy.get('[data-test-subj="rule_tags_dropdown"]').type(`${tag}{enter}{esc}`) ); // Enter the reference From e096a8de3952581eb1576681afd448e6734eddf5 Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Wed, 8 Feb 2023 14:56:29 -0800 Subject: [PATCH 30/36] Refactored failing tests. Signed-off-by: AWSHurneyt --- .../security-analytics-dashboards-plugin/1_detectors.spec.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js b/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js index a4245e444..72e08bcab 100644 --- a/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js +++ b/cypress/integration/plugins/security-analytics-dashboards-plugin/1_detectors.spec.js @@ -255,10 +255,7 @@ describe('Detectors', () => { cy.get(`[data-test-subj="edit-detector-rules"]`).click({ force: true }); // Confirm arrival on "Edit detector rules" page - cy.url().should( - 'include', - 'http://localhost:5601/app/opensearch_security_analytics_dashboards#/edit-detector-rules' - ); + cy.contains('Edit detector rules'); // Search for specific rule cy.triggerSearchField('Search...', 'USB Device'); From 2fd21d245f2f5976b36d8cb1cd201059f9506e68 Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Thu, 9 Feb 2023 11:40:36 -0800 Subject: [PATCH 31/36] Fixed failing ISM cypress test. Signed-off-by: AWSHurneyt --- .../index-management-dashboards-plugin/aliases.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cypress/integration/plugins/index-management-dashboards-plugin/aliases.js b/cypress/integration/plugins/index-management-dashboards-plugin/aliases.js index 73124ecb8..e91866987 100644 --- a/cypress/integration/plugins/index-management-dashboards-plugin/aliases.js +++ b/cypress/integration/plugins/index-management-dashboards-plugin/aliases.js @@ -119,12 +119,14 @@ describe('Aliases', () => { 'not.be.disabled' ); // click to delete - cy.get('[data-test-subj="deleteConfirmButton"]').click(); + cy.get('[data-test-subj="deleteConfirmButton"]', { + timeout: 20000, + }).click({ force: true }); // the alias should not exist cy.wait(500); - cy.get(`#_selection_column_${SAMPLE_ALIAS_PREFIX}-0-checkbox`).should( - 'not.exist' - ); + cy.get(`#_selection_column_${SAMPLE_ALIAS_PREFIX}-0-checkbox`, { + timeout: 20000, + }).should('not.exist'); }); }); From c9ad6eb259f6e1819383fc87786768faea1a50c8 Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Thu, 9 Feb 2023 13:55:06 -0800 Subject: [PATCH 32/36] Fixed failing ISM cypress test. Signed-off-by: AWSHurneyt --- .../index-management-dashboards-plugin/aliases.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/cypress/integration/plugins/index-management-dashboards-plugin/aliases.js b/cypress/integration/plugins/index-management-dashboards-plugin/aliases.js index e91866987..ad4931380 100644 --- a/cypress/integration/plugins/index-management-dashboards-plugin/aliases.js +++ b/cypress/integration/plugins/index-management-dashboards-plugin/aliases.js @@ -118,15 +118,14 @@ describe('Aliases', () => { cy.get('[data-test-subj="deleteConfirmButton"]').should( 'not.be.disabled' ); + cy.wait(500); // click to delete - cy.get('[data-test-subj="deleteConfirmButton"]', { - timeout: 20000, - }).click({ force: true }); + cy.get('[data-test-subj="deleteConfirmButton"]').click(); // the alias should not exist cy.wait(500); - cy.get(`#_selection_column_${SAMPLE_ALIAS_PREFIX}-0-checkbox`, { - timeout: 20000, - }).should('not.exist'); + cy.get(`#_selection_column_${SAMPLE_ALIAS_PREFIX}-0-checkbox`).should( + 'not.exist' + ); }); }); From d4f224be45a65baa69ad4c768b36e8f25cea22b8 Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Thu, 9 Feb 2023 14:45:43 -0800 Subject: [PATCH 33/36] Fixed failing ISM cypress test. Signed-off-by: AWSHurneyt --- .../plugins/index-management-dashboards-plugin/aliases.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/cypress/integration/plugins/index-management-dashboards-plugin/aliases.js b/cypress/integration/plugins/index-management-dashboards-plugin/aliases.js index ad4931380..150ff8b2f 100644 --- a/cypress/integration/plugins/index-management-dashboards-plugin/aliases.js +++ b/cypress/integration/plugins/index-management-dashboards-plugin/aliases.js @@ -118,9 +118,8 @@ describe('Aliases', () => { cy.get('[data-test-subj="deleteConfirmButton"]').should( 'not.be.disabled' ); - cy.wait(500); // click to delete - cy.get('[data-test-subj="deleteConfirmButton"]').click(); + cy.get('[data-test-subj="deleteConfirmButton"]').click().click(); // the alias should not exist cy.wait(500); cy.get(`#_selection_column_${SAMPLE_ALIAS_PREFIX}-0-checkbox`).should( From 4b498e9b2e17a3ee228b5a277b14950fcd34209e Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Thu, 9 Feb 2023 15:13:13 -0800 Subject: [PATCH 34/36] Fixed failing ISM cypress test. Signed-off-by: AWSHurneyt --- .../plugins/index-management-dashboards-plugin/aliases.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cypress/integration/plugins/index-management-dashboards-plugin/aliases.js b/cypress/integration/plugins/index-management-dashboards-plugin/aliases.js index 150ff8b2f..921326c02 100644 --- a/cypress/integration/plugins/index-management-dashboards-plugin/aliases.js +++ b/cypress/integration/plugins/index-management-dashboards-plugin/aliases.js @@ -114,12 +114,13 @@ describe('Aliases', () => { // The confirm button should be disabled cy.get('[data-test-subj="deleteConfirmButton"]').should('be.disabled'); // type delete - cy.wait(500).get('[data-test-subj="deleteInput"]').type('delete'); + cy.wait(500); + cy.get('[data-test-subj="deleteInput"]').type('delete'); cy.get('[data-test-subj="deleteConfirmButton"]').should( 'not.be.disabled' ); // click to delete - cy.get('[data-test-subj="deleteConfirmButton"]').click().click(); + cy.get('[data-test-subj="deleteConfirmButton"]').click(); // the alias should not exist cy.wait(500); cy.get(`#_selection_column_${SAMPLE_ALIAS_PREFIX}-0-checkbox`).should( From b4163cbb571b804087d4bbbfb7ca67353077a619 Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Thu, 9 Feb 2023 16:14:01 -0800 Subject: [PATCH 35/36] Fixed failing ISM cypress test. Signed-off-by: AWSHurneyt --- .../plugins/index-management-dashboards-plugin/aliases.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cypress/integration/plugins/index-management-dashboards-plugin/aliases.js b/cypress/integration/plugins/index-management-dashboards-plugin/aliases.js index 921326c02..5a0168cf9 100644 --- a/cypress/integration/plugins/index-management-dashboards-plugin/aliases.js +++ b/cypress/integration/plugins/index-management-dashboards-plugin/aliases.js @@ -114,11 +114,11 @@ describe('Aliases', () => { // The confirm button should be disabled cy.get('[data-test-subj="deleteConfirmButton"]').should('be.disabled'); // type delete - cy.wait(500); - cy.get('[data-test-subj="deleteInput"]').type('delete'); + cy.wait(500).get('[data-test-subj="deleteInput"]').type('delete'); cy.get('[data-test-subj="deleteConfirmButton"]').should( 'not.be.disabled' ); + cy.wait(5000); // click to delete cy.get('[data-test-subj="deleteConfirmButton"]').click(); // the alias should not exist From c42876c4b176024b8a4c7a51c8872b32e8a20cff Mon Sep 17 00:00:00 2001 From: AWSHurneyt Date: Fri, 10 Feb 2023 13:11:37 -0800 Subject: [PATCH 36/36] Removed dev code. Signed-off-by: AWSHurneyt --- .../plugins/index-management-dashboards-plugin/aliases.js | 1 - 1 file changed, 1 deletion(-) diff --git a/cypress/integration/plugins/index-management-dashboards-plugin/aliases.js b/cypress/integration/plugins/index-management-dashboards-plugin/aliases.js index 5a0168cf9..73124ecb8 100644 --- a/cypress/integration/plugins/index-management-dashboards-plugin/aliases.js +++ b/cypress/integration/plugins/index-management-dashboards-plugin/aliases.js @@ -118,7 +118,6 @@ describe('Aliases', () => { cy.get('[data-test-subj="deleteConfirmButton"]').should( 'not.be.disabled' ); - cy.wait(5000); // click to delete cy.get('[data-test-subj="deleteConfirmButton"]').click(); // the alias should not exist