diff --git a/x-pack/plugins/security_solution/common/endpoint/service/authz/authz.test.ts b/x-pack/plugins/security_solution/common/endpoint/service/authz/authz.test.ts index 332d7adde036f..8c3c697b80e2c 100644 --- a/x-pack/plugins/security_solution/common/endpoint/service/authz/authz.test.ts +++ b/x-pack/plugins/security_solution/common/endpoint/service/authz/authz.test.ts @@ -235,7 +235,15 @@ describe('Endpoint Authz service', () => { ].executePackageAction = true; const authz = calculateEndpointAuthz(licenseService, fleetAuthz, userRoles); - expect(authz.canAccessResponseConsole).toBe(true); + + // Having ONLY host isolation Release response action can only be true in a + // downgrade scenario, where we allow the user to continue to release isolated + // hosts. In that scenario, we don't show access to the response console + if (responseConsolePrivilege === 'writeHostIsolationRelease') { + expect(authz.canAccessResponseConsole).toBe(false); + } else { + expect(authz.canAccessResponseConsole).toBe(true); + } } ); }); diff --git a/x-pack/plugins/security_solution/common/endpoint/service/authz/authz.ts b/x-pack/plugins/security_solution/common/endpoint/service/authz/authz.ts index 26524dcc17888..c0c5ee06d5488 100644 --- a/x-pack/plugins/security_solution/common/endpoint/service/authz/authz.ts +++ b/x-pack/plugins/security_solution/common/endpoint/service/authz/authz.ts @@ -7,6 +7,8 @@ import type { ENDPOINT_PRIVILEGES, FleetAuthz } from '@kbn/fleet-plugin/common'; +import { omit } from 'lodash'; +import { RESPONSE_CONSOLE_ACTION_COMMANDS_TO_REQUIRED_AUTHZ } from '../response_actions/constants'; import type { LicenseService } from '../../../license'; import type { EndpointAuthz } from '../../types/authz'; import type { MaybeImmutable } from '../../types'; @@ -82,7 +84,7 @@ export const calculateEndpointAuthz = ( const canWriteExecuteOperations = hasKibanaPrivilege(fleetAuthz, 'writeExecuteOperations'); - return { + const authz: EndpointAuthz = { canWriteSecuritySolution, canReadSecuritySolution, canAccessFleet: fleetAuthz?.fleet.all ?? false, @@ -95,22 +97,22 @@ export const calculateEndpointAuthz = ( canWriteActionsLogManagement, canReadActionsLogManagement: canReadActionsLogManagement && isEnterpriseLicense, canAccessEndpointActionsLogManagement: canReadActionsLogManagement && isPlatinumPlusLicense, + + // --------------------------------------------------------- // Response Actions + // --------------------------------------------------------- canIsolateHost: canIsolateHost && isPlatinumPlusLicense, canUnIsolateHost, canKillProcess: canWriteProcessOperations && isEnterpriseLicense, canSuspendProcess: canWriteProcessOperations && isEnterpriseLicense, canGetRunningProcesses: canWriteProcessOperations && isEnterpriseLicense, - canAccessResponseConsole: - isEnterpriseLicense && - (canIsolateHost || - canUnIsolateHost || - canWriteProcessOperations || - canWriteFileOperations || - canWriteExecuteOperations), + canAccessResponseConsole: false, // set further below canWriteExecuteOperations: canWriteExecuteOperations && isEnterpriseLicense, canWriteFileOperations: canWriteFileOperations && isEnterpriseLicense, + + // --------------------------------------------------------- // artifacts + // --------------------------------------------------------- canWriteTrustedApplications, canReadTrustedApplications, canWriteHostIsolationExceptions: canWriteHostIsolationExceptions && isPlatinumPlusLicense, @@ -122,6 +124,20 @@ export const calculateEndpointAuthz = ( canWriteEventFilters, canReadEventFilters, }; + + // Response console is only accessible when license is Enterprise and user has access to any + // of the response actions except `release`. Sole access to `release` is something + // that is supported for a user in a license downgrade scenario, and in that case, we don't want + // to allow access to Response Console. + authz.canAccessResponseConsole = + isEnterpriseLicense && + Object.values(omit(RESPONSE_CONSOLE_ACTION_COMMANDS_TO_REQUIRED_AUTHZ, 'release')).some( + (responseActionAuthzKey) => { + return authz[responseActionAuthzKey]; + } + ); + + return authz; }; export const getEndpointAuthzInitialState = (): EndpointAuthz => { diff --git a/x-pack/plugins/security_solution/public/detections/components/host_isolation/use_host_isolation_action.tsx b/x-pack/plugins/security_solution/public/detections/components/host_isolation/use_host_isolation_action.tsx index 531053629e62b..818fd60afff1d 100644 --- a/x-pack/plugins/security_solution/public/detections/components/host_isolation/use_host_isolation_action.tsx +++ b/x-pack/plugins/security_solution/public/detections/components/host_isolation/use_host_isolation_action.tsx @@ -27,7 +27,9 @@ export const useHostIsolationAction = ({ detailsData, isHostIsolationPanelOpen, onAddIsolationStatusClick, -}: UseHostIsolationActionProps) => { +}: UseHostIsolationActionProps): AlertTableContextMenuItem[] => { + const { canIsolateHost, canUnIsolateHost } = useUserPrivileges().endpointPrivileges; + const isEndpointAlert = useMemo(() => { return isAlertFromEndpointEvent({ data: detailsData || [] }); }, [detailsData]); @@ -49,14 +51,14 @@ export const useHostIsolationAction = ({ const { loading: loadingHostIsolationStatus, - isIsolated: isolationStatus, + isIsolated: isHostIsolated, agentStatus, capabilities, } = useHostIsolationStatus({ agentId, }); - const isolationSupported = useMemo(() => { + const doesHostSupportIsolation = useMemo(() => { return isEndpointAlert ? isIsolationSupported({ osName: hostOsFamily, @@ -66,46 +68,45 @@ export const useHostIsolationAction = ({ : false; }, [agentVersion, capabilities, hostOsFamily, isEndpointAlert]); - const isIsolationAllowed = useUserPrivileges().endpointPrivileges.canIsolateHost; - const isolateHostHandler = useCallback(() => { closePopover(); - if (isolationStatus === false) { + if (!isHostIsolated) { onAddIsolationStatusClick('isolateHost'); } else { onAddIsolationStatusClick('unisolateHost'); } - }, [closePopover, isolationStatus, onAddIsolationStatusClick]); + }, [closePopover, isHostIsolated, onAddIsolationStatusClick]); + + return useMemo(() => { + if ( + !isEndpointAlert || + !doesHostSupportIsolation || + loadingHostIsolationStatus || + isHostIsolationPanelOpen + ) { + return []; + } - const isolateHostTitle = isolationStatus === false ? ISOLATE_HOST : UNISOLATE_HOST; + const menuItems = [ + { + key: 'isolate-host-action-item', + 'data-test-subj': 'isolate-host-action-item', + disabled: agentStatus === HostStatus.UNENROLLED, + onClick: isolateHostHandler, + name: isHostIsolated ? UNISOLATE_HOST : ISOLATE_HOST, + }, + ]; - const hostIsolationAction: AlertTableContextMenuItem[] = useMemo( - () => - isIsolationAllowed && - isEndpointAlert && - isolationSupported && - isHostIsolationPanelOpen === false && - loadingHostIsolationStatus === false - ? [ - { - key: 'isolate-host-action-item', - 'data-test-subj': 'isolate-host-action-item', - disabled: agentStatus === HostStatus.UNENROLLED, - onClick: isolateHostHandler, - name: isolateHostTitle, - }, - ] - : [], - [ - agentStatus, - isEndpointAlert, - isHostIsolationPanelOpen, - isIsolationAllowed, - isolateHostHandler, - isolateHostTitle, - isolationSupported, - loadingHostIsolationStatus, - ] - ); - return hostIsolationAction; + return canIsolateHost || (isHostIsolated && canUnIsolateHost) ? menuItems : []; + }, [ + isEndpointAlert, + doesHostSupportIsolation, + loadingHostIsolationStatus, + isHostIsolationPanelOpen, + agentStatus, + isolateHostHandler, + canIsolateHost, + isHostIsolated, + canUnIsolateHost, + ]); }; diff --git a/x-pack/plugins/security_solution/server/lib/app_features/security_kibana_features.ts b/x-pack/plugins/security_solution/server/lib/app_features/security_kibana_features.ts index 549ee7e7f9fdd..0a77e5a9e5d7e 100644 --- a/x-pack/plugins/security_solution/server/lib/app_features/security_kibana_features.ts +++ b/x-pack/plugins/security_solution/server/lib/app_features/security_kibana_features.ts @@ -122,9 +122,14 @@ export const getSecurityBaseKibanaFeature = (): BaseKibanaFeatureConfig => ({ }, }); +/** + * Returns the list of Security SubFeature IDs that should be loaded and available in + * kibana regardless of PLI or License level. + * @param _ + */ export const getSecurityBaseKibanaSubFeatureIds = ( _: ExperimentalFeatures // currently un-used, but left here as a convenience for possible future use -): SecuritySubFeatureId[] => []; +): SecuritySubFeatureId[] => [SecuritySubFeatureId.hostIsolation]; /** * Maps the AppFeatures keys to Kibana privileges that will be merged @@ -214,12 +219,13 @@ export const getSecurityAppFeaturesConfig = ( SecuritySubFeatureId.hostIsolationExceptions, SecuritySubFeatureId.responseActionsHistory, - SecuritySubFeatureId.hostIsolation, SecuritySubFeatureId.processOperations, SecuritySubFeatureId.fileOperations, SecuritySubFeatureId.executeAction, ], subFeaturesPrivileges: [ + // Adds the privilege to Isolate hosts to the already loaded `host_isolation_all` + // sub-feature (always loaded), which included the `release` privilege already { id: 'host_isolation_all', api: [`${APP_ID}-writeHostIsolation`], diff --git a/x-pack/plugins/security_solution/server/lib/app_features/security_kibana_sub_features.ts b/x-pack/plugins/security_solution/server/lib/app_features/security_kibana_sub_features.ts index a06ac83054560..a8410e4e4253d 100644 --- a/x-pack/plugins/security_solution/server/lib/app_features/security_kibana_sub_features.ts +++ b/x-pack/plugins/security_solution/server/lib/app_features/security_kibana_sub_features.ts @@ -396,7 +396,6 @@ const hostIsolationSubFeature: SubFeatureConfig = { groupType: 'mutually_exclusive', privileges: [ { - api: [`${APP_ID}-writeHostIsolationRelease`], id: 'host_isolation_all', includeIn: 'none', name: 'All', @@ -404,6 +403,11 @@ const hostIsolationSubFeature: SubFeatureConfig = { all: [], read: [], }, + // FYI: The current set of values below (`api`, `ui`) cover only `release` response action. + // There is a second set of values for API and UI that are added later if `endpointResponseActions` + // appFeature is enabled. Needed to ensure that in a downgrade of license condition, + // users are still able to un-isolate a host machine. + api: [`${APP_ID}-writeHostIsolationRelease`], ui: ['writeHostIsolationRelease'], }, ], diff --git a/x-pack/plugins/security_solution_serverless/common/pli/pli_config.ts b/x-pack/plugins/security_solution_serverless/common/pli/pli_config.ts index 779f874b266da..6122c65aa5de7 100644 --- a/x-pack/plugins/security_solution_serverless/common/pli/pli_config.ts +++ b/x-pack/plugins/security_solution_serverless/common/pli/pli_config.ts @@ -24,12 +24,7 @@ export const PLI_APP_FEATURES: PliAppFeatures = { ], }, endpoint: { - essentials: [ - AppFeatureKey.endpointHostManagement, - AppFeatureKey.endpointPolicyManagement, - AppFeatureKey.endpointPolicyProtections, - AppFeatureKey.endpointArtifactManagement, - ], + essentials: [AppFeatureKey.endpointPolicyProtections, AppFeatureKey.endpointArtifactManagement], complete: [ AppFeatureKey.endpointResponseActions, AppFeatureKey.osqueryAutomatedResponseActions, 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/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/endpoint_list_with_security_essentials.cy.ts new file mode 100644 index 0000000000000..826a9188ae6bf --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/endpoint_list_with_security_essentials.cy.ts @@ -0,0 +1,60 @@ +/* + * 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 { login } from '../../tasks/login'; +import { + getConsoleActionMenuItem, + getUnIsolateActionMenuItem, + openRowActionMenu, + visitEndpointList, +} from '../../screens/endpoint_management'; +import { + CyIndexEndpointHosts, + indexEndpointHosts, +} from '../../tasks/endpoint_management/index_endpoint_hosts'; + +describe( + 'When on the Endpoint List in Security Essentials PLI', + { + env: { + ftrConfig: { + productTypes: [{ product_line: 'security', product_tier: 'essentials' }], + }, + }, + }, + () => { + describe('and Isolated hosts exist', () => { + let indexedEndpointData: CyIndexEndpointHosts; + + before(() => { + indexEndpointHosts({ isolation: true }).then((response) => { + indexedEndpointData = response; + }); + }); + + after(() => { + if (indexedEndpointData) { + indexedEndpointData.cleanup(); + } + }); + + beforeEach(() => { + login(); + visitEndpointList(); + openRowActionMenu(); + }); + + it('should display `release` options in host row actions', () => { + getUnIsolateActionMenuItem().should('exist'); + }); + + it('should NOT display access to response console', () => { + getConsoleActionMenuItem().should('not.exist'); + }); + }); + } +); diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/feature_access/complete.cy.ts b/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/feature_access/complete.cy.ts index 09491e247e07e..c76bbe5150e3e 100644 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/feature_access/complete.cy.ts +++ b/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/feature_access/complete.cy.ts @@ -12,7 +12,7 @@ import { getEndpointManagementPageList } from '../../../screens/endpoint_managem import { ensureResponseActionAuthzAccess } from '../../../tasks/endpoint_management'; describe( - 'App Features for Complete PLI', + 'App Features for Security Complete PLI', { env: { ftrConfig: { productTypes: [{ product_line: 'security', product_tier: 'complete' }] }, @@ -50,10 +50,17 @@ describe( }); } - for (const actionName of RESPONSE_ACTION_API_COMMANDS_NAMES) { + // No access to response actions (except `unisolate`) + for (const actionName of RESPONSE_ACTION_API_COMMANDS_NAMES.filter( + (apiName) => apiName !== 'unisolate' + )) { it(`should not allow access to Response Action: ${actionName}`, () => { ensureResponseActionAuthzAccess('none', actionName, username, password); }); } + + it('should have access to `unisolate` api', () => { + ensureResponseActionAuthzAccess('all', 'unisolate', username, 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/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/feature_access/complete_with_endpoint.cy.ts index 9f27f5166fbe5..fc8a1e1a690fb 100644 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/feature_access/complete_with_endpoint.cy.ts +++ b/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/feature_access/complete_with_endpoint.cy.ts @@ -12,7 +12,7 @@ import { getEndpointManagementPageList } from '../../../screens/endpoint_managem import { ensureResponseActionAuthzAccess } from '../../../tasks/endpoint_management'; describe( - 'App Features for Complete PLI with Endpoint Complete', + 'App Features for Security Complete PLI with Endpoint Complete Addon', { env: { ftrConfig: { diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/feature_access/essentials.cy.ts b/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/feature_access/essentials.cy.ts index 0f86f1fad045e..da5da7a4fa5f9 100644 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/feature_access/essentials.cy.ts +++ b/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/feature_access/essentials.cy.ts @@ -12,7 +12,7 @@ import { ensureResponseActionAuthzAccess } from '../../../tasks/endpoint_managem import { getEndpointManagementPageList } from '../../../screens/endpoint_management'; describe( - 'App Features for Essential PLI', + 'App Features for Security Essential PLI', { env: { ftrConfig: { @@ -52,10 +52,17 @@ describe( }); } - for (const actionName of RESPONSE_ACTION_API_COMMANDS_NAMES) { - it(`should NOT allow access to Response Action: ${actionName}`, () => { + // No access to response actions (except `unisolate`) + for (const actionName of RESPONSE_ACTION_API_COMMANDS_NAMES.filter( + (apiName) => apiName !== 'unisolate' + )) { + it(`should not allow access to Response Action: ${actionName}`, () => { ensureResponseActionAuthzAccess('none', actionName, username, password); }); } + + it('should have access to `unisolate` api', () => { + ensureResponseActionAuthzAccess('all', 'unisolate', username, 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/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/feature_access/essentials_with_endpoint.cy.ts index 5d9be33243b3e..86295ef1d28c0 100644 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/feature_access/essentials_with_endpoint.cy.ts +++ b/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/feature_access/essentials_with_endpoint.cy.ts @@ -12,7 +12,7 @@ import { getEndpointManagementPageMap } from '../../../screens/endpoint_manageme import { ensureResponseActionAuthzAccess } from '../../../tasks/endpoint_management'; describe( - 'App Features for Essentials PLI with Endpoint Essentials', + 'App Features for Security Essentials PLI with Endpoint Essentials Addon', { env: { ftrConfig: { @@ -57,12 +57,18 @@ describe( }); } - for (const actionName of RESPONSE_ACTION_API_COMMANDS_NAMES) { + for (const actionName of RESPONSE_ACTION_API_COMMANDS_NAMES.filter( + (apiName) => apiName !== 'unisolate' + )) { it(`should not allow access to Response Action: ${actionName}`, () => { ensureResponseActionAuthzAccess('none', actionName, username, password); }); } + it('should have access to `unisolate` api', () => { + ensureResponseActionAuthzAccess('all', 'unisolate', username, password); + }); + it(`should have access to Fleet`, () => { visitFleetAgentList(); getAgentListTable().should('exist'); diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/policy_details_with_security_essentials.ts b/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/policy_details_with_security_essentials.cy.ts similarity index 100% rename from x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/policy_details_with_security_essentials.ts rename to x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/policy_details_with_security_essentials.cy.ts 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/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/roles/complete_with_endpoint_roles.cy.ts index 30247aae8201d..2311a803043f2 100644 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/roles/complete_with_endpoint_roles.cy.ts +++ b/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/roles/complete_with_endpoint_roles.cy.ts @@ -5,7 +5,6 @@ * 2.0. */ -import { IndexedHostsAndAlertsResponse } from '@kbn/security-solution-plugin/common/endpoint/index_data'; import { pick } from 'lodash'; import { login } from '../../../tasks/login'; import { ServerlessRoleName } from '../../../../../../../shared/lib'; @@ -33,6 +32,10 @@ import { 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'; describe( 'User Roles for Security Complete PLI with Endpoint Complete addon', @@ -51,17 +54,17 @@ describe( const pageById = getEndpointManagementPageMap(); const consoleHelpPanelResponseActionsTestSubj = getConsoleHelpPanelResponseActionTestSubj(); - let loadedEndpoints: IndexedHostsAndAlertsResponse; + let loadedEndpoints: CyIndexEndpointHosts; before(() => { - cy.task('indexEndpointHosts', {}, { timeout: 240000 }).then((response) => { + indexEndpointHosts().then((response) => { loadedEndpoints = response; }); }); after(() => { if (loadedEndpoints) { - cy.task('deleteIndexedEndpointHosts', loadedEndpoints); + loadedEndpoints.cleanup(); } }); @@ -136,7 +139,11 @@ describe( it('should have read access to Endpoint Policy Management', () => { ensurePolicyListPageAuthzAccess('read', true); - ensurePolicyDetailsPageAuthzAccess(loadedEndpoints.integrationPolicies[0].id, 'read', true); + ensurePolicyDetailsPageAuthzAccess( + loadedEndpoints.data.integrationPolicies[0].id, + 'read', + true + ); }); for (const { title, id } of artifactPagesFullAccess) { 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/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/roles/essentials_with_endpoint.roles.cy.ts index 95f30254e7fb2..c60095aa23c06 100644 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/roles/essentials_with_endpoint.roles.cy.ts +++ b/x-pack/test_serverless/functional/test_suites/security/cypress/e2e/endpoint_management/roles/essentials_with_endpoint.roles.cy.ts @@ -5,7 +5,6 @@ * 2.0. */ -import { IndexedHostsAndAlertsResponse } from '@kbn/security-solution-plugin/common/endpoint/index_data'; import { login } from '../../../tasks/login'; import { getNoPrivilegesPage, @@ -24,6 +23,10 @@ import { } 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', @@ -41,17 +44,17 @@ describe( const allPages = getEndpointManagementPageList(); const pageById = getEndpointManagementPageMap(); - let loadedEndpoints: IndexedHostsAndAlertsResponse; + let loadedEndpoints: CyIndexEndpointHosts; before(() => { - cy.task('indexEndpointHosts', {}, { timeout: 240000 }).then((response) => { + indexEndpointHosts().then((response) => { loadedEndpoints = response; }); }); after(() => { if (loadedEndpoints) { - cy.task('deleteIndexedEndpointHosts', loadedEndpoints); + loadedEndpoints.cleanup(); } }); @@ -99,7 +102,11 @@ describe( it('should have read access to Endpoint Policy Management', () => { ensurePolicyListPageAuthzAccess('read', true); - ensurePolicyDetailsPageAuthzAccess(loadedEndpoints.integrationPolicies[0].id, 'read', true); + ensurePolicyDetailsPageAuthzAccess( + loadedEndpoints.data.integrationPolicies[0].id, + 'read', + true + ); }); for (const { title, id } of artifactPagesFullAccess) { @@ -175,7 +182,11 @@ describe( it('should have access to policy management', () => { ensurePolicyListPageAuthzAccess('all', true); - ensurePolicyDetailsPageAuthzAccess(loadedEndpoints.integrationPolicies[0].id, 'all', true); + ensurePolicyDetailsPageAuthzAccess( + loadedEndpoints.data.integrationPolicies[0].id, + 'all', + true + ); }); it(`should NOT have access to Host Isolation Exceptions`, () => { diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/endpoint_list.ts b/x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/endpoint_list.ts index 5255682987d3e..a8cf41e6d9e16 100644 --- a/x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/endpoint_list.ts +++ b/x-pack/test_serverless/functional/test_suites/security/cypress/screens/endpoint_management/endpoint_list.ts @@ -73,3 +73,11 @@ export const openRowActionMenu = (options?: ListRowOptions): Cypress.Chainable = export const openConsoleFromEndpointList = (options?: ListRowOptions): Cypress.Chainable => { return openRowActionMenu(options).findByTestSubj('console').click(); }; + +export const getUnIsolateActionMenuItem = (): Cypress.Chainable => { + return cy.getByTestSubj('tableRowActionsMenuPanel').findByTestSubj('unIsolateLink'); +}; + +export const getConsoleActionMenuItem = (): Cypress.Chainable => { + return cy.getByTestSubj('tableRowActionsMenuPanel').findByTestSubj('console'); +}; diff --git a/x-pack/test_serverless/functional/test_suites/security/cypress/tasks/endpoint_management/index_endpoint_hosts.ts b/x-pack/test_serverless/functional/test_suites/security/cypress/tasks/endpoint_management/index_endpoint_hosts.ts new file mode 100644 index 0000000000000..81ea6d009814d --- /dev/null +++ b/x-pack/test_serverless/functional/test_suites/security/cypress/tasks/endpoint_management/index_endpoint_hosts.ts @@ -0,0 +1,35 @@ +/* + * 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 { + DeleteIndexedHostsAndAlertsResponse, + IndexedHostsAndAlertsResponse, +} from '@kbn/security-solution-plugin/common/endpoint/index_data'; +import { IndexEndpointHostsCyTaskOptions } from '@kbn/security-solution-plugin/public/management/cypress/types'; + +export interface CyIndexEndpointHosts { + data: IndexedHostsAndAlertsResponse; + cleanup: () => Cypress.Chainable; +} + +export const indexEndpointHosts = ( + options: IndexEndpointHostsCyTaskOptions = {} +): Cypress.Chainable => { + return cy.task('indexEndpointHosts', options, { timeout: 240000 }).then((indexHosts) => { + return { + data: indexHosts, + cleanup: () => { + cy.log( + 'Deleting Endpoint Host data', + indexHosts.hosts.map((host) => `${host.host.name} (${host.host.id})`) + ); + + return cy.task('deleteIndexedEndpointHosts', indexHosts); + }, + }; + }); +};