diff --git a/x-pack/test/security_solution_cypress/cypress/README.md b/x-pack/test/security_solution_cypress/cypress/README.md index 7ae9017c8f9c8..89ab19343dbc7 100644 --- a/x-pack/test/security_solution_cypress/cypress/README.md +++ b/x-pack/test/security_solution_cypress/cypress/README.md @@ -306,8 +306,86 @@ Per the way we set the environment during the execution process on CI, the above For test developing or test debugging purposes, you need to modify the configuration but without committing and pushing the changes in `x-pack/test/security_solution_cypress/serverless_config.ts`. +#### Custom Roles -### Running serverless tests locally pointing to a MKI project created in QA environment (Kibana QA quality gate) +Custom roles for serverless is currently supported only for stateless environments (non MKI environments). + +##### Creating a Custom Role + +To create a custom role, use the Cypress task `createServerlessCustomRole`. This task requires two parameters: +- **`roleDescriptor`**: Defines the permissions and access for the role. +- **`roleName`**: A unique name for the custom role. + +Example: + +```typescript +const roleDescriptor = { + elasticsearch: { + cluster: ['monitor'], + indices: [{ names: ['*'], privileges: ['read'] }], + }, + kibana: [ + { + base: ['all'], + feature: {}, + spaces: ['*'], + }, + ], +}; + +cy.task('createServerlessCustomRole', { roleDescriptor, roleName: 'customRole' }); +``` + +##### Using a Custom Role + +Once the custom role is created, you can log in to the application using your regular `login`` method and passing the name of the role. + +```typescript +login('customRole'); +``` + + +##### Deleting a Custom Role + +After your tests, always delete the custom role to ensure a clean environment. Use the `deleteServerlessCustomRole` task and provide the name of the role as the parameter. + +```typescript +cy.task('deleteServerlessCustomRole', 'customRole'); +``` + +##### Full workflow + +Here’s the complete workflow for creating, using, and deleting a custom role: + +```typescript +const roleDescriptor = { + elasticsearch: { + cluster: ['monitor'], + indices: [{ names: ['*'], privileges: ['read'] }], + }, + kibana: [ + { + base: ['all'], + feature: {}, + spaces: ['*'], + }, + ], +}; + +before(() => { + cy.task('createServerlessCustomRole', { roleDescriptor, roleName: 'customRole' }); +}); + +beforeEach(() => { + login('customRole'); +}); + +after(() => { + cy.task('deleteServerlessCustomRole', 'customRole'); +}); +``` + +### Running serverless tests locally pointing to a MKI project created in QA environment Note that when using any of the below scripts, the tests are going to be executed through an MKI project with the version that is currently available in QA. If you need to use a specific commit (i.e. debugging a failing tests on the periodic pipeline), check the section: `Running serverless tests locally pointing to a MKI project created in QA environment with an overridden image`. diff --git a/x-pack/test/security_solution_cypress/cypress/support/saml_auth.ts b/x-pack/test/security_solution_cypress/cypress/support/saml_auth.ts index 1f95d373b2c17..cb7ffe332ad61 100644 --- a/x-pack/test/security_solution_cypress/cypress/support/saml_auth.ts +++ b/x-pack/test/security_solution_cypress/cypress/support/saml_auth.ts @@ -5,6 +5,8 @@ * 2.0. */ +import type { Role } from '@kbn/security-plugin-types-common'; + import { ToolingLog } from '@kbn/tooling-log'; import { SecurityRoleName } from '@kbn/security-solution-plugin/common/test'; @@ -67,13 +69,13 @@ export const samlAuthentication = async ( cloudUsersFilePath, }); + const adminCookieHeader = await sessionManager.getApiCredentialsForRole('admin'); + on('task', { getSessionCookie: async (role: string | SecurityRoleName): Promise => { return sessionManager.getInteractiveUserSessionCookieWithRoleScope(role); }, getApiKeyForRole: async (role: string | SecurityRoleName): Promise => { - const adminCookieHeader = await sessionManager.getApiCredentialsForRole('admin'); - let roleDescriptor = {}; const roleConfig = getRoleConfiguration(role, rolesPath); @@ -98,6 +100,48 @@ export const samlAuthentication = async ( const apiKey = response.data.encoded; return apiKey; }, + createServerlessCustomRole: async ({ + roleDescriptor, + roleName, + }: { + roleDescriptor: { kibana: Role['kibana']; elasticsearch: Role['elasticsearch'] }; + roleName: string; + }): Promise<{ status: number; data: Role }> => { + const customRoleDescriptors = { + kibana: roleDescriptor.kibana, + elasticsearch: roleDescriptor.elasticsearch ?? [], + }; + + const response = await axios.put( + `${kbnHost}/api/security/role/${roleName}`, + customRoleDescriptors, + { + headers: { + ...INTERNAL_REQUEST_HEADERS, + ...adminCookieHeader, + }, + } + ); + return { + status: response.status, + data: response.data, + }; + }, + deleteServerlessCustomRole: async ( + roleName: string + ): Promise<{ status: number; data: unknown }> => { + const response = await axios.delete(`${kbnHost}/api/security/role/${roleName}`, { + headers: { + ...INTERNAL_REQUEST_HEADERS, + ...adminCookieHeader, + }, + }); + + return { + status: response.status, + data: response.data, + }; + }, getFullname: async ( role: string | SecurityRoleName = DEFAULT_SERVERLESS_ROLE ): Promise => { diff --git a/x-pack/test/security_solution_cypress/cypress/tasks/login.ts b/x-pack/test/security_solution_cypress/cypress/tasks/login.ts index 4d996af79cbc6..a141579c0ffca 100644 --- a/x-pack/test/security_solution_cypress/cypress/tasks/login.ts +++ b/x-pack/test/security_solution_cypress/cypress/tasks/login.ts @@ -5,7 +5,6 @@ * 2.0. */ import { LoginState } from '@kbn/security-plugin/common/login_state'; -import type { SecurityRoleName } from '@kbn/security-solution-plugin/common/test'; import { KNOWN_SERVERLESS_ROLE_DEFINITIONS } from '@kbn/security-solution-plugin/common/test'; import { LOGOUT_URL } from '../urls/navigation'; import { @@ -27,7 +26,7 @@ export const defaultUser: User = { password: Cypress.env(ELASTICSEARCH_PASSWORD), }; -export const getEnvAuth = (role: SecurityRoleName): User => { +export const getEnvAuth = (role: string): User => { if ( (Cypress.env(IS_SERVERLESS) || Cypress.env(CLOUD_SERVERLESS)) && !(role in KNOWN_SERVERLESS_ROLE_DEFINITIONS) @@ -41,7 +40,7 @@ export const getEnvAuth = (role: SecurityRoleName): User => { return user; }; -export const login = (role?: SecurityRoleName): void => { +export const login = (role?: string): void => { let testRole = ''; if (Cypress.env(IS_SERVERLESS)) { diff --git a/x-pack/test/security_solution_cypress/cypress/tsconfig.json b/x-pack/test/security_solution_cypress/cypress/tsconfig.json index 35779da01ac6d..67f8e878bc6fe 100644 --- a/x-pack/test/security_solution_cypress/cypress/tsconfig.json +++ b/x-pack/test/security_solution_cypress/cypress/tsconfig.json @@ -45,5 +45,6 @@ "@kbn/repo-info", "@kbn/elastic-assistant-common", "@kbn/cloud-security-posture-common", + "@kbn/security-plugin-types-common", ] }