diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 26784390ca41f..def24b72f41c8 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1320,9 +1320,6 @@ x-pack/plugins/cloud_integrations/cloud_full_story/server/config.ts @elastic/kib /x-pack/test/security_solution_endpoint/ @elastic/security-defend-workflows /x-pack/test/security_solution_endpoint_api_int/ @elastic/security-defend-workflows /x-pack/test_serverless/shared/lib/security/kibana_roles/ @elastic/security-defend-workflows -/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management @elastic/security-defend-workflows -/x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management @elastic/security-defend-workflows -/x-pack/test_serverless/functional/test_suites/security/cypress/tasks/endpoint_management @elastic/security-defend-workflows /x-pack/plugins/security_solution_serverless/public/upselling/sections/endpoint_management @elastic/security-defend-workflows /x-pack/plugins/security_solution_serverless/server/endpoint @elastic/security-defend-workflows diff --git a/x-pack/plugins/osquery/cypress/support/e2e.ts b/x-pack/plugins/osquery/cypress/support/e2e.ts index 76a705cb5977c..ed267eaff8ac6 100644 --- a/x-pack/plugins/osquery/cypress/support/e2e.ts +++ b/x-pack/plugins/osquery/cypress/support/e2e.ts @@ -30,8 +30,8 @@ export {}; import 'cypress-react-selector'; import registerCypressGrep from '@cypress/grep'; -import type { ServerlessRoleName } from './roles'; import { login } from '../../../../test_serverless/functional/test_suites/security/cypress/tasks/login'; +import type { ServerlessRoleName } from './roles'; registerCypressGrep(); diff --git a/x-pack/plugins/osquery/cypress/tsconfig.json b/x-pack/plugins/osquery/cypress/tsconfig.json index b8e92e55bbd2e..11f17f033495b 100644 --- a/x-pack/plugins/osquery/cypress/tsconfig.json +++ b/x-pack/plugins/osquery/cypress/tsconfig.json @@ -29,6 +29,6 @@ }, "@kbn/security-solution-plugin", "@kbn/fleet-plugin", - "@kbn/cases-plugin" + "@kbn/cases-plugin", ] } 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 6d9af6162dbe7..2664dbcbb76a0 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 @@ -6,6 +6,12 @@ */ import type { Agent } from '@kbn/fleet-plugin/common'; +import { + AGENT_HOSTNAME_CELL, + AGENT_POLICY_CELL, + TABLE_ROW_ACTIONS, + TABLE_ROW_ACTIONS_MENU, +} from '../../screens'; import type { PolicyData } from '../../../../../common/endpoint/types'; import { APP_ENDPOINTS_PATH } from '../../../../../common/constants'; import { @@ -17,16 +23,10 @@ import { import type { IndexedFleetEndpointPolicyResponse } from '../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; import { login } from '../../tasks/login'; import { loadPage } from '../../tasks/common'; -import { - AGENT_HOSTNAME_CELL, - TABLE_ROW_ACTIONS, - TABLE_ROW_ACTIONS_MENU, - AGENT_POLICY_CELL, -} from '../../screens/endpoints'; import { FLEET_REASSIGN_POLICY_MODAL, FLEET_REASSIGN_POLICY_MODAL_CONFIRM_BUTTON, -} from '../../screens/fleet'; +} from '../../screens/fleet/agent_details'; import type { CreateAndEnrollEndpointHostResponse } from '../../../../../scripts/endpoint/common/endpoint_host_services'; import { createEndpointHost } from '../../tasks/create_endpoint_host'; import { deleteAllLoadedEndpointData } from '../../tasks/delete_all_endpoint_data'; 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 a74a36bf38f60..073bb92ea8f43 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 @@ -5,13 +5,13 @@ * 2.0. */ +import { navigateToEndpointPolicyResponse } from '../../screens'; import type { CyIndexEndpointHosts } from '../../tasks/index_endpoint_hosts'; import { indexEndpointHosts } from '../../tasks/index_endpoint_hosts'; -import { navigateToEndpointPolicyResponse } from '../../screens/endpoints'; import type { HostMetadata } from '../../../../../common/endpoint/types'; import type { IndexedEndpointPolicyResponse } from '../../../../../common/endpoint/data_loaders/index_endpoint_policy_response'; import { login } from '../../tasks/login'; -import { navigateToFleetAgentDetails } from '../../screens/fleet'; +import { navigateToFleetAgentDetails } from '../../screens/fleet/agent_details'; import { EndpointPolicyResponseGenerator } from '../../../../../common/endpoint/data_generators/endpoint_policy_response_generator'; import { descriptions } from '../../../components/policy_response/policy_response_friendly_names'; diff --git a/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/README.md b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/README.md new file mode 100644 index 0000000000000..cf77c126a3c16 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/README.md @@ -0,0 +1,6 @@ +# Serverless only test + +Directory contains tests that are only applicable to serverless. +Any other type of tests should be placed instead into the `./endpoint` directory or `./mocked_data` directories and tagged appropriately + + diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/endpoint_list_with_security_essentials.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/endpoint_list_with_security_essentials.cy.ts similarity index 83% rename from x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/endpoint_list_with_security_essentials.cy.ts rename to x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/endpoint_list_with_security_essentials.cy.ts index 826a9188ae6bf..16ed98c46c549 100644 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/endpoint_list_with_security_essentials.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/endpoint_list_with_security_essentials.cy.ts @@ -5,17 +5,15 @@ * 2.0. */ -import { login } from '../../tasks/login'; +import type { CyIndexEndpointHosts } from '../../tasks/index_endpoint_hosts'; +import { indexEndpointHosts } from '../../tasks/index_endpoint_hosts'; +import { loginServerless } from '../../tasks/login_serverless'; import { getConsoleActionMenuItem, getUnIsolateActionMenuItem, openRowActionMenu, visitEndpointList, -} from '../../screens/endpoint_management'; -import { - CyIndexEndpointHosts, - indexEndpointHosts, -} from '../../tasks/endpoint_management/index_endpoint_hosts'; +} from '../../screens'; describe( 'When on the Endpoint List in Security Essentials PLI', @@ -43,7 +41,7 @@ describe( }); beforeEach(() => { - login(); + loginServerless(); visitEndpointList(); openRowActionMenu(); }); diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/feature_access/complete.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/complete.cy.ts similarity index 81% rename from x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/feature_access/complete.cy.ts rename to x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/complete.cy.ts index c76bbe5150e3e..4eb4197cff70f 100644 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/feature_access/complete.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/complete.cy.ts @@ -5,11 +5,11 @@ * 2.0. */ -import { RESPONSE_ACTION_API_COMMANDS_NAMES } from '@kbn/security-solution-plugin/common/endpoint/service/response_actions/constants'; -import { login } from '../../../tasks/login'; -import { getNoPrivilegesPage } from '../../../screens/endpoint_management/common'; -import { getEndpointManagementPageList } from '../../../screens/endpoint_management'; -import { ensureResponseActionAuthzAccess } from '../../../tasks/endpoint_management'; +import { ensureResponseActionAuthzAccess } from '../../../tasks/response_actions'; +import { loginServerless, ServerlessUser } from '../../../tasks/login_serverless'; +import { RESPONSE_ACTION_API_COMMANDS_NAMES } from '../../../../../../common/endpoint/service/response_actions/constants'; +import { getNoPrivilegesPage } from '../../../screens/common'; +import { getEndpointManagementPageList } from '../../../screens'; describe( 'App Features for Security Complete PLI', @@ -30,7 +30,7 @@ describe( let password: string; beforeEach(() => { - login('endpoint_operations_analyst').then((response) => { + loginServerless(ServerlessUser.ENDPOINT_OPERATIONS_ANALYST).then((response) => { username = response.username; password = response.password; }); diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/feature_access/complete_with_endpoint.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/complete_with_endpoint.cy.ts similarity index 74% rename from x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/feature_access/complete_with_endpoint.cy.ts rename to x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/complete_with_endpoint.cy.ts index fc8a1e1a690fb..656821bea4bba 100644 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/feature_access/complete_with_endpoint.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/complete_with_endpoint.cy.ts @@ -5,11 +5,14 @@ * 2.0. */ -import { RESPONSE_ACTION_API_COMMANDS_NAMES } from '@kbn/security-solution-plugin/common/endpoint/service/response_actions/constants'; -import { login } from '../../../tasks/login'; -import { getAgentListTable, visitFleetAgentList } from '../../../screens'; -import { getEndpointManagementPageList } from '../../../screens/endpoint_management'; -import { ensureResponseActionAuthzAccess } from '../../../tasks/endpoint_management'; +import { ensureResponseActionAuthzAccess } from '../../../tasks/response_actions'; +import { loginServerless, ServerlessUser } from '../../../tasks/login_serverless'; +import { RESPONSE_ACTION_API_COMMANDS_NAMES } from '../../../../../../common/endpoint/service/response_actions/constants'; +import { + getEndpointManagementPageList, + getFleetAgentListTable, + visitFleetAgentList, +} from '../../../screens'; describe( 'App Features for Security Complete PLI with Endpoint Complete Addon', @@ -29,7 +32,7 @@ describe( let password: string; beforeEach(() => { - login('endpoint_operations_analyst').then((response) => { + loginServerless(ServerlessUser.ENDPOINT_OPERATIONS_ANALYST).then((response) => { username = response.username; password = response.password; }); @@ -50,7 +53,7 @@ describe( it(`should have access to Fleet`, () => { visitFleetAgentList(); - getAgentListTable().should('exist'); + getFleetAgentListTable().should('exist'); }); } ); diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/feature_access/essentials.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/essentials.cy.ts similarity index 81% rename from x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/feature_access/essentials.cy.ts rename to x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/essentials.cy.ts index da5da7a4fa5f9..29934be792c6d 100644 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/feature_access/essentials.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/essentials.cy.ts @@ -5,11 +5,11 @@ * 2.0. */ -import { RESPONSE_ACTION_API_COMMANDS_NAMES } from '@kbn/security-solution-plugin/common/endpoint/service/response_actions/constants'; -import { login } from '../../../tasks/login'; -import { getNoPrivilegesPage } from '../../../screens/endpoint_management/common'; -import { ensureResponseActionAuthzAccess } from '../../../tasks/endpoint_management'; -import { getEndpointManagementPageList } from '../../../screens/endpoint_management'; +import { ensureResponseActionAuthzAccess } from '../../../tasks/response_actions'; +import { loginServerless, ServerlessUser } from '../../../tasks/login_serverless'; +import { RESPONSE_ACTION_API_COMMANDS_NAMES } from '../../../../../../common/endpoint/service/response_actions/constants'; +import { getNoPrivilegesPage } from '../../../screens/common'; +import { getEndpointManagementPageList } from '../../../screens'; describe( 'App Features for Security Essential PLI', @@ -32,7 +32,7 @@ describe( let password: string; beforeEach(() => { - login('endpoint_operations_analyst').then((response) => { + loginServerless(ServerlessUser.ENDPOINT_OPERATIONS_ANALYST).then((response) => { username = response.username; password = response.password; }); diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/feature_access/essentials_with_endpoint.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/essentials_with_endpoint.cy.ts similarity index 81% rename from x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/feature_access/essentials_with_endpoint.cy.ts rename to x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/essentials_with_endpoint.cy.ts index 86295ef1d28c0..020710ab4bf1a 100644 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/feature_access/essentials_with_endpoint.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/feature_access/essentials_with_endpoint.cy.ts @@ -5,11 +5,14 @@ * 2.0. */ -import { RESPONSE_ACTION_API_COMMANDS_NAMES } from '@kbn/security-solution-plugin/common/endpoint/service/response_actions/constants'; -import { login } from '../../../tasks/login'; -import { getAgentListTable, visitFleetAgentList } from '../../../screens'; -import { getEndpointManagementPageMap } from '../../../screens/endpoint_management'; -import { ensureResponseActionAuthzAccess } from '../../../tasks/endpoint_management'; +import { ensureResponseActionAuthzAccess } from '../../../tasks/response_actions'; +import { loginServerless, ServerlessUser } from '../../../tasks/login_serverless'; +import { RESPONSE_ACTION_API_COMMANDS_NAMES } from '../../../../../../common/endpoint/service/response_actions/constants'; +import { + getEndpointManagementPageMap, + getFleetAgentListTable, + visitFleetAgentList, +} from '../../../screens'; describe( 'App Features for Security Essentials PLI with Endpoint Essentials Addon', @@ -37,7 +40,7 @@ describe( let password: string; beforeEach(() => { - login('endpoint_operations_analyst').then((response) => { + loginServerless(ServerlessUser.ENDPOINT_OPERATIONS_ANALYST).then((response) => { username = response.username; password = response.password; }); @@ -71,7 +74,7 @@ describe( it(`should have access to Fleet`, () => { visitFleetAgentList(); - getAgentListTable().should('exist'); + getFleetAgentListTable().should('exist'); }); } ); diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/policy_details_with_security_essentials.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/policy_details_with_security_essentials.cy.ts similarity index 75% rename from x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/policy_details_with_security_essentials.cy.ts rename to x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/policy_details_with_security_essentials.cy.ts index 582a9c510c4c3..e9dea7475699c 100644 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/policy_details_with_security_essentials.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/policy_details_with_security_essentials.cy.ts @@ -5,9 +5,9 @@ * 2.0. */ -import { IndexedFleetEndpointPolicyResponse } from '@kbn/security-solution-plugin/common/endpoint/data_loaders/index_fleet_endpoint_policy'; -import { login } from '../../tasks/login'; -import { visitPolicyDetails } from '../../screens/endpoint_management/policy_details'; +import { loginServerless } from '../../tasks/login_serverless'; +import { visitPolicyDetailsPage } from '../../screens/policy_details'; +import type { IndexedFleetEndpointPolicyResponse } from '../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy'; describe( 'When displaying the Policy Details in Security Essentials PLI', @@ -34,8 +34,8 @@ describe( }); beforeEach(() => { - login(); - visitPolicyDetails(loadedPolicyData.integrationPolicies[0].id); + loginServerless(); + visitPolicyDetailsPage(loadedPolicyData.integrationPolicies[0].id); }); it('should display upselling section for protections', () => { diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/roles/complete_with_endpoint_roles.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/roles/complete_with_endpoint_roles.cy.ts similarity index 79% rename from x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/roles/complete_with_endpoint_roles.cy.ts rename to x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/roles/complete_with_endpoint_roles.cy.ts index 2311a803043f2..41ecdfe6ca140 100644 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/roles/complete_with_endpoint_roles.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/roles/complete_with_endpoint_roles.cy.ts @@ -6,10 +6,12 @@ */ import { pick } from 'lodash'; -import { login } from '../../../tasks/login'; -import { ServerlessRoleName } from '../../../../../../../shared/lib'; +import type { CyIndexEndpointHosts } from '../../../tasks/index_endpoint_hosts'; +import { indexEndpointHosts } from '../../../tasks/index_endpoint_hosts'; +import { loginServerless, ServerlessUser } from '../../../tasks/login_serverless'; +import { ensurePolicyDetailsPageAuthzAccess } from '../../../screens/policy_details'; +import type { EndpointArtifactPageId } from '../../../screens'; import { - EndpointArtifactPageId, ensureArtifactPageAuthzAccess, ensureEndpointListPageAuthzAccess, ensurePolicyListPageAuthzAccess, @@ -21,21 +23,12 @@ import { openRowActionMenu, visitEndpointList, visitPolicyList, -} from '../../../screens/endpoint_management'; -import { - ensurePermissionDeniedScreen, - getAgentListTable, + ensureFleetPermissionDeniedScreen, + getFleetAgentListTable, visitFleetAgentList, -} from '../../../screens'; -import { getConsoleHelpPanelResponseActionTestSubj, openConsoleHelpPanel, -} from '../../../screens/endpoint_management/response_console'; -import { ensurePolicyDetailsPageAuthzAccess } from '../../../screens/endpoint_management/policy_details'; -import { - CyIndexEndpointHosts, - indexEndpointHosts, -} from '../../../tasks/endpoint_management/index_endpoint_hosts'; +} from '../../../screens'; describe( 'User Roles for Security Complete PLI with Endpoint Complete addon', @@ -69,12 +62,12 @@ describe( }); // roles `t1_analyst` and `t2_analyst` are very similar with exception of one page - (['t1_analyst', `t2_analyst`] as ServerlessRoleName[]).forEach((roleName) => { + (['t1_analyst', `t2_analyst`] as ServerlessUser[]).forEach((roleName) => { describe(`for role: ${roleName}`, () => { const deniedPages = allPages.filter((page) => page.id !== 'endpointList'); beforeEach(() => { - login(roleName); + loginServerless(roleName); }); it('should have READ access to Endpoint list page', () => { @@ -98,7 +91,7 @@ describe( it('should NOT have access to Fleet', () => { visitFleetAgentList(); - ensurePermissionDeniedScreen(); + ensureFleetPermissionDeniedScreen(); }); it('should NOT have access to execute response actions', () => { @@ -130,7 +123,7 @@ describe( const deniedResponseActions = pick(consoleHelpPanelResponseActionsTestSubj, 'execute'); beforeEach(() => { - login('t3_analyst'); + loginServerless(ServerlessUser.T3_ANALYST); }); it('should have access to Endpoint list page', () => { @@ -154,7 +147,7 @@ describe( it('should NOT have access to Fleet', () => { visitFleetAgentList(); - ensurePermissionDeniedScreen(); + ensureFleetPermissionDeniedScreen(); }); describe('Response Actions access', () => { @@ -182,7 +175,7 @@ describe( const deniedPages = allPages.filter(({ id }) => id !== 'blocklist' && id !== 'endpointList'); beforeEach(() => { - login('threat_intelligence_analyst'); + loginServerless(ServerlessUser.THREAT_INTELLIGENCE_ANALYST); }); it('should have access to Endpoint list page', () => { @@ -205,7 +198,7 @@ describe( it('should NOT have access to Fleet', () => { visitFleetAgentList(); - ensurePermissionDeniedScreen(); + ensureFleetPermissionDeniedScreen(); }); it('should have access to Response Actions Log', () => { @@ -227,7 +220,7 @@ describe( ]; beforeEach(() => { - login('rule_author'); + loginServerless(ServerlessUser.RULE_AUTHOR); }); for (const { id, title } of artifactPagesFullAccess) { @@ -254,7 +247,7 @@ describe( it('should NOT have access to Fleet', () => { visitFleetAgentList(); - ensurePermissionDeniedScreen(); + ensureFleetPermissionDeniedScreen(); }); it('should have access to Response Actions Log', () => { @@ -278,7 +271,7 @@ describe( const grantedAccessPages = [pageById.endpointList, pageById.policyList]; beforeEach(() => { - login('soc_manager'); + loginServerless(ServerlessUser.SOC_MANAGER); }); for (const { id, title } of artifactPagesFullAccess) { @@ -296,7 +289,7 @@ describe( it('should NOT have access to Fleet', () => { visitFleetAgentList(); - ensurePermissionDeniedScreen(); + ensureFleetPermissionDeniedScreen(); }); describe('Response Actions access', () => { @@ -325,7 +318,7 @@ describe( const grantedAccessPages = [pageById.endpointList, pageById.policyList]; beforeEach(() => { - login('endpoint_operations_analyst'); + loginServerless(ServerlessUser.ENDPOINT_OPERATIONS_ANALYST); }); for (const { id, title } of artifactPagesFullAccess) { @@ -352,59 +345,57 @@ describe( it('should have access to Fleet', () => { visitFleetAgentList(); - getAgentListTable().should('exist'); + getFleetAgentListTable().should('exist'); }); }); - (['platform_engineer', 'endpoint_policy_manager'] as ServerlessRoleName[]).forEach( - (roleName) => { - describe(`for role: ${roleName}`, () => { - const artifactPagesFullAccess = [ - pageById.trustedApps, - pageById.eventFilters, - pageById.blocklist, - pageById.hostIsolationExceptions, - ]; - const grantedAccessPages = [pageById.endpointList, pageById.policyList]; - - beforeEach(() => { - login(roleName); - }); + (['platform_engineer', 'endpoint_policy_manager'] as ServerlessUser[]).forEach((roleName) => { + describe(`for role: ${roleName}`, () => { + const artifactPagesFullAccess = [ + pageById.trustedApps, + pageById.eventFilters, + pageById.blocklist, + pageById.hostIsolationExceptions, + ]; + const grantedAccessPages = [pageById.endpointList, pageById.policyList]; - for (const { id, title } of artifactPagesFullAccess) { - it(`should have CRUD access to: ${title}`, () => { - ensureArtifactPageAuthzAccess('all', id as EndpointArtifactPageId); - }); - } + beforeEach(() => { + loginServerless(roleName); + }); - for (const { url, title } of grantedAccessPages) { - it(`should have access to: ${title}`, () => { - cy.visit(url); - getNoPrivilegesPage().should('not.exist'); - }); - } + for (const { id, title } of artifactPagesFullAccess) { + it(`should have CRUD access to: ${title}`, () => { + ensureArtifactPageAuthzAccess('all', id as EndpointArtifactPageId); + }); + } - it('should have access to Fleet', () => { - visitFleetAgentList(); - getAgentListTable().should('exist'); + for (const { url, title } of grantedAccessPages) { + it(`should have access to: ${title}`, () => { + cy.visit(url); + getNoPrivilegesPage().should('not.exist'); }); + } - it('should have access to Response Actions Log', () => { - cy.visit(pageById.responseActionLog); + it('should have access to Fleet', () => { + visitFleetAgentList(); + getFleetAgentListTable().should('exist'); + }); - if (roleName === 'endpoint_policy_manager') { - getNoPrivilegesPage().should('exist'); - } else { - getNoPrivilegesPage().should('not.exist'); - } - }); + it('should have access to Response Actions Log', () => { + cy.visit(pageById.responseActionLog); - it('should NOT have access to execute response actions', () => { - visitEndpointList(); - openRowActionMenu().findByTestSubj('console').should('not.exist'); - }); + if (roleName === 'endpoint_policy_manager') { + getNoPrivilegesPage().should('exist'); + } else { + getNoPrivilegesPage().should('not.exist'); + } }); - } - ); + + it('should NOT have access to execute response actions', () => { + visitEndpointList(); + openRowActionMenu().findByTestSubj('console').should('not.exist'); + }); + }); + }); } ); diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/roles/essentials_with_endpoint.roles.cy.ts b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/roles/essentials_with_endpoint.roles.cy.ts similarity index 87% rename from x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/roles/essentials_with_endpoint.roles.cy.ts rename to x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/roles/essentials_with_endpoint.roles.cy.ts index c60095aa23c06..c1e41921dcc22 100644 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/roles/essentials_with_endpoint.roles.cy.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/e2e/serverless/roles/essentials_with_endpoint.roles.cy.ts @@ -5,28 +5,23 @@ * 2.0. */ -import { login } from '../../../tasks/login'; +import type { CyIndexEndpointHosts } from '../../../tasks/index_endpoint_hosts'; +import { indexEndpointHosts } from '../../../tasks/index_endpoint_hosts'; +import { loginServerless, ServerlessUser } from '../../../tasks/login_serverless'; +import type { EndpointArtifactPageId } from '../../../screens'; import { getNoPrivilegesPage, getArtifactListEmptyStateAddButton, getEndpointManagementPageMap, getEndpointManagementPageList, - EndpointArtifactPageId, ensureArtifactPageAuthzAccess, ensureEndpointListPageAuthzAccess, ensurePolicyListPageAuthzAccess, -} from '../../../screens/endpoint_management'; -import { - ensurePermissionDeniedScreen, - getAgentListTable, + ensureFleetPermissionDeniedScreen, + getFleetAgentListTable, visitFleetAgentList, + ensurePolicyDetailsPageAuthzAccess, } from '../../../screens'; -import { ServerlessRoleName } from '../../../../../../../shared/lib'; -import { ensurePolicyDetailsPageAuthzAccess } from '../../../screens/endpoint_management/policy_details'; -import { - CyIndexEndpointHosts, - indexEndpointHosts, -} from '../../../tasks/endpoint_management/index_endpoint_hosts'; describe( 'Roles for Security Essential PLI with Endpoint Essentials addon', @@ -59,12 +54,12 @@ describe( }); // roles `t1_analyst` and `t2_analyst` are the same as far as endpoint access - (['t1_analyst', `t2_analyst`] as ServerlessRoleName[]).forEach((roleName) => { + (['t1_analyst', `t2_analyst`] as ServerlessUser[]).forEach((roleName) => { describe(`for role: ${roleName}`, () => { const deniedPages = allPages.filter((page) => page.id !== 'endpointList'); beforeEach(() => { - login(roleName); + loginServerless(roleName); }); it('should have READ access to Endpoint list page', () => { @@ -80,7 +75,7 @@ describe( it('should NOT have access to Fleet', () => { visitFleetAgentList(); - ensurePermissionDeniedScreen(); + ensureFleetPermissionDeniedScreen(); }); }); }); @@ -93,7 +88,7 @@ describe( ]; beforeEach(() => { - login('t3_analyst'); + loginServerless(ServerlessUser.T3_ANALYST); }); it('should have access to Endpoint list page', () => { @@ -124,7 +119,7 @@ describe( it('should NOT have access to Fleet', () => { visitFleetAgentList(); - ensurePermissionDeniedScreen(); + ensureFleetPermissionDeniedScreen(); }); }); @@ -132,7 +127,7 @@ describe( const deniedPages = allPages.filter(({ id }) => id !== 'blocklist' && id !== 'endpointList'); beforeEach(() => { - login('threat_intelligence_analyst'); + loginServerless(ServerlessUser.THREAT_INTELLIGENCE_ANALYST); }); it('should have access to Endpoint list page', () => { @@ -155,7 +150,7 @@ describe( it('should NOT have access to Fleet', () => { visitFleetAgentList(); - ensurePermissionDeniedScreen(); + ensureFleetPermissionDeniedScreen(); }); }); @@ -167,7 +162,7 @@ describe( ]; beforeEach(() => { - login('rule_author'); + loginServerless(ServerlessUser.RULE_AUTHOR); }); for (const { id, title } of artifactPagesFullAccess) { @@ -198,7 +193,7 @@ describe( it('should NOT have access to Fleet', () => { visitFleetAgentList(); - ensurePermissionDeniedScreen(); + ensureFleetPermissionDeniedScreen(); }); }); @@ -211,7 +206,7 @@ describe( const grantedAccessPages = [pageById.endpointList, pageById.policyList]; beforeEach(() => { - login('soc_manager'); + loginServerless(ServerlessUser.SOC_MANAGER); }); for (const { id, title } of artifactPagesFullAccess) { @@ -236,7 +231,7 @@ describe( it('should NOT have access to Fleet', () => { visitFleetAgentList(); - ensurePermissionDeniedScreen(); + ensureFleetPermissionDeniedScreen(); }); }); @@ -246,7 +241,7 @@ describe( 'platform_engineer', `endpoint_operations_analyst`, 'endpoint_policy_manager', - ] as ServerlessRoleName[] + ] as ServerlessUser[] ).forEach((roleName) => { describe(`for role: ${roleName}`, () => { const artifactPagesFullAccess = [ @@ -257,7 +252,7 @@ describe( const grantedAccessPages = [pageById.endpointList, pageById.policyList]; beforeEach(() => { - login(roleName); + loginServerless(roleName); }); for (const { id, title } of artifactPagesFullAccess) { @@ -282,7 +277,7 @@ describe( it('should have access to Fleet', () => { visitFleetAgentList(); - getAgentListTable().should('exist'); + getFleetAgentListTable().should('exist'); }); }); }); diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/artifacts.ts b/x-pack/plugins/security_solution/public/management/cypress/screens/artifacts.ts similarity index 93% rename from x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/artifacts.ts rename to x-pack/plugins/security_solution/public/management/cypress/screens/artifacts.ts index abe0882ac9696..10bd7728197d7 100644 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/artifacts.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/screens/artifacts.ts @@ -5,14 +5,11 @@ * 2.0. */ -import { DeepReadonly } from 'utility-types'; +import type { DeepReadonly } from 'utility-types'; import { subj as testSubjSelector } from '@kbn/test-subj-selector'; -import { - EndpointArtifactPageId, - EndpointManagementPageMap, - getEndpointManagementPageMap, -} from './page_reference'; -import { UserAuthzAccessLevel } from './types'; +import type { EndpointArtifactPageId, EndpointManagementPageMap } from './page_reference'; +import { getEndpointManagementPageMap } from './page_reference'; +import type { UserAuthzAccessLevel } from './types'; const artifactPageTopTestSubjPrefix: Readonly> = { trustedApps: 'trustedAppsListPage', diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/common.ts b/x-pack/plugins/security_solution/public/management/cypress/screens/common.ts similarity index 100% rename from x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/common.ts rename to x-pack/plugins/security_solution/public/management/cypress/screens/common.ts diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/endpoint_list.ts b/x-pack/plugins/security_solution/public/management/cypress/screens/endpoint_list.ts similarity index 73% rename from x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/endpoint_list.ts rename to x-pack/plugins/security_solution/public/management/cypress/screens/endpoint_list.ts index a8cf41e6d9e16..e435602ebceb4 100644 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/endpoint_list.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/screens/endpoint_list.ts @@ -5,10 +5,14 @@ * 2.0. */ -import { DeepReadonly } from 'utility-types'; -import { EndpointManagementPageMap, getEndpointManagementPageMap } from './page_reference'; -import { UserAuthzAccessLevel } from './types'; +import type { DeepReadonly } from 'utility-types'; +import type { EndpointManagementPageMap } from './page_reference'; +import { getEndpointManagementPageMap } from './page_reference'; +import type { UserAuthzAccessLevel } from './types'; import { getNoPrivilegesPage } from './common'; +import { loadPage } from '../tasks/common'; +import { APP_PATH } from '../../../../common'; +import { getEndpointDetailsPath } from '../../common/routing'; interface ListRowOptions { endpointId?: string; @@ -17,6 +21,11 @@ interface ListRowOptions { rowIndex?: number; } +export const TABLE_ROW_ACTIONS_MENU = 'tableRowActionsMenuPanel'; +export const AGENT_HOSTNAME_CELL = 'hostnameCellLink'; +export const AGENT_POLICY_CELL = 'policyNameCellLink'; +export const TABLE_ROW_ACTIONS = 'endpointTableRowActions'; + const pageById: DeepReadonly = getEndpointManagementPageMap(); export const visitEndpointList = (): Cypress.Chainable => { @@ -81,3 +90,10 @@ export const getUnIsolateActionMenuItem = (): Cypress.Chainable => { export const getConsoleActionMenuItem = (): Cypress.Chainable => { return cy.getByTestSubj('tableRowActionsMenuPanel').findByTestSubj('console'); }; + +export const navigateToEndpointPolicyResponse = (endpointAgentId: string): void => { + loadPage( + APP_PATH + + getEndpointDetailsPath({ name: 'endpointPolicyResponse', selected_endpoint: endpointAgentId }) + ); +}; diff --git a/x-pack/plugins/security_solution/public/management/cypress/screens/endpoints.ts b/x-pack/plugins/security_solution/public/management/cypress/screens/endpoints.ts deleted file mode 100644 index ef5f7926e94dd..0000000000000 --- a/x-pack/plugins/security_solution/public/management/cypress/screens/endpoints.ts +++ /dev/null @@ -1,22 +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 { APP_PATH } from '../../../../common/constants'; -import { getEndpointDetailsPath } from '../../common/routing'; -import { loadPage } from '../tasks/common'; - -export const AGENT_HOSTNAME_CELL = 'hostnameCellLink'; -export const AGENT_POLICY_CELL = 'policyNameCellLink'; -export const TABLE_ROW_ACTIONS = 'endpointTableRowActions'; -export const TABLE_ROW_ACTIONS_MENU = 'tableRowActionsMenuPanel'; - -export const navigateToEndpointPolicyResponse = (endpointAgentId: string): void => { - loadPage( - APP_PATH + - getEndpointDetailsPath({ name: 'endpointPolicyResponse', selected_endpoint: endpointAgentId }) - ); -}; diff --git a/x-pack/plugins/security_solution/public/management/cypress/screens/fleet.ts b/x-pack/plugins/security_solution/public/management/cypress/screens/fleet/agent_details.ts similarity index 94% rename from x-pack/plugins/security_solution/public/management/cypress/screens/fleet.ts rename to x-pack/plugins/security_solution/public/management/cypress/screens/fleet/agent_details.ts index f1bf244c7558c..90b236173446f 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/screens/fleet.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/screens/fleet/agent_details.ts @@ -6,7 +6,7 @@ */ import { FLEET_BASE_PATH } from '@kbn/fleet-plugin/public/constants'; -import { loadPage } from '../tasks/common'; +import { loadPage } from '../../tasks/common'; export const FLEET_REASSIGN_POLICY_MODAL = 'agentReassignPolicyModal'; export const FLEET_REASSIGN_POLICY_MODAL_CONFIRM_BUTTON = 'confirmModalConfirmButton'; diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/screens/fleet/agent_list.ts b/x-pack/plugins/security_solution/public/management/cypress/screens/fleet/agent_list.ts similarity index 70% rename from x-pack/test_serverless/functional/test_suites/security/cypress/screens/fleet/agent_list.ts rename to x-pack/plugins/security_solution/public/management/cypress/screens/fleet/agent_list.ts index 02de2f51f048f..aace59c9422e1 100644 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/screens/fleet/agent_list.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/screens/fleet/agent_list.ts @@ -8,9 +8,11 @@ import { FLEET_BASE_PATH } from '@kbn/fleet-plugin/public/constants'; export const visitFleetAgentList = (): Cypress.Chainable => { + // `failOnStatus` below is necesary because the page (when not accessible) will actually return + // a `4xx` error along with an HTML page to display. return cy.visit(FLEET_BASE_PATH, { failOnStatusCode: false }); }; -export const getAgentListTable = (): Cypress.Chainable => { +export const getFleetAgentListTable = (): Cypress.Chainable => { return cy.getByTestSubj('fleetAgentListTable'); }; diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/screens/fleet/index.ts b/x-pack/plugins/security_solution/public/management/cypress/screens/fleet/index.ts similarity index 90% rename from x-pack/test_serverless/functional/test_suites/security/cypress/screens/fleet/index.ts rename to x-pack/plugins/security_solution/public/management/cypress/screens/fleet/index.ts index 5971df139f3bc..939dd8a30baa3 100644 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/screens/fleet/index.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/screens/fleet/index.ts @@ -7,3 +7,4 @@ export * from './permission_denied'; export * from './agent_list'; +export * from './agent_details'; diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/screens/fleet/permission_denied.ts b/x-pack/plugins/security_solution/public/management/cypress/screens/fleet/permission_denied.ts similarity index 87% rename from x-pack/test_serverless/functional/test_suites/security/cypress/screens/fleet/permission_denied.ts rename to x-pack/plugins/security_solution/public/management/cypress/screens/fleet/permission_denied.ts index e6bf6e4321716..5049ab7e22ad1 100644 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/screens/fleet/permission_denied.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/screens/fleet/permission_denied.ts @@ -9,6 +9,6 @@ * The screen normally returned by the API when a user does not have access to a Plugin. * Note that the requested page will likely also receive an HTTP status code of `403` */ -export const ensurePermissionDeniedScreen = (): Cypress.Chainable => { +export const ensureFleetPermissionDeniedScreen = (): Cypress.Chainable => { return cy.contains('You do not have permission to access the requested page').should('exist'); }; diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/index.ts b/x-pack/plugins/security_solution/public/management/cypress/screens/index.ts similarity index 83% rename from x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/index.ts rename to x-pack/plugins/security_solution/public/management/cypress/screens/index.ts index 54dcaaf7ee9c4..e1594d2b59f7e 100644 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/index.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/screens/index.ts @@ -8,6 +8,9 @@ export * from './common'; export * from './artifacts'; export * from './endpoint_list'; +export * from './policy_details'; export * from './policy_list'; export * from './page_reference'; +export * from './responder'; +export * from './fleet'; export * from './types'; diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/page_reference.ts b/x-pack/plugins/security_solution/public/management/cypress/screens/page_reference.ts similarity index 97% rename from x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/page_reference.ts rename to x-pack/plugins/security_solution/public/management/cypress/screens/page_reference.ts index a99a070b75b7d..5ebdeda5ddcbb 100644 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/page_reference.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/screens/page_reference.ts @@ -5,6 +5,7 @@ * 2.0. */ +import { keyBy } from 'lodash'; import { APP_BLOCKLIST_PATH, APP_ENDPOINTS_PATH, @@ -13,8 +14,7 @@ import { APP_POLICIES_PATH, APP_RESPONSE_ACTIONS_HISTORY_PATH, APP_TRUSTED_APPS_PATH, -} from '@kbn/security-solution-plugin/common/constants'; -import { keyBy } from 'lodash'; +} from '../../../../common/constants'; export interface EndpointManagementPageMap { endpointList: EndpointManagementPage; diff --git a/x-pack/plugins/security_solution/public/management/cypress/screens/policy_details.ts b/x-pack/plugins/security_solution/public/management/cypress/screens/policy_details.ts index 30b0b392ff456..863ca2283d887 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/screens/policy_details.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/screens/policy_details.ts @@ -13,11 +13,18 @@ import type { UpdatePackagePolicyResponse, } from '@kbn/fleet-plugin/common'; import { packagePolicyRouteService } from '@kbn/fleet-plugin/common'; +import type { UserAuthzAccessLevel } from './types'; import { APP_POLICIES_PATH } from '../../../../common/constants'; import type { PolicyConfig } from '../../../../common/endpoint/types'; -import { request, loadPage } from '../tasks/common'; +import { loadPage, request } from '../tasks/common'; import { expectAndCloseSuccessToast } from '../tasks/toasts'; +import { getNoPrivilegesPage } from './common'; +/** + * Loads the Policy details page - either for the `policyId` provided on input, or if undefined, + * then the first policy displayed on the Policy List will be opened + * @param policyId + */ export const visitPolicyDetailsPage = (policyId?: string) => { if (policyId) { loadPage(`${APP_POLICIES_PATH}/${policyId}`); @@ -89,3 +96,23 @@ export class PackagePolicyBackupHelper { }); } } + +export const ensurePolicyDetailsPageAuthzAccess = ( + policyId: string, + accessLevel: UserAuthzAccessLevel, + visitPage: boolean = false +): Cypress.Chainable => { + if (visitPage) { + visitPolicyDetailsPage(policyId); + } + + if (accessLevel === 'none') { + return getNoPrivilegesPage().should('exist'); + } + + if (accessLevel === 'read') { + return cy.getByTestSubj('policyDetailsSaveButton').should('not.exist'); + } + + return cy.getByTestSubj('policyDetailsSaveButton').should('exist'); +}; diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/policy_list.ts b/x-pack/plugins/security_solution/public/management/cypress/screens/policy_list.ts similarity index 79% rename from x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/policy_list.ts rename to x-pack/plugins/security_solution/public/management/cypress/screens/policy_list.ts index 6be7e37f16818..e72d0c3ecf93d 100644 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/policy_list.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/screens/policy_list.ts @@ -5,11 +5,12 @@ * 2.0. */ -import { DeepReadonly } from 'utility-types'; -import { EndpointManagementPageMap, getEndpointManagementPageMap } from './page_reference'; +import type { DeepReadonly } from 'utility-types'; +import type { EndpointManagementPageMap } from './page_reference'; +import { getEndpointManagementPageMap } from './page_reference'; import { getNoPrivilegesPage } from './common'; import { visitEndpointList } from './endpoint_list'; -import { UserAuthzAccessLevel } from './types'; +import type { UserAuthzAccessLevel } from './types'; const pageById: DeepReadonly = getEndpointManagementPageMap(); diff --git a/x-pack/plugins/security_solution/public/management/cypress/screens/responder.ts b/x-pack/plugins/security_solution/public/management/cypress/screens/responder.ts index ceacd2a5de13f..c9e320728ee23 100644 --- a/x-pack/plugins/security_solution/public/management/cypress/screens/responder.ts +++ b/x-pack/plugins/security_solution/public/management/cypress/screens/responder.ts @@ -6,6 +6,7 @@ */ import { subj as testSubjSelector } from '@kbn/test-subj-selector'; +import type { ConsoleResponseActionCommands } from '../../../../common/endpoint/service/response_actions/constants'; import { DATE_RANGE_OPTION_TO_TEST_SUBJ_MAP } from '../../../../common/test'; const TEST_SUBJ = Object.freeze({ @@ -13,6 +14,22 @@ const TEST_SUBJ = Object.freeze({ actionLogFlyout: 'responderActionLogFlyout', }); +export const getConsoleHelpPanelResponseActionTestSubj = (): Record< + ConsoleResponseActionCommands, + string +> => { + return { + isolate: 'endpointResponseActionsConsole-commandList-Responseactions-isolate', + release: 'endpointResponseActionsConsole-commandList-Responseactions-release', + processes: 'endpointResponseActionsConsole-commandList-Responseactions-processes', + 'kill-process': 'endpointResponseActionsConsole-commandList-Responseactions-kill-process', + 'suspend-process': 'endpointResponseActionsConsole-commandList-Responseactions-suspend-process', + 'get-file': 'endpointResponseActionsConsole-commandList-Responseactions-get-file', + execute: 'endpointResponseActionsConsole-commandList-Responseactions-execute', + upload: 'endpointResponseActionsConsole-commandList-Responseactions-upload', + }; +}; + const ensureOnResponder = (): Cypress.Chainable> => { return cy.getByTestSubj(TEST_SUBJ.responderPage).should('exist'); }; @@ -59,3 +76,8 @@ export const setResponderActionLogDateRange = ( cy.getByTestSubj(DATE_RANGE_OPTION_TO_TEST_SUBJ_MAP[range]).click(); cy.getByTestSubj('superDatePickerQuickMenu').should('not.exist'); }; + +export const openConsoleHelpPanel = (): Cypress.Chainable => { + ensureOnResponder(); + return cy.getByTestSubj('endpointResponseActionsConsole-header-helpButton').click(); +}; diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/types.ts b/x-pack/plugins/security_solution/public/management/cypress/screens/types.ts similarity index 100% rename from x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/types.ts rename to x-pack/plugins/security_solution/public/management/cypress/screens/types.ts diff --git a/x-pack/plugins/security_solution/public/management/cypress/tasks/login_serverless.ts b/x-pack/plugins/security_solution/public/management/cypress/tasks/login_serverless.ts new file mode 100644 index 0000000000000..533a17663e16b --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/cypress/tasks/login_serverless.ts @@ -0,0 +1,103 @@ +/* + * 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 type { LoginState } from '@kbn/security-plugin/common/login_state'; +import { COMMON_API_HEADERS, request } from './common'; + +export enum ServerlessUser { + T1_ANALYST = 't1_analyst', + T2_ANALYST = 't2_analyst', + T3_ANALYST = 't3_analyst', + THREAT_INTELLIGENCE_ANALYST = 'threat_intelligence_analyst', + RULE_AUTHOR = 'rule_author', + SOC_MANAGER = 'soc_manager', + DETECTIONS_ADMIN = 'detections_admin', + PLATFORM_ENGINEER = 'platform_engineer', + ENDPOINT_OPERATIONS_ANALYST = 'endpoint_operations_analyst', + ENDPOINT_POLICY_MANAGER = 'endpoint_policy_manager', +} + +/** + * Send login via API + * @param username + * @param password + * + * @private + */ +const sendApiLoginRequest = ( + username: string, + password: string +): Cypress.Chainable<{ username: string; password: string }> => { + const baseUrl = Cypress.config().baseUrl; + const headers = { ...COMMON_API_HEADERS }; + + cy.log(`Authenticating [${username}] via ${baseUrl}`); + + return request({ headers, url: `${baseUrl}/internal/security/login_state` }) + .then((loginState) => { + const basicProvider = loginState.body.selector.providers.find( + (provider) => provider.type === 'basic' + ); + + return request({ + url: `${baseUrl}/internal/security/login`, + method: 'POST', + headers, + body: { + providerType: basicProvider?.type, + providerName: basicProvider?.name, + currentURL: '/', + params: { username, password }, + }, + }); + }) + .then(() => ({ username, password })); +}; + +interface CyLoginTask { + (user?: ServerlessUser | 'elastic'): ReturnType; + + /** + * Login using any username/password + * @param username + * @param password + */ + with(username: string, password: string): ReturnType; +} + +/** + * Login to Kibana using API (not login page). By default, user will be logged in using + * the username and password defined via `KIBANA_USERNAME` and `KIBANA_PASSWORD` cypress env + * variables. + * @param user Defaults to `soc_manager` + */ +export const loginServerless: CyLoginTask = ( + user: ServerlessUser | 'elastic' = ServerlessUser.SOC_MANAGER +): ReturnType => { + const username = Cypress.env('KIBANA_USERNAME'); + const password = Cypress.env('KIBANA_PASSWORD'); + + if (user && user !== 'elastic') { + throw new Error('Serverless usernames not yet implemented'); + + // return cy.task('loadUserAndRole', { name: user }).then((loadedUser) => { + // username = loadedUser.username; + // password = loadedUser.password; + // + // return sendApiLoginRequest(username, password); + // }); + } else { + return sendApiLoginRequest(username, password); + } +}; + +loginServerless.with = ( + username: string, + password: string +): ReturnType => { + return sendApiLoginRequest(username, password); +}; 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 edeff5fc366eb..47f6da88c6924 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 @@ -5,10 +5,22 @@ * 2.0. */ -import { request, loadPage } from './common'; +import type { UserAuthzAccessLevel } from '../screens'; +import { loadPage, request } from './common'; import { resolvePathVariables } from '../../../common/utils/resolve_path_variables'; -import { ACTION_DETAILS_ROUTE } from '../../../../common/endpoint/constants'; +import { + ACTION_DETAILS_ROUTE, + EXECUTE_ROUTE, + GET_FILE_ROUTE, + GET_PROCESSES_ROUTE, + ISOLATE_HOST_ROUTE_V2, + KILL_PROCESS_ROUTE, + SUSPEND_PROCESS_ROUTE, + UNISOLATE_HOST_ROUTE_V2, + UPLOAD_ROUTE, +} from '../../../../common/endpoint/constants'; import type { ActionDetails, ActionDetailsApiResponse } from '../../../../common/endpoint/types'; +import type { ResponseActionsApiCommandNames } from '../../../../common/endpoint/service/response_actions/constants'; import { ENABLED_AUTOMATED_RESPONSE_ACTION_COMMANDS } from '../../../../common/endpoint/service/response_actions/constants'; export const validateAvailableCommands = () => { @@ -103,3 +115,95 @@ export const waitForActionToComplete = ( return action; }); }; + +/** + * Ensure user has the given `accessLevel` to the type of response action + * @param accessLevel + * @param responseAction + * @param username + * @param password + */ +export const ensureResponseActionAuthzAccess = ( + accessLevel: Exclude, + responseAction: ResponseActionsApiCommandNames, + username: string, + password: string +): Cypress.Chainable => { + let url: string = ''; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let apiPayload: any = { + endpoint_ids: ['some-id'], + }; + + switch (responseAction) { + case 'isolate': + url = ISOLATE_HOST_ROUTE_V2; + break; + + case 'unisolate': + url = UNISOLATE_HOST_ROUTE_V2; + break; + + case 'get-file': + url = GET_FILE_ROUTE; + Object.assign(apiPayload, { parameters: { path: 'one/two' } }); + break; + + case 'execute': + url = EXECUTE_ROUTE; + Object.assign(apiPayload, { parameters: { command: 'foo' } }); + break; + case 'running-processes': + url = GET_PROCESSES_ROUTE; + break; + + case 'kill-process': + url = KILL_PROCESS_ROUTE; + Object.assign(apiPayload, { parameters: { pid: 123 } }); + break; + + case 'suspend-process': + url = SUSPEND_PROCESS_ROUTE; + Object.assign(apiPayload, { parameters: { pid: 123 } }); + break; + + case 'upload': + url = UPLOAD_ROUTE; + { + const file = new File(['foo'], 'foo.txt'); + const formData = new FormData(); + + formData.append('file', file, file.name); + + for (const [key, value] of Object.entries(apiPayload as object)) { + formData.append(key, typeof value !== 'string' ? JSON.stringify(value) : value); + } + + apiPayload = formData; + } + break; + + default: + throw new Error(`Response action [${responseAction}] has no API payload defined`); + } + + const requestOptions: Partial = { + url, + method: 'post', + auth: { + user: username, + pass: password, + }, + headers: { + 'Content-Type': undefined, + }, + failOnStatusCode: false, + body: apiPayload as Cypress.RequestBody, + }; + + if (accessLevel === 'none') { + return request(requestOptions).its('status').should('equal', 403); + } + + return request(requestOptions).its('status').should('not.equal', 403); +}; diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/serverless.cy.ts b/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/serverless.cy.ts index 97b0a0fefad22..7000fe8ecca16 100644 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/serverless.cy.ts +++ b/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/serverless.cy.ts @@ -6,12 +6,16 @@ */ import { LEFT_NAVIGATION } from '../screens/landing_page'; -import { login } from '../tasks/login'; import { navigatesToLandingPage } from '../tasks/navigation'; describe('Serverless', () => { it('Should navigate to the landing page', () => { - login(); + cy.visit('/', { + auth: { + username: 'elastic_serverless', + password: 'changeme', + }, + }); navigatesToLandingPage(); cy.get(LEFT_NAVIGATION).should('exist'); }); diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/policy_details.ts b/x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/policy_details.ts deleted file mode 100644 index fd8fb40f2ac19..0000000000000 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/policy_details.ts +++ /dev/null @@ -1,34 +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 { APP_POLICIES_PATH } from '@kbn/security-solution-plugin/common/constants'; -import { UserAuthzAccessLevel } from './types'; -import { getNoPrivilegesPage } from './common'; - -export const visitPolicyDetails = (policyId: string): Cypress.Chainable => { - return cy.visit(`${APP_POLICIES_PATH}/${policyId}`); -}; - -export const ensurePolicyDetailsPageAuthzAccess = ( - policyId: string, - accessLevel: UserAuthzAccessLevel, - visitPage: boolean = false -): Cypress.Chainable => { - if (visitPage) { - visitPolicyDetails(policyId); - } - - if (accessLevel === 'none') { - return getNoPrivilegesPage().should('exist'); - } - - if (accessLevel === 'read') { - return cy.getByTestSubj('policyDetailsSaveButton').should('not.exist'); - } - - return cy.getByTestSubj('policyDetailsSaveButton').should('exist'); -}; diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/response_console.ts b/x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/response_console.ts deleted file mode 100644 index 1027a7e3cb5be..0000000000000 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/response_console.ts +++ /dev/null @@ -1,34 +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 { ConsoleResponseActionCommands } from '@kbn/security-solution-plugin/common/endpoint/service/response_actions/constants'; - -export const getConsoleHelpPanelResponseActionTestSubj = (): Record< - ConsoleResponseActionCommands, - string -> => { - return { - isolate: 'endpointResponseActionsConsole-commandList-Responseactions-isolate', - release: 'endpointResponseActionsConsole-commandList-Responseactions-release', - processes: 'endpointResponseActionsConsole-commandList-Responseactions-processes', - ['kill-process']: 'endpointResponseActionsConsole-commandList-Responseactions-kill-process', - ['suspend-process']: - 'endpointResponseActionsConsole-commandList-Responseactions-suspend-process', - ['get-file']: 'endpointResponseActionsConsole-commandList-Responseactions-get-file', - execute: 'endpointResponseActionsConsole-commandList-Responseactions-execute', - upload: 'endpointResponseActionsConsole-commandList-Responseactions-upload', - }; -}; - -export const ensureResponseConsoleIsOpen = (): Cypress.Chainable => { - return cy.getByTestSubj('consolePageOverlay').should('exist'); -}; - -export const openConsoleHelpPanel = (): Cypress.Chainable => { - ensureResponseConsoleIsOpen(); - return cy.getByTestSubj('endpointResponseActionsConsole-header-helpButton').click(); -}; diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/screens/index.ts b/x-pack/test_serverless/functional/test_suites/security/cypress/screens/index.ts index 415fddd939615..194bf6301191a 100644 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/screens/index.ts +++ b/x-pack/test_serverless/functional/test_suites/security/cypress/screens/index.ts @@ -5,5 +5,4 @@ * 2.0. */ -export * from './fleet'; export * from './landing_page'; diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/tasks/endpoint_management/index.ts b/x-pack/test_serverless/functional/test_suites/security/cypress/tasks/endpoint_management/index.ts deleted file mode 100644 index 539ac438bf57f..0000000000000 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/tasks/endpoint_management/index.ts +++ /dev/null @@ -1,8 +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. - */ - -export * from './response_actions'; diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/tasks/endpoint_management/response_actions.ts b/x-pack/test_serverless/functional/test_suites/security/cypress/tasks/endpoint_management/response_actions.ts deleted file mode 100644 index cf371fe63c40a..0000000000000 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/tasks/endpoint_management/response_actions.ts +++ /dev/null @@ -1,111 +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 { ResponseActionsApiCommandNames } from '@kbn/security-solution-plugin/common/endpoint/service/response_actions/constants'; -import { request } from '@kbn/security-solution-plugin/public/management/cypress/tasks/common'; -import { - EXECUTE_ROUTE, - GET_FILE_ROUTE, - GET_PROCESSES_ROUTE, - ISOLATE_HOST_ROUTE_V2, - KILL_PROCESS_ROUTE, - SUSPEND_PROCESS_ROUTE, - UNISOLATE_HOST_ROUTE_V2, - UPLOAD_ROUTE, -} from '@kbn/security-solution-plugin/common/endpoint/constants'; -import { UserAuthzAccessLevel } from '../../screens/endpoint_management'; - -/** - * Ensure user has the given `accessLevel` to the type of response action - * @param accessLevel - * @param responseAction - * @param username - * @param password - */ -export const ensureResponseActionAuthzAccess = ( - accessLevel: Exclude, - responseAction: ResponseActionsApiCommandNames, - username: string, - password: string -): Cypress.Chainable => { - let url: string = ''; - let apiPayload: any = { - endpoint_ids: ['some-id'], - }; - - switch (responseAction) { - case 'isolate': - url = ISOLATE_HOST_ROUTE_V2; - break; - - case 'unisolate': - url = UNISOLATE_HOST_ROUTE_V2; - break; - - case 'get-file': - url = GET_FILE_ROUTE; - Object.assign(apiPayload, { parameters: { path: 'one/two' } }); - break; - - case 'execute': - url = EXECUTE_ROUTE; - Object.assign(apiPayload, { parameters: { command: 'foo' } }); - break; - case 'running-processes': - url = GET_PROCESSES_ROUTE; - break; - - case 'kill-process': - url = KILL_PROCESS_ROUTE; - Object.assign(apiPayload, { parameters: { pid: 123 } }); - break; - - case 'suspend-process': - url = SUSPEND_PROCESS_ROUTE; - Object.assign(apiPayload, { parameters: { pid: 123 } }); - break; - - case 'upload': - url = UPLOAD_ROUTE; - { - const file = new File(['foo'], 'foo.txt'); - const formData = new FormData(); - - formData.append('file', file, file.name); - - for (const [key, value] of Object.entries(apiPayload as object)) { - formData.append(key, typeof value !== 'string' ? JSON.stringify(value) : value); - } - - apiPayload = formData; - } - break; - - default: - throw new Error(`Response action [${responseAction}] has no API payload defined`); - } - - const requestOptions: Partial = { - url, - method: 'post', - auth: { - user: username, - pass: password, - }, - headers: { - 'Content-Type': undefined, - }, - failOnStatusCode: false, - body: apiPayload as Cypress.RequestBody, - }; - - if (accessLevel === 'none') { - return request(requestOptions).its('status').should('equal', 403); - } - - return request(requestOptions).its('status').should('not.equal', 403); -}; diff --git a/x-pack/test_serverless/tsconfig.json b/x-pack/test_serverless/tsconfig.json index 1a94c23b6f1c1..7a075a2903860 100644 --- a/x-pack/test_serverless/tsconfig.json +++ b/x-pack/test_serverless/tsconfig.json @@ -41,9 +41,7 @@ "@kbn/security-solution-plugin", "@kbn/security-solution-plugin/public/management/cypress", "@kbn/tooling-log", - "@kbn/fleet-plugin", "@kbn/cases-plugin", - "@kbn/test-subj-selector", "@kbn/core-http-common", "@kbn/data-views-plugin", "@kbn/core-saved-objects-server",