From aa36fe67aefdec1948268120516856420b67966f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C5=91=20=C3=81brah=C3=A1m?= Date: Wed, 20 Sep 2023 10:36:11 +0200 Subject: [PATCH] [Defend Workflows] Add tags for mocked and real Endpoint Cypress tests for Serverless (#165094) ## Summary - introduces tags for [Defend Workflows] cypress tests (similarly to https://github.com/elastic/kibana/pull/162698) - adds scripts to Security Solution: - `cypress:dw:serverless:open` and `:run` - `cypress:dw:endpoint:serverless:open` and `:run` - adds CI jobs to run these scripts - so far most of the expected tests got both `@serverless` and `@brokenInServerless` tests, because of other issues to be solved, - one test is able to run against serverless: `x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/policy_details.cy.ts` --- .buildkite/ftr_configs.yml | 1 + .../pull_request/defend_workflows.yml | 25 ++ .../functional/defend_workflows_serverless.sh | 15 ++ .../defend_workflows_vagrant_serverless.sh | 15 ++ x-pack/plugins/security_solution/package.json | 14 +- .../public/management/cypress/.eslintrc.json | 13 + .../public/management/cypress/README.md | 54 ++-- .../management/cypress/cypress.config.ts | 33 +++ .../cypress_base.config.ts} | 16 +- .../cypress/cypress_endpoint.config.ts | 47 ++++ .../cypress_endpoint_serverless.config.ts | 50 ++++ .../cypress/cypress_serverless.config.ts | 36 +++ .../cypress/e2e/endpoint/artifacts.cy.ts | 3 +- .../endpoint/automated_response_actions.cy.ts | 139 +++++----- .../e2e/endpoint/endpoint_alerts.cy.ts | 123 ++++----- .../cypress/e2e/endpoint/endpoints.cy.ts | 36 +-- .../cypress/e2e/endpoint/isolate.cy.ts | 6 +- .../cypress/e2e/endpoint/policy_details.cy.ts | 4 +- .../e2e/endpoint/response_console.cy.ts | 2 +- .../artifact_tabs_in_policy_details.cy.ts | 242 +++++++++--------- .../cypress/e2e/mocked_data/artifacts.cy.ts | 2 +- .../automated_response_actions/form.cy.ts | 2 +- .../history_log.cy.ts | 2 +- .../no_license.cy.ts | 2 +- .../automated_response_actions/results.cy.ts | 2 +- .../e2e/mocked_data/endpoint_role_rbac.cy.ts | 2 +- .../cypress/e2e/mocked_data/endpoints.cy.ts | 2 +- .../cypress/e2e/mocked_data/isolate.cy.ts | 3 +- .../e2e/mocked_data/policy_details.cy.ts | 2 +- .../e2e/mocked_data/policy_response.cy.ts | 2 +- .../mocked_data/reponse_actions_history.cy.ts | 8 +- .../cypress/e2e/mocked_data/responder.cy.ts | 2 +- .../e2e/mocked_data/response_console.cy.ts | 2 +- .../management/cypress/screens/alerts.ts | 3 +- .../public/management/cypress/support/e2e.ts | 8 +- .../public/management/cypress/tasks/alerts.ts | 2 +- .../public/management/cypress/tasks/common.ts | 1 + .../management/cypress/tasks/isolate.ts | 4 +- .../cypress/tasks/response_actions.ts | 3 - .../cypress/tasks/response_console.ts | 6 +- .../cypress/tasks/run_endpoint_loader.ts | 26 +- .../public/management/cypress/tsconfig.json | 3 - .../management/cypress_endpoint.config.ts | 62 ----- .../endpoint_serverless_config.ts | 65 +++++ 44 files changed, 682 insertions(+), 408 deletions(-) create mode 100755 .buildkite/scripts/steps/functional/defend_workflows_serverless.sh create mode 100755 .buildkite/scripts/steps/functional/defend_workflows_vagrant_serverless.sh create mode 100644 x-pack/plugins/security_solution/public/management/cypress/.eslintrc.json create mode 100644 x-pack/plugins/security_solution/public/management/cypress/cypress.config.ts rename x-pack/plugins/security_solution/public/management/{cypress.config.ts => cypress/cypress_base.config.ts} (78%) create mode 100644 x-pack/plugins/security_solution/public/management/cypress/cypress_endpoint.config.ts create mode 100644 x-pack/plugins/security_solution/public/management/cypress/cypress_endpoint_serverless.config.ts create mode 100644 x-pack/plugins/security_solution/public/management/cypress/cypress_serverless.config.ts delete mode 100644 x-pack/plugins/security_solution/public/management/cypress_endpoint.config.ts create mode 100644 x-pack/test/defend_workflows_cypress/endpoint_serverless_config.ts diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml index 410d1f7598c70..742fcfa820356 100644 --- a/.buildkite/ftr_configs.yml +++ b/.buildkite/ftr_configs.yml @@ -28,6 +28,7 @@ disabled: - x-pack/test/defend_workflows_cypress/cli_config.ts - x-pack/test/defend_workflows_cypress/config.ts - x-pack/test/defend_workflows_cypress/endpoint_config.ts + - x-pack/test/defend_workflows_cypress/endpoint_serverless_config.ts - x-pack/plugins/observability_onboarding/e2e/ftr_config_open.ts - x-pack/plugins/observability_onboarding/e2e/ftr_config_runner.ts - x-pack/plugins/observability_onboarding/e2e/ftr_config.ts diff --git a/.buildkite/pipelines/pull_request/defend_workflows.yml b/.buildkite/pipelines/pull_request/defend_workflows.yml index 00f701c4e16d9..760db34a004be 100644 --- a/.buildkite/pipelines/pull_request/defend_workflows.yml +++ b/.buildkite/pipelines/pull_request/defend_workflows.yml @@ -22,3 +22,28 @@ steps: automatic: - exit_status: '*' limit: 1 + + - command: .buildkite/scripts/steps/functional/defend_workflows_serverless.sh + label: 'Defend Workflows Cypress Tests on Serverless' + agents: + queue: n2-4-spot + depends_on: build + timeout_in_minutes: 120 + parallelism: 2 + retry: + automatic: + - exit_status: '*' + limit: 1 + + - command: .buildkite/scripts/steps/functional/defend_workflows_vagrant_serverless.sh + label: 'Defend Workflows Endpoint Cypress Tests on Serverless' + agents: + queue: n2-4-virt + depends_on: build + timeout_in_minutes: 120 + parallelism: 5 + retry: + automatic: + - exit_status: '*' + limit: 1 + diff --git a/.buildkite/scripts/steps/functional/defend_workflows_serverless.sh b/.buildkite/scripts/steps/functional/defend_workflows_serverless.sh new file mode 100755 index 0000000000000..1a5357744d687 --- /dev/null +++ b/.buildkite/scripts/steps/functional/defend_workflows_serverless.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -euo pipefail + +source .buildkite/scripts/steps/functional/common.sh +source .buildkite/scripts/steps/functional/common_cypress.sh + +export JOB=kibana-defend-workflows-serverless-cypress +export KIBANA_INSTALL_DIR=${KIBANA_BUILD_LOCATION} + +echo "--- Defend Workflows Cypress tests on Serverless" + +cd x-pack/plugins/security_solution + +yarn cypress:dw:serverless:run; status=$?; yarn junit:merge || :; exit $status diff --git a/.buildkite/scripts/steps/functional/defend_workflows_vagrant_serverless.sh b/.buildkite/scripts/steps/functional/defend_workflows_vagrant_serverless.sh new file mode 100755 index 0000000000000..7451cb84b6133 --- /dev/null +++ b/.buildkite/scripts/steps/functional/defend_workflows_vagrant_serverless.sh @@ -0,0 +1,15 @@ +#!/usr/bin/env bash + +set -euo pipefail + +source .buildkite/scripts/steps/functional/common.sh +source .buildkite/scripts/steps/functional/common_cypress.sh + +export JOB=kibana-defend-workflows-endpoint-serverless-cypress +export KIBANA_INSTALL_DIR=${KIBANA_BUILD_LOCATION} + +echo "--- Defend Workflows Endpoint Cypress tests on Serverless" + +cd x-pack/plugins/security_solution + +yarn cypress:dw:endpoint:serverless:run; status=$?; yarn junit:merge || :; exit $status diff --git a/x-pack/plugins/security_solution/package.json b/x-pack/plugins/security_solution/package.json index 1c473d628ff2c..6675ae6cd3b52 100644 --- a/x-pack/plugins/security_solution/package.json +++ b/x-pack/plugins/security_solution/package.json @@ -10,12 +10,18 @@ "cypress": "NODE_OPTIONS=--openssl-legacy-provider ../../../node_modules/.bin/cypress", "cypress:burn": "yarn cypress:dw run --env burn=2 --headed", "cypress:changed-specs-only": "yarn cypress:dw run --changed-specs-only --env burn=2", - "cypress:dw": "NODE_OPTIONS=--openssl-legacy-provider node ./scripts/start_cypress_parallel --config-file ./public/management/cypress.config.ts ts --ftr-config-file ../../test/defend_workflows_cypress/cli_config", + "cypress:dw": "NODE_OPTIONS=--openssl-legacy-provider node ./scripts/start_cypress_parallel --config-file ./public/management/cypress/cypress.config.ts --ftr-config-file ../../test/defend_workflows_cypress/cli_config", "cypress:dw:open": "yarn cypress:dw open", "cypress:dw:run": "yarn cypress:dw run", - "cypress:dw:endpoint": "NODE_OPTIONS=--openssl-legacy-provider node ./scripts/start_cypress_parallel --config-file ./public/management/cypress_endpoint.config.ts --ftr-config-file ../../test/defend_workflows_cypress/endpoint_config", + "cypress:dw:endpoint": "NODE_OPTIONS=--openssl-legacy-provider node ./scripts/start_cypress_parallel --config-file ./public/management/cypress/cypress_endpoint.config.ts --ftr-config-file ../../test/defend_workflows_cypress/endpoint_config", "cypress:dw:endpoint:run": "yarn cypress:dw:endpoint run", - "cypress:dw:endpoint:open": "yarn cypress:dw:endpoint open ", + "cypress:dw:endpoint:open": "yarn cypress:dw:endpoint open", + "cypress:dw:serverless": "NODE_OPTIONS=--openssl-legacy-provider node ./scripts/start_cypress_parallel --config-file ./public/management/cypress/cypress_serverless.config.ts --ftr-config-file ../../../x-pack/test_serverless/functional/test_suites/security/cypress/security_config", + "cypress:dw:serverless:open": "yarn cypress:dw:serverless open", + "cypress:dw:serverless:run": "yarn cypress:dw:serverless run", + "cypress:dw:endpoint:serverless": "NODE_OPTIONS=--openssl-legacy-provider node ./scripts/start_cypress_parallel --config-file ./public/management/cypress/cypress_endpoint_serverless.config.ts --ftr-config-file ../../test/defend_workflows_cypress/endpoint_serverless_config", + "cypress:dw:endpoint:serverless:open": "yarn cypress:dw:endpoint:serverless open", + "cypress:dw:endpoint:serverless:run": "yarn cypress:dw:endpoint:serverless run", "junit:merge": "../../../node_modules/.bin/mochawesome-merge ../../../target/kibana-security-solution/cypress/results/mochawesome*.json > ../../../target/kibana-security-solution/cypress/results/output.json && ../../../node_modules/.bin/marge ../../../target/kibana-security-solution/cypress/results/output.json --reportDir ../../../target/kibana-security-solution/cypress/results && yarn junit:transform && mkdir -p ../../../target/junit && cp ../../../target/kibana-security-solution/cypress/results/*.xml ../../../target/junit/", "test:generate": "node scripts/endpoint/resolver_generator", "mappings:generate": "node scripts/mappings/mappings_generator", @@ -24,4 +30,4 @@ "openapi:generate": "node scripts/openapi/generate", "openapi:generate:debug": "node --inspect-brk scripts/openapi/generate" } -} +} \ No newline at end of file diff --git a/x-pack/plugins/security_solution/public/management/cypress/.eslintrc.json b/x-pack/plugins/security_solution/public/management/cypress/.eslintrc.json new file mode 100644 index 0000000000000..22a4d052afdc5 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/.eslintrc.json @@ -0,0 +1,13 @@ +{ + "plugins": ["cypress"], + "extends": [ + "plugin:cypress/recommended" + ], + "env": { + "cypress/globals": true + }, + "rules": { + "cypress/no-force": "warn", + "import/no-extraneous-dependencies": "off" + } +} diff --git a/x-pack/plugins/security_solution/public/management/cypress/README.md b/x-pack/plugins/security_solution/public/management/cypress/README.md index 70db70573a415..d78338c5898d4 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/README.md +++ b/x-pack/plugins/security_solution/public/management/cypress/README.md @@ -29,6 +29,16 @@ If you also want to run the tests against real endpoints as on the CI pipeline, See [running interactive tests on real endpoint with vagrant](#cypress-interactive-with-real-endpoints-using-vagrant) for more information. +## Adding new tests - tagging for ESS vs Serverless + +Similarly to Security Solution cypress tests, we use tags in order to select which tests we want to execute on which environment: + +- `@serverless` includes a test in the Serverless test suite. You need to explicitly add this tag to any test you want to run against a Serverless environment. +- `@ess` includes a test in the normal, non-Serverless test suite. You need to explicitly add this tag to any test you want to run against a non-Serverless environment. +- `@brokenInServerless` excludes a test from the Serverless test suite (even if it's tagged as `@serverless`). Indicates that a test should run in Serverless, but currently is broken. + +Important: if you don't provide any tag, your test won't be executed. + ## Running the tests There are currently three ways to run the tests, comprised of two execution modes and two target environments, which @@ -102,14 +112,11 @@ failures locally, etc. # bootstrap kibana from the project root and build the plugins/assets that cypress will execute against yarn kbn bootstrap && node scripts/build_kibana_platform_plugins -# launch the cypress test runner -cd x-pack/plugins/security_solution -yarn cypress:dw:run-as-ci - -# or +# launch the cypress test runner against ESS +yarn --cwd x-pack/plugins/security_solution cypress:dw:run -# launch without changing directory from kibana/ -yarn --cwd x-pack/plugins/security_solution cypress:dw:run-as-ci +# or against Serverless +yarn --cwd x-pack/plugins/security_solution cypress:dw:serverless:run ``` #### Cypress @@ -120,14 +127,11 @@ This is the preferred mode for developing new tests against mocked data # bootstrap kibana from the project root and build the plugins/assets that cypress will execute against yarn kbn bootstrap && node scripts/build_kibana_platform_plugins -# launch the cypress test runner -cd x-pack/plugins/security_solution -yarn cypress:dw:open - -# or - -# launch without changing directory from kibana/ +# launch the cypress test runner against ESS yarn --cwd x-pack/plugins/security_solution cypress:dw:open + +# or against Serverless +yarn --cwd x-pack/plugins/security_solution cypress:dw:serverless:open ``` For developing/debugging tests against real endpoint please use: @@ -138,14 +142,11 @@ Endpoint tests require [Multipass](https://multipass.run/) to be installed on yo # bootstrap kibana from the project root and build the plugins/assets that cypress will execute against yarn kbn bootstrap && node scripts/build_kibana_platform_plugins -# launch the cypress test runner with real endpoint -cd x-pack/plugins/security_solution -yarn cypress:dw:endpoint:open - -# or - -# launch without changing directory from kibana/ +# launch the cypress test runner against ESS yarn --cwd x-pack/plugins/security_solution cypress:dw:endpoint:open + +# or against Serverless +yarn --cwd x-pack/plugins/security_solution cypress:dw:endpoint:serverless:open ``` #### Cypress (interactive) with real Endpoints using Vagrant @@ -172,14 +173,11 @@ Endpoint tests require [Multipass](https://multipass.run/) to be installed on yo # bootstrap kibana from the project root and build the plugins/assets that cypress will execute against yarn kbn bootstrap && node scripts/build_kibana_platform_plugins -# launch the cypress test runner with real endpoint -cd x-pack/plugins/security_solution -yarn cypress:dw:endpoint:run - -# or - -# launch without changing directory from kibana/ +# launch the cypress test runner with real endpoint against ESS yarn --cwd x-pack/plugins/security_solution cypress:dw:endpoint:run + +# or against Serverless +yarn --cwd x-pack/plugins/security_solution cypress:dw:endpoint:serverless:run ``` ## Folder Structure diff --git a/x-pack/plugins/security_solution/public/management/cypress/cypress.config.ts b/x-pack/plugins/security_solution/public/management/cypress/cypress.config.ts new file mode 100644 index 0000000000000..ad18b6ca8ef1d --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/cypress.config.ts @@ -0,0 +1,33 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { defineCypressConfig } from '@kbn/cypress-config'; +import { getCypressBaseConfig } from './cypress_base.config'; + +import { dataLoaders } from './support/data_loaders'; + +export default defineCypressConfig({ + ...getCypressBaseConfig(), + + env: { + ...getCypressBaseConfig().env, + + grepTags: '@ess', + }, + + e2e: { + ...getCypressBaseConfig().e2e, + + specPattern: 'public/management/cypress/e2e/mocked_data/', + setupNodeEvents: (on, config) => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + require('@cypress/grep/src/plugin')(config); + + return dataLoaders(on, config); + }, + }, +}); diff --git a/x-pack/plugins/security_solution/public/management/cypress.config.ts b/x-pack/plugins/security_solution/public/management/cypress/cypress_base.config.ts similarity index 78% rename from x-pack/plugins/security_solution/public/management/cypress.config.ts rename to x-pack/plugins/security_solution/public/management/cypress/cypress_base.config.ts index 34e7ae02cb626..b45e33388d039 100644 --- a/x-pack/plugins/security_solution/public/management/cypress.config.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/cypress_base.config.ts @@ -5,11 +5,7 @@ * 2.0. */ -import { defineCypressConfig } from '@kbn/cypress-config'; -// eslint-disable-next-line @kbn/imports/no_boundary_crossing -import { dataLoaders } from './cypress/support/data_loaders'; - -export default defineCypressConfig({ +export const getCypressBaseConfig = () => ({ reporter: '../../../../node_modules/cypress-multi-reporters', reporterOptions: { configFile: './public/management/reporter_config.json', @@ -36,21 +32,23 @@ export default defineCypressConfig({ KIBANA_URL: 'http://localhost:5601', ELASTICSEARCH_URL: 'http://localhost:9200', FLEET_SERVER_URL: 'https://localhost:8220', + // Username/password used for both elastic and kibana KIBANA_USERNAME: 'system_indices_superuser', KIBANA_PASSWORD: 'changeme', ELASTICSEARCH_USERNAME: 'system_indices_superuser', ELASTICSEARCH_PASSWORD: 'changeme', + + // grep related configs + grepFilterSpecs: true, + grepOmitFiltered: true, }, e2e: { // baseUrl: To override, set Env. variable `CYPRESS_BASE_URL` baseUrl: 'http://localhost:5601', + supportFile: 'public/management/cypress/support/e2e.ts', - specPattern: 'public/management/cypress/e2e/mocked_data/', experimentalRunAllSpecs: true, - setupNodeEvents: (on, config) => { - return dataLoaders(on, config); - }, }, }); diff --git a/x-pack/plugins/security_solution/public/management/cypress/cypress_endpoint.config.ts b/x-pack/plugins/security_solution/public/management/cypress/cypress_endpoint.config.ts new file mode 100644 index 0000000000000..409e3dc258ee2 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/cypress_endpoint.config.ts @@ -0,0 +1,47 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { defineCypressConfig } from '@kbn/cypress-config'; +import { getCypressBaseConfig } from './cypress_base.config'; + +import { dataLoaders, dataLoadersForRealEndpoints } from './support/data_loaders'; + +import { responseActionTasks } from './support/response_actions'; + +// eslint-disable-next-line import/no-default-export +export default defineCypressConfig({ + ...getCypressBaseConfig(), + + env: { + ...getCypressBaseConfig().env, + + 'cypress-react-selector': { + root: '#security-solution-app', + }, + + grepTags: '@ess', + }, + + e2e: { + ...getCypressBaseConfig().e2e, + + experimentalMemoryManagement: true, + experimentalInteractiveRunEvents: true, + specPattern: 'public/management/cypress/e2e/endpoint/*.cy.{js,jsx,ts,tsx}', + setupNodeEvents: (on: Cypress.PluginEvents, config: Cypress.PluginConfigOptions) => { + dataLoaders(on, config); + // Data loaders specific to "real" Endpoint testing + dataLoadersForRealEndpoints(on, config); + responseActionTasks(on, config); + + // eslint-disable-next-line @typescript-eslint/no-var-requires + require('@cypress/grep/src/plugin')(config); + + return config; + }, + }, +}); diff --git a/x-pack/plugins/security_solution/public/management/cypress/cypress_endpoint_serverless.config.ts b/x-pack/plugins/security_solution/public/management/cypress/cypress_endpoint_serverless.config.ts new file mode 100644 index 0000000000000..d0fe78831f892 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/cypress_endpoint_serverless.config.ts @@ -0,0 +1,50 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { defineCypressConfig } from '@kbn/cypress-config'; +import { getCypressBaseConfig } from './cypress_base.config'; +import { dataLoaders } from './support/data_loaders'; +import { responseActionTasks } from './support/response_actions'; + +// eslint-disable-next-line import/no-default-export +export default defineCypressConfig({ + ...getCypressBaseConfig(), + + env: { + ...getCypressBaseConfig().env, + + IS_SERVERLESS: true, + grepTags: '@serverless --@brokenInServerless', + + 'cypress-react-selector': { + root: '#security-solution-app', + }, + }, + + e2e: { + ...getCypressBaseConfig().e2e, + + experimentalMemoryManagement: true, + experimentalInteractiveRunEvents: true, + + specPattern: 'public/management/cypress/e2e/endpoint/*.cy.{js,jsx,ts,tsx}', + + setupNodeEvents: (on, config) => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + require('@cypress/grep/src/plugin')(config); + + dataLoaders(on, config); + + // skip dataLoadersForRealEndpoints() + // https://github.com/elastic/security-team/issues/7467 + // Data loaders specific to "real" Endpoint testing + // dataLoadersForRealEndpoints(on, config); + + responseActionTasks(on, config); + }, + }, +}); diff --git a/x-pack/plugins/security_solution/public/management/cypress/cypress_serverless.config.ts b/x-pack/plugins/security_solution/public/management/cypress/cypress_serverless.config.ts new file mode 100644 index 0000000000000..60517176bc482 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/cypress_serverless.config.ts @@ -0,0 +1,36 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { defineCypressConfig } from '@kbn/cypress-config'; +import { getCypressBaseConfig } from './cypress_base.config'; +import { dataLoaders } from './support/data_loaders'; + +// eslint-disable-next-line import/no-default-export +export default defineCypressConfig({ + ...getCypressBaseConfig(), + + env: { + ...getCypressBaseConfig().env, + + IS_SERVERLESS: true, + + grepTags: '@serverless --@brokenInServerless', + }, + + e2e: { + ...getCypressBaseConfig().e2e, + + specPattern: 'public/management/cypress/e2e/mocked_data/', + + setupNodeEvents: (on, config) => { + // eslint-disable-next-line @typescript-eslint/no-var-requires + require('@cypress/grep/src/plugin')(config); + + return dataLoaders(on, config); + }, + }, +}); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/artifacts.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/artifacts.cy.ts index 151e0f6bf233b..e854653e74e0f 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/artifacts.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/artifacts.cy.ts @@ -36,7 +36,7 @@ const yieldAppliedEndpointRevision = (): Cypress.Chainable => const parseRevNumber = (revString: string) => Number(revString.match(/\d+/)?.[0]); -describe('Artifact pages', () => { +describe('Artifact pages', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => { let indexedPolicy: IndexedFleetEndpointPolicyResponse; let policy: PolicyData; let createdHost: CreateAndEnrollEndpointHostResponse; @@ -61,6 +61,7 @@ describe('Artifact pages', () => { // wait for ManifestManager to pick up artifact changes that happened either here // or in a previous test suite `after` + // eslint-disable-next-line cypress/no-unnecessary-waiting cy.wait(6000); // packagerTaskInterval + 1s yieldEndpointPolicyRevision().then((actualEndpointPolicyRevision) => { diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/automated_response_actions.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/automated_response_actions.cy.ts index 77b2164169641..a671b1c855f84 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/automated_response_actions.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/automated_response_actions.cy.ts @@ -20,86 +20,91 @@ import { createEndpointHost } from '../../tasks/create_endpoint_host'; import { deleteAllLoadedEndpointData } from '../../tasks/delete_all_endpoint_data'; import { enableAllPolicyProtections } from '../../tasks/endpoint_policy'; -describe('Automated Response Actions', () => { - let indexedPolicy: IndexedFleetEndpointPolicyResponse; - let policy: PolicyData; - let createdHost: CreateAndEnrollEndpointHostResponse; - - before(() => { - getEndpointIntegrationVersion().then((version) => - createAgentPolicyTask(version, 'automated_response_actions').then((data) => { - indexedPolicy = data; - policy = indexedPolicy.integrationPolicies[0]; - - return enableAllPolicyProtections(policy.id).then(() => { - // Create and enroll a new Endpoint host - return createEndpointHost(policy.policy_id).then((host) => { - createdHost = host as CreateAndEnrollEndpointHostResponse; +describe( + 'Automated Response Actions', + { tags: ['@ess', '@serverless', '@brokenInServerless'] }, + () => { + let indexedPolicy: IndexedFleetEndpointPolicyResponse; + let policy: PolicyData; + let createdHost: CreateAndEnrollEndpointHostResponse; + + before(() => { + getEndpointIntegrationVersion().then((version) => + createAgentPolicyTask(version, 'automated_response_actions').then((data) => { + indexedPolicy = data; + policy = indexedPolicy.integrationPolicies[0]; + + return enableAllPolicyProtections(policy.id).then(() => { + // Create and enroll a new Endpoint host + return createEndpointHost(policy.policy_id).then((host) => { + createdHost = host as CreateAndEnrollEndpointHostResponse; + }); }); - }); - }) - ); - }); + }) + ); + }); - after(() => { - if (createdHost) { - cy.task('destroyEndpointHost', createdHost); - } + after(() => { + if (createdHost) { + cy.task('destroyEndpointHost', createdHost); + } - if (indexedPolicy) { - cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy); - } + if (indexedPolicy) { + cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy); + } - if (createdHost) { - deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); - } - }); + if (createdHost) { + deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); + } + }); - const hostname = new URL(Cypress.env('FLEET_SERVER_URL')).port; - const fleetHostname = `dev-fleet-server.${hostname}`; + const hostname = new URL(Cypress.env('FLEET_SERVER_URL')).port; + const fleetHostname = `dev-fleet-server.${hostname}`; - beforeEach(() => { - login(); - disableExpandableFlyoutAdvancedSettings(); - }); + beforeEach(() => { + login(); + disableExpandableFlyoutAdvancedSettings(); + }); - describe('From alerts', () => { - let ruleId: string; - let ruleName: string; + describe('From alerts', () => { + let ruleId: string; + let ruleName: string; - before(() => { - loadRule().then((data) => { - ruleId = data.id; - ruleName = data.name; + before(() => { + loadRule().then((data) => { + ruleId = data.id; + ruleName = data.name; + }); }); - }); - after(() => { - if (ruleId) { - cleanupRule(ruleId); - } - }); - it.skip('should have generated endpoint and rule', () => { - loadPage(APP_ENDPOINTS_PATH); - cy.contains(createdHost.hostname).should('exist'); + after(() => { + if (ruleId) { + cleanupRule(ruleId); + } + }); - toggleRuleOffAndOn(ruleName); + it.skip('should have generated endpoint and rule', () => { + loadPage(APP_ENDPOINTS_PATH); + cy.contains(createdHost.hostname).should('exist'); - visitRuleAlerts(ruleName); - closeAllToasts(); + toggleRuleOffAndOn(ruleName); - changeAlertsFilter('event.category: "file"'); - cy.getByTestSubj('expand-event').first().click(); - cy.getByTestSubj('responseActionsViewTab').click(); - cy.getByTestSubj('response-actions-notification').should('not.have.text', '0'); + visitRuleAlerts(ruleName); + closeAllToasts(); - cy.getByTestSubj(`response-results-${createdHost.hostname}-details-tray`) - .should('contain', 'isolate completed successfully') - .and('contain', createdHost.hostname); + changeAlertsFilter('event.category: "file"'); + cy.getByTestSubj('expand-event').first().click(); + cy.getByTestSubj('responseActionsViewTab').click(); + cy.getByTestSubj('response-actions-notification').should('not.have.text', '0'); - cy.getByTestSubj(`response-results-${fleetHostname}-details-tray`) - .should('contain', 'The host does not have Elastic Defend integration installed') - .and('contain', 'dev-fleet-server'); + cy.getByTestSubj(`response-results-${createdHost.hostname}-details-tray`) + .should('contain', 'isolate completed successfully') + .and('contain', createdHost.hostname); + + cy.getByTestSubj(`response-results-${fleetHostname}-details-tray`) + .should('contain', 'The host does not have Elastic Defend integration installed') + .and('contain', 'dev-fleet-server'); + }); }); - }); -}); + } +); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/endpoint_alerts.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/endpoint_alerts.cy.ts index 5a33371754be5..f77b5fe53b8ff 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/endpoint_alerts.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/endpoint_alerts.cy.ts @@ -19,79 +19,80 @@ import { login } from '../../tasks/login'; import { EXECUTE_ROUTE } from '../../../../../common/endpoint/constants'; import { waitForActionToComplete } from '../../tasks/response_actions'; -describe('Endpoint generated alerts', () => { - let indexedPolicy: IndexedFleetEndpointPolicyResponse; - let policy: PolicyData; - let createdHost: CreateAndEnrollEndpointHostResponse; +describe( + 'Endpoint generated alerts', + { tags: ['@ess', '@serverless', '@brokenInServerless'] }, + () => { + let indexedPolicy: IndexedFleetEndpointPolicyResponse; + let policy: PolicyData; + let createdHost: CreateAndEnrollEndpointHostResponse; - before(() => { - getEndpointIntegrationVersion().then((version) => { - createAgentPolicyTask(version, 'alerts test').then((data) => { - indexedPolicy = data; - policy = indexedPolicy.integrationPolicies[0]; + before(() => { + getEndpointIntegrationVersion().then((version) => { + createAgentPolicyTask(version, 'alerts test').then((data) => { + indexedPolicy = data; + policy = indexedPolicy.integrationPolicies[0]; - return enableAllPolicyProtections(policy.id).then(() => { - // Create and enroll a new Endpoint host - return createEndpointHost(policy.policy_id).then((host) => { - createdHost = host as CreateAndEnrollEndpointHostResponse; + return enableAllPolicyProtections(policy.id).then(() => { + // Create and enroll a new Endpoint host + return createEndpointHost(policy.policy_id).then((host) => { + createdHost = host as CreateAndEnrollEndpointHostResponse; + }); }); }); }); }); - }); - after(() => { - if (createdHost) { - cy.task('destroyEndpointHost', createdHost); - } + after(() => { + if (createdHost) { + cy.task('destroyEndpointHost', createdHost); + } - if (indexedPolicy) { - cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy); - } + if (indexedPolicy) { + cy.task('deleteIndexedFleetEndpointPolicies', indexedPolicy); + } - if (createdHost) { - deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); - } - }); + if (createdHost) { + deleteAllLoadedEndpointData({ endpointAgentIds: [createdHost.agentId] }); + } + }); - beforeEach(() => { - login(); - }); + beforeEach(() => { + login(); + }); - it('should create a Detection Engine alert from an endpoint alert', () => { - // Triggers a Malicious Behaviour alert on Linux system (`grep *` was added only to identify this specific alert) - const executeMaliciousCommand = `bash -c cat /dev/tcp/foo | grep ${Math.random() - .toString(16) - .substring(2)}`; + it('should create a Detection Engine alert from an endpoint alert', () => { + // Triggers a Malicious Behaviour alert on Linux system (`grep *` was added only to identify this specific alert) + const executeMaliciousCommand = `bash -c cat /dev/tcp/foo | grep ${Math.random() + .toString(16) + .substring(2)}`; - // Send `execute` command that triggers malicious behaviour using the `execute` response action - request({ - method: 'POST', - url: EXECUTE_ROUTE, - body: { - endpoint_ids: [createdHost.agentId], - parameters: { - command: executeMaliciousCommand, - }, - }, - headers: { - 'Elastic-Api-Version': '2023-10-31', - }, - }) - .then((response) => waitForActionToComplete(response.body.data.id)) - .then(() => { - return waitForEndpointAlerts(createdHost.agentId, [ - { - term: { 'process.group_leader.args': executeMaliciousCommand }, + // Send `execute` command that triggers malicious behaviour using the `execute` response action + request({ + method: 'POST', + url: EXECUTE_ROUTE, + body: { + endpoint_ids: [createdHost.agentId], + parameters: { + command: executeMaliciousCommand, }, - ]); + }, }) - .then(() => { - return navigateToAlertsList( - `query=(language:kuery,query:'agent.id: "${createdHost.agentId}" ')` - ); - }); + .then((response) => waitForActionToComplete(response.body.data.id)) + .then(() => { + return waitForEndpointAlerts(createdHost.agentId, [ + { + term: { 'process.group_leader.args': executeMaliciousCommand }, + }, + ]); + }) + .then(() => { + return navigateToAlertsList( + `query=(language:kuery,query:'agent.id: "${createdHost.agentId}" ')` + ); + }); - getAlertsTableRows().should('have.length.greaterThan', 0); - }); -}); + getAlertsTableRows().should('have.length.greaterThan', 0); + }); + } +); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/endpoints.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/endpoints.cy.ts index d86fabde64a18..6d9af6162dbe7 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/endpoints.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/endpoints.cy.ts @@ -32,7 +32,7 @@ import { createEndpointHost } from '../../tasks/create_endpoint_host'; import { deleteAllLoadedEndpointData } from '../../tasks/delete_all_endpoint_data'; import { enableAllPolicyProtections } from '../../tasks/endpoint_policy'; -describe('Endpoints page', () => { +describe('Endpoints page', { tags: '@ess' }, () => { let indexedPolicy: IndexedFleetEndpointPolicyResponse; let policy: PolicyData; let createdHost: CreateAndEnrollEndpointHostResponse; @@ -109,24 +109,26 @@ describe('Endpoints page', () => { it('User can reassign a single endpoint to a different Agent Configuration', () => { loadPage(APP_ENDPOINTS_PATH); - const hostname = cy - .getByTestSubj(AGENT_HOSTNAME_CELL) - .filter(`:contains("${createdHost.hostname}")`); - const tableRow = hostname.parents('tr'); - tableRow.findByTestSubj(TABLE_ROW_ACTIONS).click(); - cy.getByTestSubj(TABLE_ROW_ACTIONS_MENU).contains('Reassign agent policy').click(); - cy.getByTestSubj(FLEET_REASSIGN_POLICY_MODAL) - .find('select') - .select(response.agentPolicies[0].name); - cy.getByTestSubj(FLEET_REASSIGN_POLICY_MODAL_CONFIRM_BUTTON).click(); cy.getByTestSubj(AGENT_HOSTNAME_CELL) .filter(`:contains("${createdHost.hostname}")`) - .should('exist'); - cy.getByTestSubj(AGENT_HOSTNAME_CELL) - .filter(`:contains("${createdHost.hostname}")`) - .parents('tr') - .findByTestSubj(AGENT_POLICY_CELL) - .should('have.text', response.agentPolicies[0].name); + .then((hostname) => { + const tableRow = hostname.parents('tr'); + + tableRow.find(`[data-test-subj=${TABLE_ROW_ACTIONS}`).trigger('click'); + cy.getByTestSubj(TABLE_ROW_ACTIONS_MENU).contains('Reassign agent policy').click(); + cy.getByTestSubj(FLEET_REASSIGN_POLICY_MODAL) + .find('select') + .select(response.agentPolicies[0].name); + cy.getByTestSubj(FLEET_REASSIGN_POLICY_MODAL_CONFIRM_BUTTON).click(); + cy.getByTestSubj(AGENT_HOSTNAME_CELL) + .filter(`:contains("${createdHost.hostname}")`) + .should('exist'); + cy.getByTestSubj(AGENT_HOSTNAME_CELL) + .filter(`:contains("${createdHost.hostname}")`) + .parents('tr') + .findByTestSubj(AGENT_POLICY_CELL) + .should('have.text', response.agentPolicies[0].name); + }); }); }); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/isolate.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/isolate.cy.ts index f39d7fae9f0fe..f09e0b462a75d 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/isolate.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/isolate.cy.ts @@ -31,7 +31,7 @@ import { createEndpointHost } from '../../tasks/create_endpoint_host'; import { deleteAllLoadedEndpointData } from '../../tasks/delete_all_endpoint_data'; import { enableAllPolicyProtections } from '../../tasks/endpoint_policy'; -describe.skip('Isolate command', () => { +describe.skip('Isolate command', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => { let isolateComment: string; let releaseComment: string; let indexedPolicy: IndexedFleetEndpointPolicyResponse; @@ -84,7 +84,7 @@ describe.skip('Isolate command', () => { filterOutIsolatedHosts(); cy.contains('No items found'); - cy.getByTestSubj('adminSearchBar').click().type('{selectall}{backspace}'); + cy.getByTestSubj('adminSearchBar').type('{selectall}{backspace}'); cy.getByTestSubj('querySubmitButton').click(); cy.getByTestSubj('endpointTableRowActions').click(); cy.getByTestSubj('isolateLink').click(); @@ -105,7 +105,7 @@ describe.skip('Isolate command', () => { releaseHostWithComment(releaseComment, createdHost.hostname); cy.contains('Confirm').click(); cy.getByTestSubj('euiFlyoutCloseButton').click(); - cy.getByTestSubj('adminSearchBar').click().type('{selectall}{backspace}'); + cy.getByTestSubj('adminSearchBar').type('{selectall}{backspace}'); cy.getByTestSubj('querySubmitButton').click(); checkEndpointListForOnlyUnIsolatedHosts(); }); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/policy_details.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/policy_details.cy.ts index 0689f89f75472..6e95c1ad73557 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/policy_details.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/policy_details.cy.ts @@ -19,6 +19,7 @@ import { disableExpandableFlyoutAdvancedSettings, loadPage } from '../../tasks/c describe( 'Policy Details', { + tags: '@ess', env: { ftrConfig: { enableExperimental: ['protectionUpdatesEnabled'] } }, }, () => { @@ -175,7 +176,8 @@ describe( it('should update note on save', () => { loadProtectionUpdatesUrl(policy.id); cy.getByTestSubj('protection-updates-manifest-note').contains(testNote); - cy.getByTestSubj('protection-updates-manifest-note').clear().type(updatedTestNote); + cy.getByTestSubj('protection-updates-manifest-note').clear(); + cy.getByTestSubj('protection-updates-manifest-note').type(updatedTestNote); cy.intercept('POST', `/api/endpoint/protection_updates_note/*`).as('note_updated'); cy.getByTestSubj('policyDetailsSaveButton').click(); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/response_console.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/response_console.cy.ts index 245de3ce5512c..f1d6af17a3146 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/response_console.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/endpoint/response_console.cy.ts @@ -27,7 +27,7 @@ import { enableAllPolicyProtections } from '../../tasks/endpoint_policy'; import { createEndpointHost } from '../../tasks/create_endpoint_host'; import { deleteAllLoadedEndpointData } from '../../tasks/delete_all_endpoint_data'; -describe('Response console', () => { +describe('Response console', { tags: ['@ess', '@serverless', '@brokenInServerless'] }, () => { beforeEach(() => { login(); }); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/artifact_tabs_in_policy_details.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/artifact_tabs_in_policy_details.cy.ts index 2977db30fadc9..39ebae1825365 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/artifact_tabs_in_policy_details.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/artifact_tabs_in_policy_details.cy.ts @@ -63,162 +63,166 @@ const visitArtifactTab = (tabId: string) => { cy.get(`#${tabId}`).click(); }; -describe('Artifact tabs in Policy Details page', () => { - before(() => { - login(); - loadEndpointDataForEventFiltersIfNeeded(); - }); - - after(() => { - login(); - removeAllArtifacts(); - }); - - for (const testData of getArtifactsListTestsData()) { - describe(`${testData.title} tab`, () => { - beforeEach(() => { - login(); - removeExceptionsList(testData.createRequestBody.list_id); - }); - - it(`[NONE] User cannot see the tab for ${testData.title}`, () => { - loginWithPrivilegeNone(testData.privilegePrefix); - visitPolicyDetailsPage(); +describe( + 'Artifact tabs in Policy Details page', + { tags: ['@ess', '@serverless', '@brokenInServerless'] }, // broken due to disabled Native Role Management + () => { + before(() => { + login(); + loadEndpointDataForEventFiltersIfNeeded(); + }); - cy.get(`#${testData.tabId}`).should('not.exist'); - }); + after(() => { + login(); + removeAllArtifacts(); + }); - context(`Given there are no ${testData.title} entries`, () => { - it(`[READ] User CANNOT add ${testData.title} artifact`, () => { - loginWithPrivilegeRead(testData.privilegePrefix); - visitArtifactTab(testData.tabId); + for (const testData of getArtifactsListTestsData()) { + describe(`${testData.title} tab`, () => { + beforeEach(() => { + login(); + removeExceptionsList(testData.createRequestBody.list_id); + }); - cy.getByTestSubj('policy-artifacts-empty-unexisting').should('exist'); + it(`[NONE] User cannot see the tab for ${testData.title}`, () => { + loginWithPrivilegeNone(testData.privilegePrefix); + visitPolicyDetailsPage(); - cy.getByTestSubj('unexisting-manage-artifacts-button').should('not.exist'); + cy.get(`#${testData.tabId}`).should('not.exist'); }); - it(`[ALL] User can add ${testData.title} artifact`, () => { - loginWithPrivilegeAll(); - visitArtifactTab(testData.tabId); + context(`Given there are no ${testData.title} entries`, () => { + it(`[READ] User CANNOT add ${testData.title} artifact`, () => { + loginWithPrivilegeRead(testData.privilegePrefix); + visitArtifactTab(testData.tabId); - cy.getByTestSubj('policy-artifacts-empty-unexisting').should('exist'); + cy.getByTestSubj('policy-artifacts-empty-unexisting').should('exist'); - cy.getByTestSubj('unexisting-manage-artifacts-button').should('exist').click(); + cy.getByTestSubj('unexisting-manage-artifacts-button').should('not.exist'); + }); - const { formActions, checkResults } = testData.create; + it(`[ALL] User can add ${testData.title} artifact`, () => { + loginWithPrivilegeAll(); + visitArtifactTab(testData.tabId); - performUserActions(formActions); + cy.getByTestSubj('policy-artifacts-empty-unexisting').should('exist'); - // Add a per policy artifact - but not assign it to any policy - cy.get('[data-test-subj$="-perPolicy"]').click(); // test-subjects are generated in different formats, but all ends with -perPolicy - cy.getByTestSubj(`${testData.pagePrefix}-flyout-submitButton`).click(); + cy.getByTestSubj('unexisting-manage-artifacts-button').should('exist').click(); - // Check new artifact is in the list - for (const checkResult of checkResults) { - cy.getByTestSubj(checkResult.selector).should('have.text', checkResult.value); - } + const { formActions, checkResults } = testData.create; - cy.getByTestSubj('policyDetailsPage').should('not.exist'); - cy.getByTestSubj('backToOrigin').contains(/^Back to .+ policy$/); + performUserActions(formActions); - cy.getByTestSubj('backToOrigin').click(); - cy.getByTestSubj('policyDetailsPage').should('exist'); - }); - }); + // Add a per policy artifact - but not assign it to any policy + cy.get('[data-test-subj$="-perPolicy"]').click(); // test-subjects are generated in different formats, but all ends with -perPolicy + cy.getByTestSubj(`${testData.pagePrefix}-flyout-submitButton`).click(); - context(`Given there are no assigned ${testData.title} entries`, () => { - beforeEach(() => { - login(); - createArtifactList(testData.createRequestBody.list_id); - createPerPolicyArtifact(testData.artifactName, testData.createRequestBody); + // Check new artifact is in the list + for (const checkResult of checkResults) { + cy.getByTestSubj(checkResult.selector).should('have.text', checkResult.value); + } + + cy.getByTestSubj('policyDetailsPage').should('not.exist'); + cy.getByTestSubj('backToOrigin').contains(/^Back to .+ policy$/); + + cy.getByTestSubj('backToOrigin').click(); + cy.getByTestSubj('policyDetailsPage').should('exist'); + }); }); - it(`[READ] User CANNOT Manage or Assign ${testData.title} artifacts`, () => { - loginWithPrivilegeRead(testData.privilegePrefix); - visitArtifactTab(testData.tabId); + context(`Given there are no assigned ${testData.title} entries`, () => { + beforeEach(() => { + login(); + createArtifactList(testData.createRequestBody.list_id); + createPerPolicyArtifact(testData.artifactName, testData.createRequestBody); + }); - cy.getByTestSubj('policy-artifacts-empty-unassigned').should('exist'); + it(`[READ] User CANNOT Manage or Assign ${testData.title} artifacts`, () => { + loginWithPrivilegeRead(testData.privilegePrefix); + visitArtifactTab(testData.tabId); - cy.getByTestSubj('unassigned-manage-artifacts-button').should('not.exist'); - cy.getByTestSubj('unassigned-assign-artifacts-button').should('not.exist'); - }); + cy.getByTestSubj('policy-artifacts-empty-unassigned').should('exist'); - it(`[ALL] User can Manage and Assign ${testData.title} artifacts`, () => { - loginWithPrivilegeAll(); - visitArtifactTab(testData.tabId); + cy.getByTestSubj('unassigned-manage-artifacts-button').should('not.exist'); + cy.getByTestSubj('unassigned-assign-artifacts-button').should('not.exist'); + }); - cy.getByTestSubj('policy-artifacts-empty-unassigned').should('exist'); + it(`[ALL] User can Manage and Assign ${testData.title} artifacts`, () => { + loginWithPrivilegeAll(); + visitArtifactTab(testData.tabId); - // Manage artifacts - cy.getByTestSubj('unassigned-manage-artifacts-button').should('exist').click(); - cy.location('pathname').should( - 'equal', - `/app/security/administration/${testData.urlPath}` - ); - cy.getByTestSubj('backToOrigin').click(); + cy.getByTestSubj('policy-artifacts-empty-unassigned').should('exist'); - // Assign artifacts - cy.getByTestSubj('unassigned-assign-artifacts-button').should('exist').click(); + // Manage artifacts + cy.getByTestSubj('unassigned-manage-artifacts-button').should('exist').click(); + cy.location('pathname').should( + 'equal', + `/app/security/administration/${testData.urlPath}` + ); + cy.getByTestSubj('backToOrigin').click(); - cy.getByTestSubj('artifacts-assign-flyout').should('exist'); - cy.getByTestSubj('artifacts-assign-confirm-button').should('be.disabled'); + // Assign artifacts + cy.getByTestSubj('unassigned-assign-artifacts-button').should('exist').click(); - cy.getByTestSubj(`${testData.artifactName}_checkbox`).click(); - cy.getByTestSubj('artifacts-assign-confirm-button').click(); - }); - }); + cy.getByTestSubj('artifacts-assign-flyout').should('exist'); + cy.getByTestSubj('artifacts-assign-confirm-button').should('be.disabled'); - context(`Given there are assigned ${testData.title} entries`, () => { - beforeEach(() => { - login(); - createArtifactList(testData.createRequestBody.list_id); - yieldFirstPolicyID().then((policyID) => { - createPerPolicyArtifact(testData.artifactName, testData.createRequestBody, policyID); + cy.getByTestSubj(`${testData.artifactName}_checkbox`).click(); + cy.getByTestSubj('artifacts-assign-confirm-button').click(); }); }); - it(`[READ] User can see ${testData.title} artifacts but CANNOT assign or remove from policy`, () => { - loginWithPrivilegeRead(testData.privilegePrefix); - visitArtifactTab(testData.tabId); + context(`Given there are assigned ${testData.title} entries`, () => { + beforeEach(() => { + login(); + createArtifactList(testData.createRequestBody.list_id); + yieldFirstPolicyID().then((policyID) => { + createPerPolicyArtifact(testData.artifactName, testData.createRequestBody, policyID); + }); + }); - // List of artifacts - cy.getByTestSubj('artifacts-collapsed-list-card').should('have.length', 1); - cy.getByTestSubj('artifacts-collapsed-list-card-header-titleHolder').contains( - testData.artifactName - ); + it(`[READ] User can see ${testData.title} artifacts but CANNOT assign or remove from policy`, () => { + loginWithPrivilegeRead(testData.privilegePrefix); + visitArtifactTab(testData.tabId); - // Cannot assign artifacts - cy.getByTestSubj('artifacts-assign-button').should('not.exist'); + // List of artifacts + cy.getByTestSubj('artifacts-collapsed-list-card').should('have.length', 1); + cy.getByTestSubj('artifacts-collapsed-list-card-header-titleHolder').contains( + testData.artifactName + ); - // Cannot remove from policy - cy.getByTestSubj('artifacts-collapsed-list-card-header-actions-button').click(); - cy.getByTestSubj('remove-from-policy-action').should('not.exist'); - }); + // Cannot assign artifacts + cy.getByTestSubj('artifacts-assign-button').should('not.exist'); - it(`[ALL] User can see ${testData.title} artifacts and can assign or remove artifacts from policy`, () => { - loginWithPrivilegeAll(); - visitArtifactTab(testData.tabId); + // Cannot remove from policy + cy.getByTestSubj('artifacts-collapsed-list-card-header-actions-button').click(); + cy.getByTestSubj('remove-from-policy-action').should('not.exist'); + }); - // List of artifacts - cy.getByTestSubj('artifacts-collapsed-list-card').should('have.length', 1); - cy.getByTestSubj('artifacts-collapsed-list-card-header-titleHolder').contains( - testData.artifactName - ); + it(`[ALL] User can see ${testData.title} artifacts and can assign or remove artifacts from policy`, () => { + loginWithPrivilegeAll(); + visitArtifactTab(testData.tabId); - // Assign artifacts - cy.getByTestSubj('artifacts-assign-button').should('exist').click(); - cy.getByTestSubj('artifacts-assign-flyout').should('exist'); - cy.getByTestSubj('artifacts-assign-cancel-button').click(); + // List of artifacts + cy.getByTestSubj('artifacts-collapsed-list-card').should('have.length', 1); + cy.getByTestSubj('artifacts-collapsed-list-card-header-titleHolder').contains( + testData.artifactName + ); - // Remove from policy - cy.getByTestSubj('artifacts-collapsed-list-card-header-actions-button').click(); - cy.getByTestSubj('remove-from-policy-action').click(); - cy.getByTestSubj('confirmModalConfirmButton').click(); + // Assign artifacts + cy.getByTestSubj('artifacts-assign-button').should('exist').click(); + cy.getByTestSubj('artifacts-assign-flyout').should('exist'); + cy.getByTestSubj('artifacts-assign-cancel-button').click(); - cy.contains('Successfully removed'); + // Remove from policy + cy.getByTestSubj('artifacts-collapsed-list-card-header-actions-button').click(); + cy.getByTestSubj('remove-from-policy-action').click(); + cy.getByTestSubj('confirmModalConfirmButton').click(); + + cy.contains('Successfully removed'); + }); }); }); - }); + } } -}); +); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/artifacts.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/artifacts.cy.ts index 53693ab40b651..8f575282ad3f7 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/artifacts.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/artifacts.cy.ts @@ -35,7 +35,7 @@ const loginWithoutAccess = (url: string) => { loadPage(url); }; -describe('Artifacts pages', () => { +describe('Artifacts pages', { tags: '@ess' }, () => { before(() => { login(); loadEndpointDataForEventFiltersIfNeeded(); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/automated_response_actions/form.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/automated_response_actions/form.cy.ts index 2e82ff002e36b..c5a6e636acdb3 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/automated_response_actions/form.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/automated_response_actions/form.cy.ts @@ -18,7 +18,7 @@ import { cleanupRule, generateRandomStringName, loadRule } from '../../../tasks/ import { RESPONSE_ACTION_TYPES } from '../../../../../../common/api/detection_engine'; import { loginWithRole, ROLE } from '../../../tasks/login'; -describe('Form', () => { +describe('Form', { tags: '@ess' }, () => { describe('User with no access can not create an endpoint response action', () => { before(() => { loginWithRole(ROLE.endpoint_response_actions_no_access); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/automated_response_actions/history_log.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/automated_response_actions/history_log.cy.ts index 388f6eb81dfcb..ebab02870d307 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/automated_response_actions/history_log.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/automated_response_actions/history_log.cy.ts @@ -12,7 +12,7 @@ import { indexEndpointRuleAlerts } from '../../../tasks/index_endpoint_rule_aler import { login, ROLE } from '../../../tasks/login'; -describe('Response actions history page', () => { +describe('Response actions history page', { tags: '@ess' }, () => { let endpointData: ReturnTypeFromChainable | undefined; let endpointDataWithAutomated: ReturnTypeFromChainable | undefined; let alertData: ReturnTypeFromChainable | undefined; diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/automated_response_actions/no_license.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/automated_response_actions/no_license.cy.ts index b046a067e260c..b9591f94a2f25 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/automated_response_actions/no_license.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/automated_response_actions/no_license.cy.ts @@ -15,7 +15,7 @@ import type { ReturnTypeFromChainable } from '../../../types'; import { indexEndpointHosts } from '../../../tasks/index_endpoint_hosts'; import { indexEndpointRuleAlerts } from '../../../tasks/index_endpoint_rule_alerts'; -describe('No License', { env: { ftrConfig: { license: 'basic' } } }, () => { +describe('No License', { tags: '@ess', env: { ftrConfig: { license: 'basic' } } }, () => { describe('User cannot use endpoint action in form', () => { const [ruleName, ruleDescription] = generateRandomStringName(2); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/automated_response_actions/results.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/automated_response_actions/results.cy.ts index 82fc29edb7b5e..cbbd997004312 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/automated_response_actions/results.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/automated_response_actions/results.cy.ts @@ -15,7 +15,7 @@ import { indexEndpointRuleAlerts } from '../../../tasks/index_endpoint_rule_aler import { login, ROLE } from '../../../tasks/login'; -describe('Results', () => { +describe('Results', { tags: '@ess' }, () => { let endpointData: ReturnTypeFromChainable | undefined; let alertData: ReturnTypeFromChainable | undefined; const [endpointAgentId, endpointHostname] = generateRandomStringName(2); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/endpoint_role_rbac.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/endpoint_role_rbac.cy.ts index a3198d894076e..07840c05b85de 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/endpoint_role_rbac.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/endpoint_role_rbac.cy.ts @@ -9,7 +9,7 @@ import { closeAllToasts } from '../../tasks/toasts'; import { login } from '../../tasks/login'; import { loadPage } from '../../tasks/common'; -describe('When defining a kibana role for Endpoint security access', () => { +describe('When defining a kibana role for Endpoint security access', { tags: '@ess' }, () => { const getAllSubFeatureRows = (): Cypress.Chainable> => { return cy .get('#featurePrivilegeControls_siem') diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/endpoints.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/endpoints.cy.ts index ce9533d857677..5804143f3b19c 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/endpoints.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/endpoints.cy.ts @@ -13,7 +13,7 @@ import { indexEndpointHosts } from '../../tasks/index_endpoint_hosts'; import { login } from '../../tasks/login'; import { loadPage } from '../../tasks/common'; -describe('Endpoints page', () => { +describe('Endpoints page', { tags: '@ess' }, () => { let endpointData: ReturnTypeFromChainable; before(() => { diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/isolate.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/isolate.cy.ts index 549b1c4e2a328..8998ec3cc32b7 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/isolate.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/isolate.cy.ts @@ -29,7 +29,7 @@ import { indexNewCase } from '../../tasks/index_new_case'; import { indexEndpointHosts } from '../../tasks/index_endpoint_hosts'; import { indexEndpointRuleAlerts } from '../../tasks/index_endpoint_rule_alerts'; -describe('Isolate command', () => { +describe('Isolate command', { tags: '@ess' }, () => { describe('from Manage', () => { let endpointData: ReturnTypeFromChainable | undefined; let isolatedEndpointData: ReturnTypeFromChainable | undefined; @@ -165,6 +165,7 @@ describe('Isolate command', () => { cy.contains(`Isolation on host ${hostname} successfully submitted`); cy.getByTestSubj('euiFlyoutCloseButton').click(); + // eslint-disable-next-line cypress/no-unnecessary-waiting cy.wait(1000); openAlertDetails(); diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/policy_details.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/policy_details.cy.ts index 543ce48ffb79d..11800441fc035 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/policy_details.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/policy_details.cy.ts @@ -17,7 +17,7 @@ import type { CyIndexEndpointHosts } from '../../tasks/index_endpoint_hosts'; import { indexEndpointHosts } from '../../tasks/index_endpoint_hosts'; import { login } from '../../tasks/login'; -describe('Policy Details', () => { +describe('Policy Details', { tags: ['@ess', '@serverless'] }, () => { const packagePolicyBackupHelper = new PackagePolicyBackupHelper(); let indexedHostsData: CyIndexEndpointHosts; diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/policy_response.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/policy_response.cy.ts index cb846a62317fb..a74a36bf38f60 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/policy_response.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/policy_response.cy.ts @@ -15,7 +15,7 @@ import { navigateToFleetAgentDetails } from '../../screens/fleet'; import { EndpointPolicyResponseGenerator } from '../../../../../common/endpoint/data_generators/endpoint_policy_response_generator'; import { descriptions } from '../../../components/policy_response/policy_response_friendly_names'; -describe.skip('Endpoint Policy Response', () => { +describe.skip('Endpoint Policy Response', { tags: '@ess' }, () => { let loadedEndpoint: CyIndexEndpointHosts; let endpointMetadata: HostMetadata; let loadedPolicyResponse: IndexedEndpointPolicyResponse; diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/reponse_actions_history.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/reponse_actions_history.cy.ts index 5c4bb0f3efb8c..7d1fe8b40a51e 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/reponse_actions_history.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/reponse_actions_history.cy.ts @@ -10,7 +10,7 @@ import { indexEndpointHosts } from '../../tasks/index_endpoint_hosts'; import { login } from '../../tasks/login'; import { loadPage } from '../../tasks/common'; -describe('Response actions history page', () => { +describe('Response actions history page', { tags: '@ess' }, () => { let endpointData: ReturnTypeFromChainable; // let actionData: ReturnTypeFromChainable; @@ -54,16 +54,16 @@ describe('Response actions history page', () => { it('collapses expanded tray with a single click', () => { loadPage(`/app/security/administration/response_actions_history`); // 2nd row on 1st page - const row = cy.getByTestSubj('response-actions-list-expand-button').eq(1); + cy.getByTestSubj('response-actions-list-expand-button').eq(1).as('2nd-row'); // expand the row - row.click(); + cy.get('@2nd-row').click(); cy.getByTestSubj('response-actions-list-details-tray').should('exist'); cy.url().should('include', 'withOutputs'); // collapse the row cy.intercept('GET', '/api/endpoint/action*').as('getResponses'); - row.click(); + cy.get('@2nd-row').click(); // wait for the API response to come back // and then see if the tray is actually closed cy.wait('@getResponses', { timeout: 500 }).then(() => { diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/responder.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/responder.cy.ts index 60775450c35e0..1e699300d1dab 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/responder.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/responder.cy.ts @@ -21,7 +21,7 @@ import { indexNewCase } from '../../tasks/index_new_case'; import { indexEndpointHosts } from '../../tasks/index_endpoint_hosts'; import { indexEndpointRuleAlerts } from '../../tasks/index_endpoint_rule_alerts'; -describe('When accessing Endpoint Response Console', () => { +describe('When accessing Endpoint Response Console', { tags: '@ess' }, () => { const performResponderSanityChecks = () => { openResponderActionLogFlyout(); // Ensure the popover in the action log date quick select picker is accessible diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/response_console.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/response_console.cy.ts index fa347d77581ae..9bfc4ff5fc58d 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/response_console.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/mocked_data/response_console.cy.ts @@ -24,7 +24,7 @@ import { } from '../../tasks/isolate'; import { login } from '../../tasks/login'; -describe('Response console', () => { +describe('Response console', { tags: '@ess' }, () => { beforeEach(() => { login(); }); diff --git a/x-pack/plugins/security_solution/public/management/cypress/screens/alerts.ts b/x-pack/plugins/security_solution/public/management/cypress/screens/alerts.ts index d9077bfb984a9..a1e53cee9b09a 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/screens/alerts.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/screens/alerts.ts @@ -13,7 +13,8 @@ export const navigateToAlertsList = (urlQueryParams: string = '') => { }; export const clickAlertListRefreshButton = (): Cypress.Chainable => { - return cy.getByTestSubj('querySubmitButton').click().should('be.enabled'); + cy.getByTestSubj('querySubmitButton').click(); + return cy.getByTestSubj('querySubmitButton').should('be.enabled'); }; /** diff --git a/x-pack/plugins/security_solution/public/management/cypress/support/e2e.ts b/x-pack/plugins/security_solution/public/management/cypress/support/e2e.ts index 0c60549e02850..7c8bf5104524b 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/support/e2e.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/support/e2e.ts @@ -24,11 +24,13 @@ import { subj as testSubjSelector } from '@kbn/test-subj-selector'; -// force ESM in this module -export {}; - import 'cypress-react-selector'; +// @ts-ignore +import registerCypressGrep from '@cypress/grep'; + +registerCypressGrep(); + Cypress.Commands.addQuery<'getByTestSubj'>( 'getByTestSubj', function getByTestSubj(selector, options) { diff --git a/x-pack/plugins/security_solution/public/management/cypress/tasks/alerts.ts b/x-pack/plugins/security_solution/public/management/cypress/tasks/alerts.ts index 0ff00c181b26d..30679364bd2f8 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/tasks/alerts.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/tasks/alerts.ts @@ -181,7 +181,7 @@ export const getEndpointDetectionAlertsQueryForAgentId = (endpointAgentId: strin export const changeAlertsFilter = (text: string) => { cy.getByTestSubj('filters-global-container').within(() => { - cy.getByTestSubj('queryInput').click().type(text); + cy.getByTestSubj('queryInput').type(text); cy.getByTestSubj('querySubmitButton').click(); }); }; diff --git a/x-pack/plugins/security_solution/public/management/cypress/tasks/common.ts b/x-pack/plugins/security_solution/public/management/cypress/tasks/common.ts index 38866ec5b5d29..ceba06f142f35 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/tasks/common.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/tasks/common.ts @@ -13,6 +13,7 @@ export const API_AUTH = Object.freeze({ export const COMMON_API_HEADERS = Object.freeze({ 'kbn-xsrf': 'cypress', 'x-elastic-internal-origin': 'security-solution', + 'Elastic-Api-Version': '2023-10-31', }); export const waitForPageToBeLoaded = () => { diff --git a/x-pack/plugins/security_solution/public/management/cypress/tasks/isolate.ts b/x-pack/plugins/security_solution/public/management/cypress/tasks/isolate.ts index 2c76247b24780..a15a71f1362eb 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/tasks/isolate.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/tasks/isolate.ts @@ -5,6 +5,8 @@ * 2.0. */ +/* eslint-disable cypress/no-unnecessary-waiting */ + import type { ActionDetails } from '../../../../common/endpoint/types'; import { loadPage } from './common'; @@ -114,7 +116,7 @@ export const filterOutEndpoints = (endpointHostname: string): void => { }; export const filterOutIsolatedHosts = (): void => { - cy.getByTestSubj('adminSearchBar').click().type('united.endpoint.Endpoint.state.isolation: true'); + cy.getByTestSubj('adminSearchBar').type('united.endpoint.Endpoint.state.isolation: true'); cy.getByTestSubj('querySubmitButton').click(); }; diff --git a/x-pack/plugins/security_solution/public/management/cypress/tasks/response_actions.ts b/x-pack/plugins/security_solution/public/management/cypress/tasks/response_actions.ts index 911f8a0511c11..edeff5fc366eb 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/tasks/response_actions.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/tasks/response_actions.ts @@ -84,9 +84,6 @@ export const waitForActionToComplete = ( return request({ method: 'GET', url: resolvePathVariables(ACTION_DETAILS_ROUTE, { action_id: actionId || 'undefined' }), - headers: { - 'Elastic-Api-Version': '2023-10-31', - }, }).then((response) => { if (response.body.data.isCompleted) { action = response.body.data; diff --git a/x-pack/plugins/security_solution/public/management/cypress/tasks/response_console.ts b/x-pack/plugins/security_solution/public/management/cypress/tasks/response_console.ts index 19ef3c5d68d37..958f16abad5c6 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/tasks/response_console.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/tasks/response_console.ts @@ -22,13 +22,11 @@ export const openResponseConsoleFromEndpointList = (): void => { }; export const inputConsoleCommand = (command: string): void => { - cy.getByTestSubj('endpointResponseActionsConsole-inputCapture').click().type(command); + cy.getByTestSubj('endpointResponseActionsConsole-inputCapture').type(command); }; export const clearConsoleCommandInput = (): void => { - cy.getByTestSubj('endpointResponseActionsConsole-inputCapture') - .click() - .type(`{selectall}{backspace}`); + cy.getByTestSubj('endpointResponseActionsConsole-inputCapture').type(`{selectall}{backspace}`); }; export const selectCommandFromHelpMenu = (command: string): void => { diff --git a/x-pack/plugins/security_solution/public/management/cypress/tasks/run_endpoint_loader.ts b/x-pack/plugins/security_solution/public/management/cypress/tasks/run_endpoint_loader.ts index 36c06e8aee59b..71d9ec58e80ab 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/tasks/run_endpoint_loader.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/tasks/run_endpoint_loader.ts @@ -6,8 +6,13 @@ */ export const runEndpointLoaderScript = () => { - const { ELASTICSEARCH_USERNAME, ELASTICSEARCH_PASSWORD, ELASTICSEARCH_URL, KIBANA_URL } = - Cypress.env(); + const { + ELASTICSEARCH_USERNAME, + ELASTICSEARCH_PASSWORD, + ELASTICSEARCH_URL, + KIBANA_URL, + IS_SERVERLESS, + } = Cypress.env(); const ES_URL = new URL(ELASTICSEARCH_URL); ES_URL.username = ELASTICSEARCH_USERNAME; @@ -16,8 +21,23 @@ export const runEndpointLoaderScript = () => { const KBN_URL = new URL(KIBANA_URL); KBN_URL.username = ELASTICSEARCH_USERNAME; KBN_URL.password = ELASTICSEARCH_PASSWORD; + // FIXME: remove use of cli script and use instead data loaders - const script = `node scripts/endpoint/resolver_generator.js --node="${ES_URL.toString()}" --kibana="${KBN_URL.toString()}" --delete --numHosts=1 --numDocs=1 --fleet --withNewUser=santaEndpoint:changeme --anc=1 --gen=1 --ch=1 --related=1 --relAlerts=1`; + const script = + `node scripts/endpoint/resolver_generator.js ` + + `--node="${ES_URL.toString()}" ` + + `--kibana="${KBN_URL.toString()}" ` + + `--delete ` + + `--numHosts=1 ` + + `--numDocs=1 ` + + `--fleet ` + + `--withNewUser=santaEndpoint:changeme ` + + `--anc=1 ` + + `--gen=1 ` + + `--ch=1 ` + + `--related=1 ` + + `--relAlerts=1 ` + + `--ssl=${IS_SERVERLESS}`; cy.exec(script, { env: { NODE_TLS_REJECT_UNAUTHORIZED: 1 }, timeout: 180000 }); }; diff --git a/x-pack/plugins/security_solution/public/management/cypress/tsconfig.json b/x-pack/plugins/security_solution/public/management/cypress/tsconfig.json index dc0b2e1ca4fd4..4d7fe47ec2d23 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/tsconfig.json +++ b/x-pack/plugins/security_solution/public/management/cypress/tsconfig.json @@ -2,9 +2,6 @@ "extends": "../../../../../../tsconfig.base.json", "include": [ "**/*", - "../cypress_endpoint.config.ts", - "../cypress.config.ts", - "./cypress.d.ts" ], "exclude": [ "target/**/*" diff --git a/x-pack/plugins/security_solution/public/management/cypress_endpoint.config.ts b/x-pack/plugins/security_solution/public/management/cypress_endpoint.config.ts deleted file mode 100644 index cd1a4c506bc38..0000000000000 --- a/x-pack/plugins/security_solution/public/management/cypress_endpoint.config.ts +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { defineCypressConfig } from '@kbn/cypress-config'; -// eslint-disable-next-line @kbn/imports/no_boundary_crossing -import { dataLoaders, dataLoadersForRealEndpoints } from './cypress/support/data_loaders'; -// eslint-disable-next-line @kbn/imports/no_boundary_crossing -import { responseActionTasks } from './cypress/support/response_actions'; - -// eslint-disable-next-line import/no-default-export -export default defineCypressConfig({ - reporter: '../../../../node_modules/cypress-multi-reporters', - reporterOptions: { - configFile: './public/management/reporter_config.json', - }, - - defaultCommandTimeout: 60000, - execTimeout: 120000, - pageLoadTimeout: 12000, - - retries: { - runMode: 1, - openMode: 0, - }, - - screenshotsFolder: - '../../../target/kibana-security-solution/public/management/cypress/screenshots', - trashAssetsBeforeRuns: false, - video: false, - viewportHeight: 900, - viewportWidth: 1440, - experimentalStudio: true, - - env: { - 'cypress-react-selector': { - root: '#security-solution-app', - }, - KIBANA_USERNAME: 'system_indices_superuser', - KIBANA_PASSWORD: 'changeme', - ELASTICSEARCH_USERNAME: 'system_indices_superuser', - ELASTICSEARCH_PASSWORD: 'changeme', - }, - - e2e: { - experimentalMemoryManagement: true, - experimentalInteractiveRunEvents: true, - baseUrl: 'http://localhost:5620', - supportFile: 'public/management/cypress/support/e2e.ts', - specPattern: 'public/management/cypress/e2e/endpoint/*.cy.{js,jsx,ts,tsx}', - experimentalRunAllSpecs: true, - setupNodeEvents: (on: Cypress.PluginEvents, config: Cypress.PluginConfigOptions) => { - dataLoaders(on, config); - // Data loaders specific to "real" Endpoint testing - dataLoadersForRealEndpoints(on, config); - responseActionTasks(on, config); - }, - }, -}); diff --git a/x-pack/test/defend_workflows_cypress/endpoint_serverless_config.ts b/x-pack/test/defend_workflows_cypress/endpoint_serverless_config.ts new file mode 100644 index 0000000000000..ef7bda4d01d03 --- /dev/null +++ b/x-pack/test/defend_workflows_cypress/endpoint_serverless_config.ts @@ -0,0 +1,65 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { getLocalhostRealIp } from '@kbn/security-solution-plugin/scripts/endpoint/common/localhost_services'; +import { FtrConfigProviderContext } from '@kbn/test'; + +import { ExperimentalFeatures } from '@kbn/security-solution-plugin/common/experimental_features'; +import { DefendWorkflowsCypressCliTestRunner } from './runner'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const defendWorkflowsCypressConfig = await readConfigFile(require.resolve('./config.ts')); + const svlSharedConfig = await readConfigFile( + require.resolve('../../test_serverless/shared/config.base.ts') + ); + + const hostIp = getLocalhostRealIp(); + + const enabledFeatureFlags: Array = []; + + return { + ...svlSharedConfig.getAll(), + esTestCluster: { + ...svlSharedConfig.get('esTestCluster'), + serverArgs: [ + ...svlSharedConfig.get('esTestCluster.serverArgs'), + // define custom es server here + // API Keys is enabled at the top level + ], + }, + servers: { + ...svlSharedConfig.get('servers'), + fleetserver: { + protocol: 'https', + hostname: hostIp, + port: 8220, + }, + }, + kbnTestServer: { + ...svlSharedConfig.get('kbnTestServer'), + serverArgs: [ + ...svlSharedConfig.get('kbnTestServer.serverArgs'), + '--csp.strict=false', + '--csp.warnLegacyBrowsers=false', + '--serverless=security', + '--xpack.encryptedSavedObjects.encryptionKey="abcdefghijklmnopqrstuvwxyz123456"', + + '--xpack.security.enabled=true', + `--xpack.fleet.agents.fleet_server.hosts=["https://${hostIp}:8220"]`, + `--xpack.fleet.agents.elasticsearch.host=http://${hostIp}:${defendWorkflowsCypressConfig.get( + 'servers.elasticsearch.port' + )}`, + + // set the packagerTaskInterval to 5s in order to speed up test executions when checking fleet artifacts + '--xpack.securitySolution.packagerTaskInterval=5s', + + `--xpack.securitySolution.enableExperimental=${JSON.stringify(enabledFeatureFlags)}`, + ], + }, + testRunner: DefendWorkflowsCypressCliTestRunner, + }; +}