Skip to content

Commit

Permalink
[Security Solution][Endpoint] Refactor Cypress login task and ensur…
Browse files Browse the repository at this point in the history
…e consistent use of users across ESS and Serverless tests (elastic#166958)

## Summary

- Cypress `login` task refactored:
- `login(user?)` : logs use in using the default `user` or one of the
users supported by security solution and endpoint management tests
- `login.with(username, password)` : Logs a user in by using `username`
and `password`
- `login.withCustomRole(role)` : creates the provided `role`, creates a
user for it by the same role name and logs in with it
- The Cypress process for loading users into Kibana only applies to
non-serverless (at the moment). For serverless, it only validates that
the `username` being used is one of the approved user names that applies
to serverless
- FYI: the creation/availability of serverless roles/users for testing
is an ongoing effort by the kibana ops team
- New generic `RoleAndUserLoader` class. Is initialized with an map of
`Roles` and provide a standard interface for loading them.
- A sub-class (`EndpointSecurityTestRolesLoader`) was also created for
the endpoint security test users, which uses the existing set of role
definitions
- The `resolver_generator_script` was also updated to use the new
`EndpointSecurityTestRolesLoader` class for handling the `--rbacUser`
argument

---------

Co-authored-by: kibanamachine <[email protected]>
  • Loading branch information
paul-tavares and kibanamachine authored Sep 25, 2023
1 parent 93ce988 commit 3f03264
Show file tree
Hide file tree
Showing 26 changed files with 714 additions and 461 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* 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 { EndpointSecurityRoleNames } from '../../../../scripts/endpoint/common/roles_users';

export type KibanaKnownUserAccounts = keyof typeof KIBANA_KNOWN_DEFAULT_ACCOUNTS;

export type SecurityTestUser = EndpointSecurityRoleNames | KibanaKnownUserAccounts;

/**
* List of kibana system accounts
*/
export const KIBANA_KNOWN_DEFAULT_ACCOUNTS = {
elastic: 'elastic',
elastic_serverless: 'elastic_serverless',
system_indices_superuser: 'system_indices_superuser',
} as const;
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ import type {
HostPolicyResponse,
LogsEndpointActionResponse,
} from '../../../common/endpoint/types';
import type { IndexEndpointHostsCyTaskOptions, HostActionResponse } from './types';
import type {
HostActionResponse,
IndexEndpointHostsCyTaskOptions,
LoadUserAndRoleCyTaskOptions,
CreateUserAndRoleCyTaskOptions,
} from './types';
import type {
DeleteIndexedFleetEndpointPoliciesResponse,
IndexedFleetEndpointPolicyResponse,
Expand All @@ -32,6 +37,7 @@ import type {
DeletedIndexedEndpointRuleAlerts,
IndexedEndpointRuleAlerts,
} from '../../../common/endpoint/data_loaders/index_endpoint_rule_alerts';
import type { LoadedRoleAndUser } from '../../../scripts/endpoint/common/role_and_user_loader';

declare global {
namespace Cypress {
Expand Down Expand Up @@ -185,6 +191,18 @@ declare global {
arg: { hostname: string; path: string; password?: string },
options?: Partial<Loggable & Timeoutable>
): Chainable<string>;

task(
name: 'loadUserAndRole',
arg: LoadUserAndRoleCyTaskOptions,
options?: Partial<Loggable & Timeoutable>
): Chainable<LoadedRoleAndUser>;

task(
name: 'createUserAndRole',
arg: CreateUserAndRoleCyTaskOptions,
options?: Partial<Loggable & Timeoutable>
): Chainable<LoadedRoleAndUser>;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/

import { getRoleWithArtifactReadPrivilege } from '../../fixtures/role_with_artifact_read_privilege';
import { getEndpointSecurityPolicyManager } from '../../../../../scripts/endpoint/common/roles_users/endpoint_security_policy_manager';
import { getArtifactsListTestsData } from '../../fixtures/artifacts_page';
import { visitPolicyDetailsPage } from '../../screens/policy_details';
Expand All @@ -16,27 +17,21 @@ import {
yieldFirstPolicyID,
} from '../../tasks/artifacts';
import { loadEndpointDataForEventFiltersIfNeeded } from '../../tasks/load_endpoint_data';
import {
getRoleWithArtifactReadPrivilege,
login,
loginWithCustomRole,
loginWithRole,
ROLE,
} from '../../tasks/login';
import { login, ROLE } from '../../tasks/login';
import { performUserActions } from '../../tasks/perform_user_actions';

const loginWithPrivilegeAll = () => {
loginWithRole(ROLE.endpoint_security_policy_manager);
login(ROLE.endpoint_policy_manager);
};

const loginWithPrivilegeRead = (privilegePrefix: string) => {
const roleWithArtifactReadPrivilege = getRoleWithArtifactReadPrivilege(privilegePrefix);
loginWithCustomRole('roleWithArtifactReadPrivilege', roleWithArtifactReadPrivilege);
login.withCustomRole({ name: 'roleWithArtifactReadPrivilege', ...roleWithArtifactReadPrivilege });
};

const loginWithPrivilegeNone = (privilegePrefix: string) => {
const roleWithoutArtifactPrivilege = getRoleWithoutArtifactPrivilege(privilegePrefix);
loginWithCustomRole('roleWithoutArtifactPrivilege', roleWithoutArtifactPrivilege);
login.withCustomRole({ name: 'roleWithoutArtifactPrivilege', ...roleWithoutArtifactPrivilege });
};

const getRoleWithoutArtifactPrivilege = (privilegePrefix: string) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,8 @@
* 2.0.
*/

import {
getRoleWithArtifactReadPrivilege,
login,
loginWithCustomRole,
loginWithRole,
ROLE,
} from '../../tasks/login';
import { getRoleWithArtifactReadPrivilege } from '../../fixtures/role_with_artifact_read_privilege';
import { login, ROLE } from '../../tasks/login';
import { loadPage } from '../../tasks/common';

import { getArtifactsListTestsData } from '../../fixtures/artifacts_page';
Expand All @@ -20,18 +15,18 @@ import { performUserActions } from '../../tasks/perform_user_actions';
import { loadEndpointDataForEventFiltersIfNeeded } from '../../tasks/load_endpoint_data';

const loginWithWriteAccess = (url: string) => {
loginWithRole(ROLE.endpoint_security_policy_manager);
login(ROLE.endpoint_policy_manager);
loadPage(url);
};

const loginWithReadAccess = (privilegePrefix: string, url: string) => {
const roleWithArtifactReadPrivilege = getRoleWithArtifactReadPrivilege(privilegePrefix);
loginWithCustomRole('roleWithArtifactReadPrivilege', roleWithArtifactReadPrivilege);
login.withCustomRole({ name: 'roleWithArtifactReadPrivilege', ...roleWithArtifactReadPrivilege });
loadPage(url);
};

const loginWithoutAccess = (url: string) => {
loginWithRole(ROLE.t1_analyst);
login(ROLE.t1_analyst);
loadPage(url);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ import {
} from '../../tasks/response_actions';
import { cleanupRule, generateRandomStringName, loadRule } from '../../tasks/api_fixtures';
import { RESPONSE_ACTION_TYPES } from '../../../../../common/api/detection_engine';
import { loginWithRole, ROLE } from '../../tasks/login';
import { login, ROLE } from '../../tasks/login';

describe('Form', { tags: '@ess' }, () => {
describe('User with no access can not create an endpoint response action', () => {
before(() => {
loginWithRole(ROLE.endpoint_response_actions_no_access);
login(ROLE.endpoint_response_actions_no_access);
});

it('no endpoint response action option during rule creation', () => {
Expand All @@ -36,7 +36,7 @@ describe('Form', { tags: '@ess' }, () => {
const [ruleName, ruleDescription] = generateRandomStringName(2);

before(() => {
loginWithRole(ROLE.endpoint_response_actions_access);
login(ROLE.endpoint_response_actions_access);
});
after(() => {
cleanupRule(ruleId);
Expand Down Expand Up @@ -94,7 +94,7 @@ describe('Form', { tags: '@ess' }, () => {
});
});
beforeEach(() => {
loginWithRole(ROLE.endpoint_response_actions_access);
login(ROLE.endpoint_response_actions_access);
});
after(() => {
cleanupRule(ruleId);
Expand Down Expand Up @@ -146,7 +146,7 @@ describe('Form', { tags: '@ess' }, () => {
const [ruleName, ruleDescription] = generateRandomStringName(2);

before(() => {
loginWithRole(ROLE.endpoint_response_actions_no_access);
login(ROLE.endpoint_response_actions_no_access);
});

it('response actions are disabled', () => {
Expand All @@ -166,7 +166,7 @@ describe('Form', { tags: '@ess' }, () => {
loadRule().then((res) => {
ruleId = res.id;
});
loginWithRole(ROLE.endpoint_response_actions_no_access);
login(ROLE.endpoint_response_actions_no_access);
});
after(() => {
cleanupRule(ruleId);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { disableExpandableFlyoutAdvancedSettings } from '../../tasks/common';
import { APP_ALERTS_PATH } from '../../../../../common/constants';
import { closeAllToasts } from '../../tasks/toasts';
import { fillUpNewRule } from '../../tasks/response_actions';
import { login, loginWithRole, ROLE } from '../../tasks/login';
import { login, ROLE } from '../../tasks/login';
import { generateRandomStringName } from '../../tasks/utils';
import type { ReturnTypeFromChainable } from '../../types';
import { indexEndpointHosts } from '../../tasks/index_endpoint_hosts';
Expand All @@ -20,7 +20,7 @@ describe('No License', { tags: '@ess', env: { ftrConfig: { license: 'basic' } }
const [ruleName, ruleDescription] = generateRandomStringName(2);

before(() => {
loginWithRole(ROLE.endpoint_response_actions_access);
login(ROLE.endpoint_response_actions_access);
});

it('response actions are disabled', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import type { CyIndexEndpointHosts } from '../../tasks/index_endpoint_hosts';
import { indexEndpointHosts } from '../../tasks/index_endpoint_hosts';
import { loginServerless } from '../../tasks/login_serverless';
import { login } from '../../tasks/login';
import {
getConsoleActionMenuItem,
getUnIsolateActionMenuItem,
Expand Down Expand Up @@ -42,7 +42,7 @@ describe(
});

beforeEach(() => {
loginServerless();
login();
visitEndpointList();
openRowActionMenu();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import { ensureResponseActionAuthzAccess } from '../../../tasks/response_actions';
import { loginServerless, ServerlessUser } from '../../../tasks/login_serverless';
import { login, ROLE } from '../../../tasks/login';
import { RESPONSE_ACTION_API_COMMANDS_NAMES } from '../../../../../../common/endpoint/service/response_actions/constants';
import { getNoPrivilegesPage } from '../../../screens/common';
import { getEndpointManagementPageList } from '../../../screens';
Expand All @@ -31,7 +31,7 @@ describe(
let password: string;

beforeEach(() => {
loginServerless(ServerlessUser.ENDPOINT_OPERATIONS_ANALYST).then((response) => {
login(ROLE.endpoint_operations_analyst).then((response) => {
username = response.username;
password = response.password;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import { ensureResponseActionAuthzAccess } from '../../../tasks/response_actions';
import { loginServerless, ServerlessUser } from '../../../tasks/login_serverless';
import { login, ROLE } from '../../../tasks/login';
import { RESPONSE_ACTION_API_COMMANDS_NAMES } from '../../../../../../common/endpoint/service/response_actions/constants';
import {
getEndpointManagementPageList,
Expand All @@ -33,7 +33,7 @@ describe(
let password: string;

beforeEach(() => {
loginServerless(ServerlessUser.ENDPOINT_OPERATIONS_ANALYST).then((response) => {
login(ROLE.endpoint_operations_analyst).then((response) => {
username = response.username;
password = response.password;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import { ensureResponseActionAuthzAccess } from '../../../tasks/response_actions';
import { loginServerless, ServerlessUser } from '../../../tasks/login_serverless';
import { login, ROLE } from '../../../tasks/login';
import { RESPONSE_ACTION_API_COMMANDS_NAMES } from '../../../../../../common/endpoint/service/response_actions/constants';
import { getNoPrivilegesPage } from '../../../screens/common';
import { getEndpointManagementPageList } from '../../../screens';
Expand All @@ -33,7 +33,7 @@ describe(
let password: string;

beforeEach(() => {
loginServerless(ServerlessUser.ENDPOINT_OPERATIONS_ANALYST).then((response) => {
login(ROLE.endpoint_operations_analyst).then((response) => {
username = response.username;
password = response.password;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import { ensureResponseActionAuthzAccess } from '../../../tasks/response_actions';
import { loginServerless, ServerlessUser } from '../../../tasks/login_serverless';
import { login, ROLE } from '../../../tasks/login';
import { RESPONSE_ACTION_API_COMMANDS_NAMES } from '../../../../../../common/endpoint/service/response_actions/constants';
import {
getEndpointManagementPageMap,
Expand Down Expand Up @@ -41,7 +41,7 @@ describe(
let password: string;

beforeEach(() => {
loginServerless(ServerlessUser.ENDPOINT_OPERATIONS_ANALYST).then((response) => {
login(ROLE.endpoint_operations_analyst).then((response) => {
username = response.username;
password = response.password;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/

import { loginServerless } from '../../tasks/login_serverless';
import { login } from '../../tasks/login';
import { visitPolicyDetailsPage } from '../../screens/policy_details';
import type { IndexedFleetEndpointPolicyResponse } from '../../../../../common/endpoint/data_loaders/index_fleet_endpoint_policy';

Expand Down Expand Up @@ -35,7 +35,7 @@ describe(
});

beforeEach(() => {
loginServerless();
login();
visitPolicyDetailsPage(loadedPolicyData.integrationPolicies[0].id);
});

Expand Down
Loading

0 comments on commit 3f03264

Please sign in to comment.