mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[Security Solution] [Cypress] SAML for Serverless login and role testing (#172655)
Relates to: * https://github.com/elastic/kibana/issues/166340 * https://github.com/elastic/kibana/pull/170852 * https://github.com/elastic/kibana/pull/170417 * https://github.com/elastic/kibana/pull/172678 ## Summary In this PR we are using the code implemented on https://github.com/elastic/kibana/pull/170417 and https://github.com/elastic/kibana/pull/172678 to allow SAML and role testing inside Cypress. * We are creating a Cypress task to use the above-developed code and be able to retrieve a session cookie given a role. * We updated the login task to know how we should perform the login depending if we are in Serverless (MKI or serverless FTR) or ESS * In the parallel serverless script: * We are updating the `BASE_ENV_URL` variable to use the proper QA environment (pending to be done in follow-up PRs, to extract this value so it is not hardcoded cc @dkirchan ) * We are adding the `IS_SERVERLESS` environment variable needed for the logic on the login task. This changed implied to update the `es_archiver` file to continue work as expected. * We have added the `TEST_CLOUD_HOST_NAME` environment variable needed for the code we are reusing to retrieve the session cookie for MKI. * We have updated the Security Solution quality gate script to set the `role_users.json` file needed by the code we are reusing to get the different session cookies on MKI * We have adjusted the tests because the username now follows the pattern `test <role>` (@dmlemeshko is it possible to have as username just the role? Is this something that can impact other tests and teams?) * We have [skipped](https://github.com/elastic/kibana/issues/173168) a test that got unstable after the changes. ## How to test it in your machine ### Serverless FTR 1. Navigate to `x-pack/test/security_solution_cypress` 2. Execute `yarn cypress:open:qa:serverless` 3. Click on `E2E testing` 4. Click on any test to execute it ### Serverless MKI Setup a valid Elastic Cloud API key for QA environment: 1. Navigate to QA environment. 2. Click on the `User menu button` located on the top right of the header. 3. Click on `Organization`. 5. Click on the `API keys` tab. 6. Click on `Create API key` button. 7. Add a name, set an expiration date, assign an organization owner role. 8. Click on `Create API key` 9. Save the value of the key Store the saved key on `~/.elastic/cloud.json` using the following format: ```json { "api_key": { "qa": "<API_KEY>" } } ``` Store the email and password of the account you used to login in the QA Environment at the root directory of your Kibana project on `.ftr/role_users.json`, using the following format: ```json { "admin": { "email": "<email>", "password": "<password>" } } ``` If you want to execute a test with a role different from the default one, make sure you have created the user under your organization and is added to the above json following the format: ```json { "admin": { "email": "<email>", "password": "<password>" }, "<roleName>": { "email": "<email>", "password": "<password>" } } ``` 1. Navigate to `x-pack/test/security_solution_cypress` 2. Execute `yarn cypress:open:qa:serverless` 3. Click on `E2E testing` 4. Click on any test to execute it --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
a26eec451f
commit
c580213c00
14 changed files with 131 additions and 14 deletions
|
@ -16,6 +16,9 @@ export JOB=kibana-security-solution-chrome
|
|||
|
||||
buildkite-agent meta-data set "${BUILDKITE_JOB_ID}_is_test_execution_step" "true"
|
||||
|
||||
mkdir .ftr
|
||||
retry 5 5 vault kv get -format=json -field=data secret/kibana-issues/dev/security-quality-gate/role-users > .ftr/role_users.json
|
||||
|
||||
cd x-pack/test/security_solution_cypress
|
||||
set +e
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ const DEFAULT_CONFIGURATION: Readonly<ProductType[]> = [
|
|||
|
||||
const DEFAULT_REGION = 'aws-eu-west-1';
|
||||
const PROJECT_NAME_PREFIX = 'kibana-cypress-security-solution-ephemeral';
|
||||
const BASE_ENV_URL = 'https://global.qa.cld.elstc.co';
|
||||
const BASE_ENV_URL = 'https://console.qa.cld.elstc.co';
|
||||
let log: ToolingLog;
|
||||
const API_HEADERS = Object.freeze({
|
||||
'kbn-xsrf': 'cypress-creds',
|
||||
|
@ -571,6 +571,7 @@ ${JSON.stringify(cypressConfigFile, null, 2)}
|
|||
KIBANA_PASSWORD: credentials.password,
|
||||
|
||||
CLOUD_SERVERLESS: true,
|
||||
IS_SERVERLESS: true,
|
||||
};
|
||||
|
||||
if (process.env.DEBUG && !process.env.CI) {
|
||||
|
@ -582,6 +583,7 @@ ${JSON.stringify(cypressConfigFile, null, 2)}
|
|||
----------------------------------------------
|
||||
`);
|
||||
}
|
||||
process.env.TEST_CLOUD_HOST_NAME = new URL(BASE_ENV_URL).hostname;
|
||||
|
||||
if (isOpen) {
|
||||
await cypress.open({
|
||||
|
|
|
@ -304,8 +304,51 @@ Store the saved key on `~/.elastic/cloud.json` using the following format:
|
|||
}
|
||||
```
|
||||
|
||||
#### Known limitations
|
||||
- Currently RBAC cannot be tested.
|
||||
Store the email and password of the account you used to login in the QA Environment at the root directory of your Kibana project on `.ftr/role_users.json`, using the following format:
|
||||
|
||||
```json
|
||||
{
|
||||
"admin": {
|
||||
"email": "<email>",
|
||||
"password": "<password>"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Testing with different roles
|
||||
|
||||
If you want to execute a test using Cypress on visual mode with MKI, you need to make sure you have the user created in your organization, and add it tot he `.ftr/role_users.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"admin": {
|
||||
"email": "<email>",
|
||||
"password": "<password>"
|
||||
},
|
||||
"<roleName>": {
|
||||
"email": "<email>",
|
||||
"password": "<password>"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
As role names please use:
|
||||
- admin
|
||||
- detections_admin
|
||||
- editor
|
||||
- endpoint_operations_analyst
|
||||
- endpoint_policy_manager
|
||||
- none
|
||||
- platform_engineer
|
||||
- rule_author
|
||||
- soc_manager
|
||||
- t1_analyst
|
||||
- t2_analyst
|
||||
- t3_analyst
|
||||
- threat_intelligence_analyst
|
||||
- viewer
|
||||
|
||||
The above should be the same used on the automation.
|
||||
|
||||
#### PLIs
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import { defineCypressConfig } from '@kbn/cypress-config';
|
||||
import { esArchiver } from './support/es_archiver';
|
||||
import { samlAuthentication } from './support/saml_auth';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default defineCypressConfig({
|
||||
|
@ -39,6 +40,7 @@ export default defineCypressConfig({
|
|||
specPattern: './cypress/e2e/**/*.cy.ts',
|
||||
setupNodeEvents(on, config) {
|
||||
esArchiver(on, config);
|
||||
samlAuthentication(on, config);
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
require('@cypress/grep/src/plugin')(config);
|
||||
return config;
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import { defineCypressConfig } from '@kbn/cypress-config';
|
||||
import { esArchiver } from './support/es_archiver';
|
||||
import { samlAuthentication } from './support/saml_auth';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default defineCypressConfig({
|
||||
|
@ -41,6 +42,7 @@ export default defineCypressConfig({
|
|||
specPattern: './cypress/e2e/**/*.cy.ts',
|
||||
setupNodeEvents(on, config) {
|
||||
esArchiver(on, config);
|
||||
samlAuthentication(on, config);
|
||||
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
require('@cypress/grep/src/plugin')(config);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import { defineCypressConfig } from '@kbn/cypress-config';
|
||||
import { esArchiver } from './support/es_archiver';
|
||||
import { samlAuthentication } from './support/saml_auth';
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default defineCypressConfig({
|
||||
|
@ -31,6 +32,7 @@ export default defineCypressConfig({
|
|||
experimentalMemoryManagement: true,
|
||||
setupNodeEvents(on, config) {
|
||||
esArchiver(on, config);
|
||||
samlAuthentication(on, config);
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
require('@cypress/grep/src/plugin')(config);
|
||||
return config;
|
||||
|
|
|
@ -106,10 +106,10 @@ describe('Cases', { tags: ['@ess', '@serverless'] }, () => {
|
|||
);
|
||||
cy.get(CASE_DETAILS_USERNAMES)
|
||||
.eq(REPORTER)
|
||||
.should('have.text', Cypress.env(ELASTICSEARCH_USERNAME));
|
||||
.should('contain', Cypress.env(ELASTICSEARCH_USERNAME));
|
||||
cy.get(CASE_DETAILS_USERNAMES)
|
||||
.eq(PARTICIPANTS)
|
||||
.should('have.text', Cypress.env(ELASTICSEARCH_USERNAME));
|
||||
.should('contain', Cypress.env(ELASTICSEARCH_USERNAME));
|
||||
cy.get(CASE_DETAILS_TAGS).should('have.text', expectedTags);
|
||||
|
||||
EXPECTED_METRICS.forEach((metric) => {
|
||||
|
|
|
@ -46,7 +46,8 @@ describe('Overview Page', { tags: ['@ess', '@serverless'] }, () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('Favorite Timelines', () => {
|
||||
// https://github.com/elastic/kibana/issues/173168
|
||||
describe('Favorite Timelines', { tags: ['@brokenInServerless'] }, () => {
|
||||
it('should appear on overview page', () => {
|
||||
createTimeline(getTimeline())
|
||||
.then((response) => response.body.data.persistTimeline.timeline.savedObjectId)
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { IS_SERVERLESS, CLOUD_SERVERLESS } from '../env_var_names_constants';
|
||||
import { getDataTestSubjectSelector } from '../helpers/common';
|
||||
import { GLOBAL_FILTERS_CONTAINER } from './date_picker';
|
||||
|
||||
|
@ -204,9 +205,15 @@ export const ALERT_ASSIGNEES_SELECT_PANEL =
|
|||
export const ALERT_ASSIGNEES_UPDATE_BUTTON =
|
||||
'[data-test-subj="securitySolutionAssigneesApplyButton"]';
|
||||
|
||||
export const ALERT_USER_AVATAR = (assignee: string) =>
|
||||
`[data-test-subj="securitySolutionUsersAvatar-${assignee}"][title='${assignee}']`;
|
||||
export const ALERT_USER_AVATAR = (assignee: string) => {
|
||||
let expectedAssignee = assignee;
|
||||
|
||||
if (Cypress.env(IS_SERVERLESS) && !Cypress.env(CLOUD_SERVERLESS)) {
|
||||
expectedAssignee = `test ${expectedAssignee}`;
|
||||
}
|
||||
|
||||
return `[data-test-subj^="securitySolutionUsersAvatar-"][title='${expectedAssignee}']`;
|
||||
};
|
||||
export const ALERT_AVATARS_PANEL = '[data-test-subj="securitySolutionUsersAvatarsPanel"]';
|
||||
|
||||
export const ALERT_ASIGNEES_COLUMN =
|
||||
|
|
|
@ -18,7 +18,7 @@ export const esArchiver = (
|
|||
): EsArchiver => {
|
||||
const log = new ToolingLog({ level: 'verbose', writeTo: process.stdout });
|
||||
|
||||
const isSnapshotServerless = config.env.IS_SERVERLESS;
|
||||
const isServerless = config.env.IS_SERVERLESS;
|
||||
const isCloudServerless = config.env.CLOUD_SERVERLESS;
|
||||
|
||||
const serverlessCloudUser = {
|
||||
|
@ -27,7 +27,7 @@ export const esArchiver = (
|
|||
};
|
||||
|
||||
let authOverride;
|
||||
if (!isSnapshotServerless) {
|
||||
if (isServerless) {
|
||||
authOverride = isCloudServerless ? serverlessCloudUser : systemIndicesSuperuser;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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 { ToolingLog } from '@kbn/tooling-log';
|
||||
|
||||
import { SecurityRoleName } from '@kbn/security-solution-plugin/common/test';
|
||||
import { HostOptions, SamlSessionManager } from '@kbn/test';
|
||||
|
||||
export const samlAuthentication = async (
|
||||
on: Cypress.PluginEvents,
|
||||
config: Cypress.PluginConfigOptions
|
||||
): Promise<void> => {
|
||||
const log = new ToolingLog({ level: 'verbose', writeTo: process.stdout });
|
||||
|
||||
const kbnHost = config.env.KIBANA_URL || config.env.BASE_URL;
|
||||
|
||||
const kbnUrl = new URL(kbnHost);
|
||||
|
||||
const hostOptions: HostOptions = {
|
||||
protocol: kbnUrl.protocol as 'http' | 'https',
|
||||
hostname: kbnUrl.hostname,
|
||||
port: parseInt(kbnUrl.port, 10),
|
||||
username: config.env.ELASTICSEARCH_USERNAME,
|
||||
password: config.env.ELASTICSEARCH_PASSWORD,
|
||||
};
|
||||
|
||||
on('task', {
|
||||
getSessionCookie: async (role: string | SecurityRoleName): Promise<string> => {
|
||||
const sessionManager = new SamlSessionManager({
|
||||
hostOptions,
|
||||
log,
|
||||
isCloud: config.env.CLOUD_SERVERLESS,
|
||||
});
|
||||
return sessionManager.getSessionCookieForRole(role);
|
||||
},
|
||||
});
|
||||
};
|
|
@ -39,7 +39,7 @@ function createUser(username: string, password: string, roles: string[] = []): v
|
|||
password,
|
||||
roles,
|
||||
full_name: username,
|
||||
email: '',
|
||||
email: `${username}@elastic.co`,
|
||||
};
|
||||
|
||||
rootRequest({
|
||||
|
|
|
@ -41,8 +41,22 @@ export const getEnvAuth = (role: SecurityRoleName): User => {
|
|||
};
|
||||
|
||||
export const login = (role?: SecurityRoleName): void => {
|
||||
const user = role ? getEnvAuth(role) : defaultUser;
|
||||
loginWithUser(user);
|
||||
let testRole = '';
|
||||
|
||||
if (Cypress.env(IS_SERVERLESS)) {
|
||||
if (!role) {
|
||||
testRole = Cypress.env(CLOUD_SERVERLESS) ? 'admin' : 'system_indices_superuser';
|
||||
} else {
|
||||
testRole = role;
|
||||
}
|
||||
cy.task('getSessionCookie', testRole).then((cookie) => {
|
||||
cy.setCookie('sid', cookie as string);
|
||||
});
|
||||
cy.visit('/');
|
||||
} else {
|
||||
const user = role ? getEnvAuth(role) : defaultUser;
|
||||
loginWithUser(user);
|
||||
}
|
||||
};
|
||||
|
||||
export const loginWithUser = (user: User): void => {
|
||||
|
|
|
@ -40,6 +40,6 @@
|
|||
"@kbn/management-settings-ids",
|
||||
"@kbn/es-query",
|
||||
"@kbn/ml-plugin",
|
||||
"@kbn/license-management-plugin"
|
||||
"@kbn/license-management-plugin",
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue