From b9f9b86e41be69621805c5defbd70c0fa6193753 Mon Sep 17 00:00:00 2001 From: Maxim Palenov Date: Tue, 31 Oct 2023 02:24:23 +0100 Subject: [PATCH] move privileges tests into the new folder --- .buildkite/ftr_configs.yml | 8 +- .../security_and_spaces/group1/index.ts | 1 - .../security_and_spaces/group10/index.ts | 1 - .../config/ess/config.base.ts | 6 + .../config/ess/setup_users.ts | 30 ++ .../package.json | 6 +- .../privileges/configs/ess.config.ts | 22 ++ .../privileges/configs/serverless.config.ts | 15 + .../privileges/ess_only_privileges.ts | 266 ++++++++++++++++++ .../default_license/privileges/index.ts | 16 ++ .../default_license/privileges/privileges.ts} | 207 +------------- .../privileges/rule_privileges.ts} | 103 +++---- .../privileges/serverless_only_privileges.ts | 140 +++++++++ .../utils/create_detection_engine_indices.ts | 37 +++ .../utils/generate_event.ts | 17 ++ .../detections_response/utils/index.ts | 2 + .../utils/rules/create_rule_with_auth.ts | 35 +++ .../utils/rules/get_custom_query_rule.ts | 33 +++ .../utils/rules/get_threshold_rule.ts | 41 +++ .../detections_response/utils/rules/index.ts | 3 + .../detections_response/utils/rules/types.ts | 8 + .../detections_response/utils/types.ts | 19 ++ 22 files changed, 752 insertions(+), 264 deletions(-) create mode 100644 x-pack/test/security_solution_api_integration/config/ess/setup_users.ts create mode 100644 x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/configs/ess.config.ts create mode 100644 x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/configs/serverless.config.ts create mode 100644 x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/ess_only_privileges.ts create mode 100644 x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/index.ts rename x-pack/test/{detection_engine_api_integration/security_and_spaces/group10/read_privileges.ts => security_solution_api_integration/test_suites/detections_response/default_license/privileges/privileges.ts} (59%) rename x-pack/test/{detection_engine_api_integration/security_and_spaces/group1/check_privileges.ts => security_solution_api_integration/test_suites/detections_response/default_license/privileges/rule_privileges.ts} (55%) create mode 100644 x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/serverless_only_privileges.ts create mode 100644 x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/create_detection_engine_indices.ts create mode 100644 x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/generate_event.ts create mode 100644 x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_rule_with_auth.ts create mode 100644 x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_custom_query_rule.ts create mode 100644 x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_threshold_rule.ts create mode 100644 x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/types.ts create mode 100644 x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/types.ts diff --git a/.buildkite/ftr_configs.yml b/.buildkite/ftr_configs.yml index 7abd52a1ea153..5dcf3d1d0ef16 100644 --- a/.buildkite/ftr_configs.yml +++ b/.buildkite/ftr_configs.yml @@ -16,7 +16,6 @@ disabled: - x-pack/test/security_solution_api_integration/config/ess/config.base.ts - x-pack/test/security_solution_api_integration/config/serverless/config.base.ts - # QA suites that are run out-of-band - x-pack/test/stack_functional_integration/configs/config.stack_functional_integration_base.js - x-pack/test/upgrade/config.ts @@ -459,8 +458,5 @@ enabled: - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/rule_creation/configs/ess.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/actions/configs/serverless.config.ts - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/actions/configs/ess.config.ts - - - - - + - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/configs/serverless.config.ts + - x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/configs/ess.config.ts diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/index.ts index 1c9c874127660..fd5cb85e8fff5 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/index.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/index.ts @@ -15,7 +15,6 @@ export default ({ loadTestFile }: FtrProviderContext): void => { // existence being near 0. loadTestFile(require.resolve('./aliases')); - loadTestFile(require.resolve('./check_privileges')); loadTestFile(require.resolve('./create_index')); loadTestFile(require.resolve('./preview_rules')); loadTestFile(require.resolve('./create_rules_bulk')); diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/index.ts b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/index.ts index 7822d11698c95..b05464606867a 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/index.ts +++ b/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/index.ts @@ -25,7 +25,6 @@ export default ({ loadTestFile }: FtrProviderContext): void => { loadTestFile(require.resolve('./perform_bulk_action')); loadTestFile(require.resolve('./perform_bulk_action_dry_run')); loadTestFile(require.resolve('./patch_rules')); - loadTestFile(require.resolve('./read_privileges')); loadTestFile(require.resolve('./open_close_signals')); loadTestFile(require.resolve('./get_signals_migration_status')); loadTestFile(require.resolve('./create_signals_migrations')); diff --git a/x-pack/test/security_solution_api_integration/config/ess/config.base.ts b/x-pack/test/security_solution_api_integration/config/ess/config.base.ts index b4fbdba6de4c4..d493d76b712fc 100644 --- a/x-pack/test/security_solution_api_integration/config/ess/config.base.ts +++ b/x-pack/test/security_solution_api_integration/config/ess/config.base.ts @@ -8,6 +8,8 @@ import { CA_CERT_PATH } from '@kbn/dev-utils'; import { FtrConfigProviderContext, kbnTestConfig, kibanaTestUser } from '@kbn/test'; import { services } from '../../../api_integration/services'; +import { FtrProviderContext } from '../../ftr_provider_context'; +import { setupUsers } from './setup_users'; interface CreateTestConfigOptions { license: string; @@ -107,6 +109,10 @@ export function createTestConfig(options: CreateTestConfigOptions, testFiles?: s }, mochaOpts: { grep: '/^(?!.*@brokenInEss).*@ess.*/', + rootHooks: { + beforeAll: async ({ getService }: FtrProviderContext) => + setupUsers(getService('security')), + }, }, }; }; diff --git a/x-pack/test/security_solution_api_integration/config/ess/setup_users.ts b/x-pack/test/security_solution_api_integration/config/ess/setup_users.ts new file mode 100644 index 0000000000000..d31b44a527918 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/config/ess/setup_users.ts @@ -0,0 +1,30 @@ +/* + * 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 { + KNOWN_ESS_ROLE_DEFINITIONS, + KNOWN_SERVERLESS_ROLE_DEFINITIONS, +} from '@kbn/security-solution-plugin/common/test'; +import { SecurityService } from '../../../../../test/common/services/security/security'; + +export async function setupUsers(securityService: SecurityService): Promise { + const KNOWN_ROLE_DEFINITIONS = [ + ...Object.values(KNOWN_SERVERLESS_ROLE_DEFINITIONS), + ...Object.values(KNOWN_ESS_ROLE_DEFINITIONS), + ]; + + for (const roleDefinition of KNOWN_ROLE_DEFINITIONS) { + await securityService.role.create(roleDefinition.name, roleDefinition); + + await securityService.user.create(roleDefinition.name, { + password: 'changeme', + roles: [roleDefinition.name], + full_name: roleDefinition.name, + email: 'detections-reader@example.com', + }); + } +} diff --git a/x-pack/test/security_solution_api_integration/package.json b/x-pack/test/security_solution_api_integration/package.json index 305db2251e0b1..02deb1d3a4916 100644 --- a/x-pack/test/security_solution_api_integration/package.json +++ b/x-pack/test/security_solution_api_integration/package.json @@ -36,6 +36,10 @@ "actions:runner:serverless": "npm run run-tests actions serverless serverlessEnv", "actions:qa:serverless": "npm run run-tests actions serverless qaEnv", "actions:server:ess": "npm run initialize-server actions ess", - "actions:runner:ess": "npm run run-tests actions ess essEnv" + "actions:runner:ess": "npm run run-tests actions ess essEnv", + "privileges:server:serverless": "npm run initialize-server privileges serverless", + "privileges:runner:serverless": "npm run run-tests privileges serverless serverlessEnv", + "privileges:server:ess": "npm run initialize-server privileges ess", + "privileges:runner:ess": "npm run run-tests privileges ess essEnv" } } diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/configs/ess.config.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/configs/ess.config.ts new file mode 100644 index 0000000000000..a3205ac0927c1 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/configs/ess.config.ts @@ -0,0 +1,22 @@ +/* + * 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 { FtrConfigProviderContext } from '@kbn/test'; + +export default async function ({ readConfigFile }: FtrConfigProviderContext) { + const functionalConfig = await readConfigFile( + require.resolve('../../../../../config/ess/config.base.trial') + ); + + return { + ...functionalConfig.getAll(), + testFiles: [require.resolve('..')], + junit: { + reportName: 'Detection Engine ESS/ Privileges API Integration Tests', + }, + }; +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/configs/serverless.config.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/configs/serverless.config.ts new file mode 100644 index 0000000000000..65e31e7f0a9b0 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/configs/serverless.config.ts @@ -0,0 +1,15 @@ +/* + * 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 { createTestConfig } from '../../../../../config/serverless/config.base'; + +export default createTestConfig({ + testFiles: [require.resolve('..')], + junit: { + reportName: 'Detection Engine Serverless/ Privileges API Integration Tests', + }, +}); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/ess_only_privileges.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/ess_only_privileges.ts new file mode 100644 index 0000000000000..54b5f1d81d76a --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/ess_only_privileges.ts @@ -0,0 +1,266 @@ +/* + * 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 expect from '@kbn/expect'; +import { DETECTION_ENGINE_PRIVILEGES_URL } from '@kbn/security-solution-plugin/common/constants'; +import { ROLES } from '@kbn/security-solution-plugin/common/test'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; + +export default ({ getService }: FtrProviderContext) => { + const supertest = getService('supertest'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + + describe('@ess Privileges', () => { + it('should return expected privileges for elastic admin', async () => { + const { body } = await supertest.get(DETECTION_ENGINE_PRIVILEGES_URL).send().expect(200); + expect(body).to.eql({ + username: 'elastic', + has_all_requested: true, + cluster: { + monitor_ml: true, + manage_ccr: true, + manage_index_templates: true, + monitor_watcher: true, + monitor_transform: true, + read_ilm: true, + manage_api_key: true, + manage_security: true, + manage_own_api_key: true, + manage_saml: true, + all: true, + manage_ilm: true, + manage_ingest_pipelines: true, + read_ccr: true, + manage_rollup: true, + monitor: true, + manage_watcher: true, + manage: true, + manage_transform: true, + manage_token: true, + manage_ml: true, + manage_pipeline: true, + monitor_rollup: true, + transport_client: true, + create_snapshot: true, + }, + index: { + '.alerts-security.alerts-default': { + all: true, + manage_ilm: true, + read: true, + create_index: true, + read_cross_cluster: true, + index: true, + monitor: true, + delete: true, + manage: true, + delete_index: true, + create_doc: true, + view_index_metadata: true, + create: true, + manage_follow_index: true, + manage_leader_index: true, + maintenance: true, + write: true, + }, + }, + application: {}, + is_authenticated: true, + has_encryption_key: true, + }); + }); + + it('should return expected privileges for a "detections_admin" user', async () => { + const { body } = await supertestWithoutAuth + .get(DETECTION_ENGINE_PRIVILEGES_URL) + .auth(ROLES.detections_admin, 'changeme') + .send() + .expect(200); + expect(body).to.eql({ + username: 'detections_admin', + has_all_requested: false, + cluster: { + monitor_ml: true, + manage_ccr: false, + manage_index_templates: true, + monitor_watcher: true, + monitor_transform: true, + read_ilm: true, + manage_api_key: false, + manage_security: false, + manage_own_api_key: false, + manage_saml: false, + all: false, + manage_ilm: true, + manage_ingest_pipelines: true, + read_ccr: false, + manage_rollup: true, + monitor: true, + manage_watcher: true, + manage: true, + manage_transform: true, + manage_token: false, + manage_ml: true, + manage_pipeline: true, + monitor_rollup: true, + transport_client: true, + create_snapshot: true, + }, + index: { + '.alerts-security.alerts-default': { + all: false, + manage_ilm: true, + read: true, + create_index: true, + read_cross_cluster: false, + index: true, + monitor: true, + delete: true, + manage: true, + delete_index: true, + create_doc: true, + view_index_metadata: true, + create: true, + manage_follow_index: true, + manage_leader_index: true, + maintenance: true, + write: true, + }, + }, + application: {}, + is_authenticated: true, + has_encryption_key: true, + }); + }); + + it('should return expected privileges for a "reader" user', async () => { + const { body } = await supertestWithoutAuth + .get(DETECTION_ENGINE_PRIVILEGES_URL) + .auth(ROLES.reader, 'changeme') + .send() + .expect(200); + expect(body).to.eql({ + username: 'reader', + has_all_requested: false, + cluster: { + monitor_ml: false, + manage_ccr: false, + manage_index_templates: false, + monitor_watcher: false, + monitor_transform: false, + read_ilm: false, + manage_api_key: false, + manage_security: false, + manage_own_api_key: false, + manage_saml: false, + all: false, + manage_ilm: false, + manage_ingest_pipelines: false, + read_ccr: false, + manage_rollup: false, + monitor: false, + manage_watcher: false, + manage: false, + manage_transform: false, + manage_token: false, + manage_ml: false, + manage_pipeline: false, + monitor_rollup: false, + transport_client: false, + create_snapshot: false, + }, + index: { + '.alerts-security.alerts-default': { + all: false, + manage_ilm: false, + read: true, + create_index: false, + read_cross_cluster: false, + index: false, + monitor: false, + delete: false, + manage: false, + delete_index: false, + create_doc: false, + view_index_metadata: true, + create: false, + manage_follow_index: false, + manage_leader_index: false, + maintenance: true, + write: false, + }, + }, + application: {}, + is_authenticated: true, + has_encryption_key: true, + }); + }); + + it('should return expected privileges for a "hunter" user', async () => { + const { body } = await supertestWithoutAuth + .get(DETECTION_ENGINE_PRIVILEGES_URL) + .auth(ROLES.hunter, 'changeme') + .send() + .expect(200); + expect(body).to.eql({ + username: 'hunter', + has_all_requested: false, + cluster: { + monitor_ml: false, + manage_ccr: false, + manage_index_templates: false, + monitor_watcher: false, + monitor_transform: false, + read_ilm: false, + manage_api_key: false, + manage_security: false, + manage_own_api_key: false, + manage_saml: false, + all: false, + manage_ilm: false, + manage_ingest_pipelines: false, + read_ccr: false, + manage_rollup: false, + monitor: false, + manage_watcher: false, + manage: false, + manage_transform: false, + manage_token: false, + manage_ml: false, + manage_pipeline: false, + monitor_rollup: false, + transport_client: false, + create_snapshot: false, + }, + index: { + '.alerts-security.alerts-default': { + all: false, + manage_ilm: false, + read: true, + create_index: false, + read_cross_cluster: false, + index: true, + monitor: false, + delete: true, + manage: false, + delete_index: false, + create_doc: true, + view_index_metadata: false, + create: true, + manage_follow_index: false, + manage_leader_index: false, + maintenance: false, + write: true, + }, + }, + application: {}, + is_authenticated: true, + has_encryption_key: true, + }); + }); + }); +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/index.ts new file mode 100644 index 0000000000000..231337ef55342 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/index.ts @@ -0,0 +1,16 @@ +/* + * 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 { FtrProviderContext } from '../../../../ftr_provider_context'; + +export default function ({ loadTestFile }: FtrProviderContext) { + describe('Privileges', function () { + loadTestFile(require.resolve('./rule_privileges')); + loadTestFile(require.resolve('./privileges')); + loadTestFile(require.resolve('./serverless_only_privileges')); + loadTestFile(require.resolve('./ess_only_privileges')); + }); +} diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/read_privileges.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/privileges.ts similarity index 59% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group10/read_privileges.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/privileges.ts index b95c6771367f4..9f3f665386ee0 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group10/read_privileges.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/privileges.ts @@ -7,78 +7,14 @@ import expect from '@kbn/expect'; import { DETECTION_ENGINE_PRIVILEGES_URL } from '@kbn/security-solution-plugin/common/constants'; - import { ROLES } from '@kbn/security-solution-plugin/common/test'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { createUserAndRole, deleteUserAndRole } from '../../../common/services/security_solution'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; -// eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { - const supertest = getService('supertest'); const supertestWithoutAuth = getService('supertestWithoutAuth'); - describe('read_privileges', () => { - it('should return expected privileges for elastic admin', async () => { - const { body } = await supertest.get(DETECTION_ENGINE_PRIVILEGES_URL).send().expect(200); - expect(body).to.eql({ - username: 'elastic', - has_all_requested: true, - cluster: { - monitor_ml: true, - manage_ccr: true, - manage_index_templates: true, - monitor_watcher: true, - monitor_transform: true, - read_ilm: true, - manage_api_key: true, - manage_security: true, - manage_own_api_key: true, - manage_saml: true, - all: true, - manage_ilm: true, - manage_ingest_pipelines: true, - read_ccr: true, - manage_rollup: true, - monitor: true, - manage_watcher: true, - manage: true, - manage_transform: true, - manage_token: true, - manage_ml: true, - manage_pipeline: true, - monitor_rollup: true, - transport_client: true, - create_snapshot: true, - }, - index: { - '.alerts-security.alerts-default': { - all: true, - manage_ilm: true, - read: true, - create_index: true, - read_cross_cluster: true, - index: true, - monitor: true, - delete: true, - manage: true, - delete_index: true, - create_doc: true, - view_index_metadata: true, - create: true, - manage_follow_index: true, - manage_leader_index: true, - maintenance: true, - write: true, - }, - }, - application: {}, - is_authenticated: true, - has_encryption_key: true, - }); - }); - + describe('@ess @serverless Privileges', () => { it('should return expected privileges for a "t1_analyst" user', async () => { - await createUserAndRole(getService, ROLES.t1_analyst); const { body } = await supertestWithoutAuth .get(DETECTION_ENGINE_PRIVILEGES_URL) .auth(ROLES.t1_analyst, 'changeme') @@ -139,11 +75,9 @@ export default ({ getService }: FtrProviderContext) => { is_authenticated: true, has_encryption_key: true, }); - await deleteUserAndRole(getService, ROLES.t1_analyst); }); it('should return expected privileges for a "t2_analyst" user', async () => { - await createUserAndRole(getService, ROLES.t2_analyst); const { body } = await supertestWithoutAuth .get(DETECTION_ENGINE_PRIVILEGES_URL) .auth(ROLES.t2_analyst, 'changeme') @@ -204,76 +138,9 @@ export default ({ getService }: FtrProviderContext) => { is_authenticated: true, has_encryption_key: true, }); - await deleteUserAndRole(getService, ROLES.t2_analyst); - }); - - it('should return expected privileges for a "hunter" user', async () => { - await createUserAndRole(getService, ROLES.hunter); - const { body } = await supertestWithoutAuth - .get(DETECTION_ENGINE_PRIVILEGES_URL) - .auth(ROLES.hunter, 'changeme') - .send() - .expect(200); - expect(body).to.eql({ - username: 'hunter', - has_all_requested: false, - cluster: { - monitor_ml: false, - manage_ccr: false, - manage_index_templates: false, - monitor_watcher: false, - monitor_transform: false, - read_ilm: false, - manage_api_key: false, - manage_security: false, - manage_own_api_key: false, - manage_saml: false, - all: false, - manage_ilm: false, - manage_ingest_pipelines: false, - read_ccr: false, - manage_rollup: false, - monitor: false, - manage_watcher: false, - manage: false, - manage_transform: false, - manage_token: false, - manage_ml: false, - manage_pipeline: false, - monitor_rollup: false, - transport_client: false, - create_snapshot: false, - }, - index: { - '.alerts-security.alerts-default': { - all: false, - manage_ilm: false, - read: true, - create_index: false, - read_cross_cluster: false, - index: true, - monitor: false, - delete: true, - manage: false, - delete_index: false, - create_doc: true, - view_index_metadata: false, - create: true, - manage_follow_index: false, - manage_leader_index: false, - maintenance: false, - write: true, - }, - }, - application: {}, - is_authenticated: true, - has_encryption_key: true, - }); - await deleteUserAndRole(getService, ROLES.hunter); }); it('should return expected privileges for a "rule_author" user', async () => { - await createUserAndRole(getService, ROLES.rule_author); const { body } = await supertestWithoutAuth .get(DETECTION_ENGINE_PRIVILEGES_URL) .auth(ROLES.rule_author, 'changeme') @@ -334,11 +201,9 @@ export default ({ getService }: FtrProviderContext) => { is_authenticated: true, has_encryption_key: true, }); - await deleteUserAndRole(getService, ROLES.rule_author); }); it('should return expected privileges for a "soc_manager" user', async () => { - await createUserAndRole(getService, ROLES.soc_manager); const { body } = await supertestWithoutAuth .get(DETECTION_ENGINE_PRIVILEGES_URL) .auth(ROLES.soc_manager, 'changeme') @@ -399,11 +264,9 @@ export default ({ getService }: FtrProviderContext) => { is_authenticated: true, has_encryption_key: true, }); - await deleteUserAndRole(getService, ROLES.soc_manager); }); it('should return expected privileges for a "platform_engineer" user', async () => { - await createUserAndRole(getService, ROLES.platform_engineer); const { body } = await supertestWithoutAuth .get(DETECTION_ENGINE_PRIVILEGES_URL) .auth(ROLES.platform_engineer, 'changeme') @@ -464,72 +327,6 @@ export default ({ getService }: FtrProviderContext) => { is_authenticated: true, has_encryption_key: true, }); - await deleteUserAndRole(getService, ROLES.platform_engineer); - }); - - it('should return expected privileges for a "detections_admin" user', async () => { - await createUserAndRole(getService, ROLES.detections_admin); - const { body } = await supertestWithoutAuth - .get(DETECTION_ENGINE_PRIVILEGES_URL) - .auth(ROLES.detections_admin, 'changeme') - .send() - .expect(200); - expect(body).to.eql({ - username: 'detections_admin', - has_all_requested: false, - cluster: { - monitor_ml: true, - manage_ccr: false, - manage_index_templates: true, - monitor_watcher: true, - monitor_transform: true, - read_ilm: true, - manage_api_key: false, - manage_security: false, - manage_own_api_key: false, - manage_saml: false, - all: false, - manage_ilm: true, - manage_ingest_pipelines: true, - read_ccr: false, - manage_rollup: true, - monitor: true, - manage_watcher: true, - manage: true, - manage_transform: true, - manage_token: false, - manage_ml: true, - manage_pipeline: true, - monitor_rollup: true, - transport_client: true, - create_snapshot: true, - }, - index: { - '.alerts-security.alerts-default': { - all: false, - manage_ilm: true, - read: true, - create_index: true, - read_cross_cluster: false, - index: true, - monitor: true, - delete: true, - manage: true, - delete_index: true, - create_doc: true, - view_index_metadata: true, - create: true, - manage_follow_index: true, - manage_leader_index: true, - maintenance: true, - write: true, - }, - }, - application: {}, - is_authenticated: true, - has_encryption_key: true, - }); - await deleteUserAndRole(getService, ROLES.detections_admin); }); }); }; diff --git a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/check_privileges.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/rule_privileges.ts similarity index 55% rename from x-pack/test/detection_engine_api_integration/security_and_spaces/group1/check_privileges.ts rename to x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/rule_privileges.ts index 3a016fe68618d..57de1072985fd 100644 --- a/x-pack/test/detection_engine_api_integration/security_and_spaces/group1/check_privileges.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/rule_privileges.ts @@ -8,71 +8,76 @@ import expect from '@kbn/expect'; import { DETECTION_ENGINE_RULES_URL } from '@kbn/security-solution-plugin/common/constants'; import { ROLES } from '@kbn/security-solution-plugin/common/test'; -import { ThresholdRuleCreateProps } from '@kbn/security-solution-plugin/common/api/detection_engine'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; import { - createSignalsIndex, + createDetectionEngineIndices, deleteAllRules, waitForRulePartialFailure, - getRuleForSignalTesting, createRuleWithAuth, - getThresholdRuleForSignalTesting, deleteAllAlerts, + getCustomQueryRule, + getThresholdRule, } from '../../utils'; -import { createUserAndRole, deleteUserAndRole } from '../../../common/services/security_solution'; -// eslint-disable-next-line import/no-default-export export default ({ getService }: FtrProviderContext) => { const supertest = getService('supertest'); - const esArchiver = getService('esArchiver'); const supertestWithoutAuth = getService('supertestWithoutAuth'); const log = getService('log'); const es = getService('es'); - describe('check_privileges', () => { - before(async () => { - await esArchiver.load('x-pack/test/functional/es_archives/auditbeat/hosts'); - await esArchiver.load('x-pack/test/functional/es_archives/security_solution/alias'); - await createSignalsIndex(supertest, log); - }); + const INDEX_WITH_ACCESS = 'logs-test'; + const INDEX_WITH_ACCESS_PATTERN = 'logs-*'; + const INDEX_WITHOUT_ACCESS = 'unknown'; + const INDEX_WITHOUT_ACCESS_PATTERN = 'unknown'; - after(async () => { - await esArchiver.unload('x-pack/test/functional/es_archives/auditbeat/hosts'); - await esArchiver.unload('x-pack/test/functional/es_archives/security_solution/alias'); + describe('@ess @serverless Rule privileges', () => { + before(async () => { + await createDetectionEngineIndices(supertest, log); await deleteAllAlerts(supertest, log, es); + await es.indices.delete({ index: INDEX_WITH_ACCESS, ignore_unavailable: true }); + await es.indices.delete({ index: INDEX_WITHOUT_ACCESS, ignore_unavailable: true }); + // @timestamp mapping is required for the Threshold rule testing + await es.indices.create({ + index: 'logs-test', + mappings: { + properties: { + '@timestamp': { + type: 'date', + }, + }, + }, + }); }); beforeEach(async () => { await deleteAllRules(supertest, log); }); - afterEach(async () => { - await deleteAllRules(supertest, log); - }); - describe('should set status to partial failure when user has no access', () => { - const indexTestCases = [ - ['host_alias'], - ['host_alias', 'auditbeat-8.0.0'], - ['host_alias*'], - ['host_alias*', 'auditbeat-*'], - ]; - indexTestCases.forEach((index) => { - it(`for KQL rule with index param: ${index}`, async () => { - const rule = { - ...getRuleForSignalTesting(index), + [ + [INDEX_WITHOUT_ACCESS], + [INDEX_WITH_ACCESS, INDEX_WITHOUT_ACCESS], + [INDEX_WITHOUT_ACCESS_PATTERN], + [INDEX_WITH_ACCESS_PATTERN, INDEX_WITHOUT_ACCESS_PATTERN], + ].forEach((indices) => { + it(`for KQL rule with index param: ${indices}`, async () => { + const rule = getCustomQueryRule({ + index: indices, query: 'process.executable: "/usr/bin/sudo"', - }; - await createUserAndRole(getService, ROLES.detections_admin); + from: 'now-1h', + enabled: true, + }); const { id } = await createRuleWithAuth(supertestWithoutAuth, rule, { user: ROLES.detections_admin, pass: 'changeme', }); + await waitForRulePartialFailure({ supertest, log, id, }); + const { body } = await supertest .get(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') @@ -82,36 +87,36 @@ export default ({ getService }: FtrProviderContext) => { // TODO: https://github.com/elastic/kibana/pull/121644 clean up, make type-safe expect(body?.execution_summary?.last_execution.message).to.eql( - `This rule may not have the required read privileges to the following index patterns: ["${index[0]}"]` + `This rule may not have the required read privileges to the following index patterns: ["${INDEX_WITHOUT_ACCESS}"]` ); - - await deleteUserAndRole(getService, ROLES.detections_admin); }); }); - const thresholdIndexTestCases = [ - ['host_alias', 'auditbeat-8.0.0'], - ['host_alias*', 'auditbeat-*'], - ]; - thresholdIndexTestCases.forEach((index) => { - it(`for threshold rule with index param: ${index}`, async () => { - const rule: ThresholdRuleCreateProps = { - ...getThresholdRuleForSignalTesting(index), + [ + [INDEX_WITH_ACCESS, INDEX_WITHOUT_ACCESS], + [INDEX_WITH_ACCESS_PATTERN, INDEX_WITHOUT_ACCESS_PATTERN], + ].forEach((indices) => { + it(`for threshold rule with index param: ${indices}`, async () => { + const rule = getThresholdRule({ + index: indices, threshold: { field: [], - value: 700, + value: 1, }, - }; - await createUserAndRole(getService, ROLES.detections_admin); + from: 'now-1h', + enabled: true, + }); const { id } = await createRuleWithAuth(supertestWithoutAuth, rule, { user: ROLES.detections_admin, pass: 'changeme', }); + await waitForRulePartialFailure({ supertest, log, id, }); + const { body } = await supertest .get(DETECTION_ENGINE_RULES_URL) .set('kbn-xsrf', 'true') @@ -121,10 +126,8 @@ export default ({ getService }: FtrProviderContext) => { // TODO: https://github.com/elastic/kibana/pull/121644 clean up, make type-safe expect(body?.execution_summary?.last_execution.message).to.eql( - `This rule may not have the required read privileges to the following index patterns: ["${index[0]}"]` + `This rule may not have the required read privileges to the following index patterns: ["${INDEX_WITHOUT_ACCESS}"]` ); - - await deleteUserAndRole(getService, ROLES.detections_admin); }); }); }); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/serverless_only_privileges.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/serverless_only_privileges.ts new file mode 100644 index 0000000000000..6da2bda62d4fa --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/default_license/privileges/serverless_only_privileges.ts @@ -0,0 +1,140 @@ +/* + * 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 expect from '@kbn/expect'; +import { DETECTION_ENGINE_PRIVILEGES_URL } from '@kbn/security-solution-plugin/common/constants'; +import { ROLES } from '@kbn/security-solution-plugin/common/test'; +import { FtrProviderContext } from '../../../../ftr_provider_context'; + +export default ({ getService }: FtrProviderContext) => { + const supertest = getService('supertest'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + + describe('@serverless Privileges', () => { + it('should return expected privileges for elastic admin', async () => { + const { body } = await supertest.get(DETECTION_ENGINE_PRIVILEGES_URL).send().expect(200); + expect(body).to.eql({ + username: 'elastic_serverless', + has_all_requested: true, + cluster: { + monitor_ml: true, + manage_ccr: true, + manage_index_templates: true, + monitor_watcher: true, + monitor_transform: true, + read_ilm: true, + manage_api_key: true, + manage_security: true, + manage_own_api_key: true, + manage_saml: true, + all: true, + manage_ilm: true, + manage_ingest_pipelines: true, + read_ccr: true, + manage_rollup: true, + monitor: true, + manage_watcher: true, + manage: true, + manage_transform: true, + manage_token: true, + manage_ml: true, + manage_pipeline: true, + monitor_rollup: true, + transport_client: true, + create_snapshot: true, + }, + index: { + '.alerts-security.alerts-default': { + all: true, + manage_ilm: true, + read: true, + create_index: true, + read_cross_cluster: true, + index: true, + monitor: true, + delete: true, + manage: true, + delete_index: true, + create_doc: true, + view_index_metadata: true, + create: true, + manage_follow_index: true, + manage_leader_index: true, + maintenance: true, + write: true, + }, + }, + application: {}, + is_authenticated: true, + has_encryption_key: true, + }); + }); + + it('should return expected privileges for a "detections_admin" user', async () => { + const { body } = await supertestWithoutAuth + .get(DETECTION_ENGINE_PRIVILEGES_URL) + .auth(ROLES.detections_admin, 'changeme') + .send() + .expect(200); + expect(body).to.eql({ + username: 'detections_admin', + has_all_requested: false, + cluster: { + monitor_ml: false, + manage_ccr: false, + manage_index_templates: true, + monitor_watcher: false, + monitor_transform: true, + read_ilm: false, + manage_api_key: false, + manage_security: false, + manage_own_api_key: false, + manage_saml: false, + all: false, + manage_ilm: false, + manage_ingest_pipelines: false, + read_ccr: false, + manage_rollup: false, + monitor: false, + manage_watcher: false, + manage: false, + manage_transform: true, + manage_token: false, + manage_ml: false, + manage_pipeline: false, + monitor_rollup: false, + transport_client: false, + create_snapshot: false, + }, + index: { + '.alerts-security.alerts-default': { + all: false, + manage_ilm: true, + read: true, + create_index: true, + read_cross_cluster: false, + index: true, + monitor: true, + delete: true, + manage: true, + delete_index: true, + create_doc: true, + view_index_metadata: true, + create: true, + manage_follow_index: true, + manage_leader_index: true, + maintenance: true, + write: true, + }, + }, + application: {}, + is_authenticated: true, + has_encryption_key: true, + }); + }); + }); +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/create_detection_engine_indices.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/create_detection_engine_indices.ts new file mode 100644 index 0000000000000..fac8d70f91100 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/create_detection_engine_indices.ts @@ -0,0 +1,37 @@ +/* + * 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 SuperTest from 'supertest'; +import { ToolingLog } from '@kbn/tooling-log'; + +import { DETECTION_ENGINE_INDEX_URL } from '@kbn/security-solution-plugin/common/constants'; +import { countDownTest } from './count_down_test'; + +/** + * Creates the detection engine indices for use inside of beforeEach blocks of tests + * This will retry 50 times before giving up and hopefully still not interfere with other tests + * @param supertest The supertest client library + */ +export const createDetectionEngineIndices = async ( + supertest: SuperTest.SuperTest, + log: ToolingLog +): Promise => { + await countDownTest( + async () => { + await supertest + .post(DETECTION_ENGINE_INDEX_URL) + .set('kbn-xsrf', 'true') + .set('elastic-api-version', '2023-10-31') + .send(); + return { + passed: true, + }; + }, + 'createDetectionEngineIndices', + log + ); +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/generate_event.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/generate_event.ts new file mode 100644 index 0000000000000..ea7a61f222eec --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/generate_event.ts @@ -0,0 +1,17 @@ +/* + * 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 { SecurityEvent } from './types'; + +export function generateEvent(extra: Record = {}): SecurityEvent { + return { + '@timestamp': Date.now(), + ecs: { version: '1.4.0' }, + event: { kind: 'event', category: 'process', type: 'start' }, + ...extra, + }; +} diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/index.ts index 3289ea7d8f7ab..89549354bf401 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/index.ts @@ -16,3 +16,5 @@ export * from './count_down_test'; export * from './count_down_es'; export * from './update_username'; export * from './refresh_index'; +export * from './create_detection_engine_indices'; +export * from './generate_event'; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_rule_with_auth.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_rule_with_auth.ts new file mode 100644 index 0000000000000..f465dcf598895 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/create_rule_with_auth.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 type SuperTest from 'supertest'; + +import { DETECTION_ENGINE_RULES_URL } from '@kbn/security-solution-plugin/common/constants'; +import type { + RuleCreateProps, + RuleResponse, +} from '@kbn/security-solution-plugin/common/api/detection_engine'; + +/** + * Helper to cut down on the noise in some of the tests. + * @param supertest The supertest deps + * @param rule The rule to create + */ +export const createRuleWithAuth = async ( + supertest: SuperTest.SuperTest, + rule: RuleCreateProps, + auth: { user: string; pass: string } +): Promise => { + const { body } = await supertest + .post(DETECTION_ENGINE_RULES_URL) + .set('kbn-xsrf', 'true') + .set('elastic-api-version', '2023-10-31') + .auth(auth.user, auth.pass) + .send(rule) + .expect(200); + + return body; +}; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_custom_query_rule.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_custom_query_rule.ts new file mode 100644 index 0000000000000..6971e71fc8eda --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_custom_query_rule.ts @@ -0,0 +1,33 @@ +/* + * 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 { QueryRuleCreateProps } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { CreateRulePropsRewrites } from './types'; + +/** + * Returns custom query rule params that is easy for most basic testing of output of alerts. + * It starts out in an disabled. The 'from' is set very far back to test the basics of signal + * creation and testing by getting all the signals at once. + * + * @param rewrites rule params rewrites, see QueryRuleCreateProps for possible fields + */ +export const getCustomQueryRule = ( + rewrites?: CreateRulePropsRewrites +): QueryRuleCreateProps => ({ + type: 'query', + query: '*:*', + name: 'Custom query rule', + description: 'Custom query rule description', + risk_score: 1, + rule_id: 'rule-1', + severity: 'high', + index: ['auditbeat-*'], + interval: '100m', + from: 'now-6m', + enabled: false, + ...rewrites, +}); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_threshold_rule.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_threshold_rule.ts new file mode 100644 index 0000000000000..2c7ebcb65c2f5 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/get_threshold_rule.ts @@ -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 type { ThresholdRuleCreateProps } from '@kbn/security-solution-plugin/common/api/detection_engine'; +import { CreateRulePropsRewrites } from './types'; + +/** + * This is a typical signal testing rule that is easy for most basic testing of output of Threshold signals. + * It starts out in an enabled true state. The 'from' is set very far back to test the basics of signal + * creation for Threshold and testing by getting all the signals at once. + * @param ruleId The optional ruleId which is threshold-rule by default. + * @param enabled Enables the rule on creation or not. Defaulted to true. + */ +export const getThresholdRule = ( + rewrites?: CreateRulePropsRewrites +): ThresholdRuleCreateProps => ({ + type: 'threshold', + query: '*:*', + index: ['auditbeat-*'], + name: 'Threshold Rule', + description: 'The new rule description.', + severity: 'high', + risk_score: 17, + tags: ['test', 'newRule'], + references: ['http://example.com/', 'https://example.com/'], + false_positives: ['False1', 'False2'], + note: '# test markdown', + threshold: { + field: 'process.name', + value: 21, + }, + interval: '100m', + from: 'now-6m', + max_signals: 100, + enabled: false, + ...rewrites, +}); diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/index.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/index.ts index 0170faa8ceeda..49ec6bbdbaa2f 100644 --- a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/index.ts +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/index.ts @@ -7,8 +7,11 @@ export * from './get_rule'; export * from './get_simple_rule'; export * from './create_rule'; +export * from './create_rule_with_auth'; export * from './delete_all_rules'; export * from './delete_rule'; +export * from './get_custom_query_rule'; +export * from './get_threshold_rule'; export * from './get_simple_rule_output'; export * from './get_simple_rule_output_without_rule_id'; export * from './get_simple_rule_without_rule_id'; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/types.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/types.ts new file mode 100644 index 0000000000000..f8acb18aa9930 --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/rules/types.ts @@ -0,0 +1,8 @@ +/* + * 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 type CreateRulePropsRewrites = Partial>; diff --git a/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/types.ts b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/types.ts new file mode 100644 index 0000000000000..3052ee26e259b --- /dev/null +++ b/x-pack/test/security_solution_api_integration/test_suites/detections_response/utils/types.ts @@ -0,0 +1,19 @@ +/* + * 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 interface SecurityEvent { + [field: string]: unknown; + '@timestamp': number; + ecs: { + version: string; + }; + event: { + kind: 'event'; + category: string; + type: string; + }; +}