mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 01:38:56 -04:00
[Security Solution][Endpoint] Move endpoint management serverless specific tests (#166669)
## Summary - Moves the Serverless Endpoint Management tests from `x-pack/test_serverless/functional/test_suites/security/cypress` to `x-pack/plugins/security_solution/public/management/cypress` along with its set of supporting `screens` and `task`'s - This work is in preparation for enabling tests to be run in a serverless environment > ❗❗ NOTE > Tests for serverless are not currently running. The kibana core team is working on providing serverless users that have serverless security roles assigned to them for testing. Also, an effort in underway to also use a tagging approach to define which existing tests should run in serverless. --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
3f3a27b20a
commit
23b2f3b080
37 changed files with 450 additions and 389 deletions
3
.github/CODEOWNERS
vendored
3
.github/CODEOWNERS
vendored
|
@ -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
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -29,6 +29,6 @@
|
|||
},
|
||||
"@kbn/security-solution-plugin",
|
||||
"@kbn/fleet-plugin",
|
||||
"@kbn/cases-plugin"
|
||||
"@kbn/cases-plugin",
|
||||
]
|
||||
}
|
||||
|
|
|
@ -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';
|
||||
|
|
|
@ -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';
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
@ -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();
|
||||
});
|
|
@ -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;
|
||||
});
|
|
@ -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');
|
||||
});
|
||||
}
|
||||
);
|
|
@ -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;
|
||||
});
|
|
@ -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');
|
||||
});
|
||||
}
|
||||
);
|
|
@ -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', () => {
|
|
@ -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];
|
||||
(['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];
|
||||
|
||||
beforeEach(() => {
|
||||
login(roleName);
|
||||
});
|
||||
|
||||
for (const { id, title } of artifactPagesFullAccess) {
|
||||
it(`should have CRUD access to: ${title}`, () => {
|
||||
ensureArtifactPageAuthzAccess('all', id as EndpointArtifactPageId);
|
||||
});
|
||||
}
|
||||
|
||||
for (const { url, title } of grantedAccessPages) {
|
||||
it(`should have access to: ${title}`, () => {
|
||||
cy.visit(url);
|
||||
getNoPrivilegesPage().should('not.exist');
|
||||
});
|
||||
}
|
||||
|
||||
it('should have access to Fleet', () => {
|
||||
visitFleetAgentList();
|
||||
getAgentListTable().should('exist');
|
||||
});
|
||||
|
||||
it('should have access to Response Actions Log', () => {
|
||||
cy.visit(pageById.responseActionLog);
|
||||
|
||||
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');
|
||||
});
|
||||
beforeEach(() => {
|
||||
loginServerless(roleName);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
for (const { id, title } of artifactPagesFullAccess) {
|
||||
it(`should have CRUD access to: ${title}`, () => {
|
||||
ensureArtifactPageAuthzAccess('all', id as EndpointArtifactPageId);
|
||||
});
|
||||
}
|
||||
|
||||
for (const { url, title } of grantedAccessPages) {
|
||||
it(`should have access to: ${title}`, () => {
|
||||
cy.visit(url);
|
||||
getNoPrivilegesPage().should('not.exist');
|
||||
});
|
||||
}
|
||||
|
||||
it('should have access to Fleet', () => {
|
||||
visitFleetAgentList();
|
||||
getFleetAgentListTable().should('exist');
|
||||
});
|
||||
|
||||
it('should have access to Response Actions Log', () => {
|
||||
cy.visit(pageById.responseActionLog);
|
||||
|
||||
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');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
|
@ -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');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -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<Record<EndpointArtifactPageId, string>> = {
|
||||
trustedApps: 'trustedAppsListPage',
|
|
@ -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<EndpointManagementPageMap> = 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 })
|
||||
);
|
||||
};
|
|
@ -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 })
|
||||
);
|
||||
};
|
|
@ -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';
|
|
@ -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');
|
||||
};
|
|
@ -7,3 +7,4 @@
|
|||
|
||||
export * from './permission_denied';
|
||||
export * from './agent_list';
|
||||
export * from './agent_details';
|
|
@ -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');
|
||||
};
|
|
@ -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';
|
|
@ -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;
|
|
@ -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');
|
||||
};
|
||||
|
|
|
@ -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<EndpointManagementPageMap> = getEndpointManagementPageMap();
|
||||
|
|
@ -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<JQuery<HTMLDivElement>> => {
|
||||
return cy.getByTestSubj<HTMLDivElement>(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();
|
||||
};
|
||||
|
|
|
@ -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<LoginState>({ 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<typeof sendApiLoginRequest>;
|
||||
|
||||
/**
|
||||
* Login using any username/password
|
||||
* @param username
|
||||
* @param password
|
||||
*/
|
||||
with(username: string, password: string): ReturnType<typeof sendApiLoginRequest>;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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<typeof sendApiLoginRequest> => {
|
||||
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<typeof sendApiLoginRequest> => {
|
||||
return sendApiLoginRequest(username, password);
|
||||
};
|
|
@ -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<UserAuthzAccessLevel, 'read'>,
|
||||
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<Cypress.RequestOptions> = {
|
||||
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);
|
||||
};
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
|
|
|
@ -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');
|
||||
};
|
|
@ -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();
|
||||
};
|
|
@ -5,5 +5,4 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
export * from './fleet';
|
||||
export * from './landing_page';
|
||||
|
|
|
@ -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';
|
|
@ -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<UserAuthzAccessLevel, 'read'>,
|
||||
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<Cypress.RequestOptions> = {
|
||||
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);
|
||||
};
|
|
@ -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",
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue