From 73ef3cf9c3c66919c90f038c14164424aebd2b7a Mon Sep 17 00:00:00 2001 From: Tre Date: Fri, 21 Jun 2024 11:33:25 +0100 Subject: [PATCH] [FTR](platform-security) update common serverless api tests to use api keys (#184935) ## Summary - Update files within: `x-pack/test_serverless/api_integration/test_suites/common/platform_security/` Contributes to: https://github.com/elastic/kibana/issues/180834 --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../common/platform_security/anonymous.ts | 23 ++- .../common/platform_security/api_keys.ts | 62 ++++--- .../platform_security/authentication.ts | 21 ++- .../platform_security/authentication_http.ts | 8 +- .../common/platform_security/authorization.ts | 74 +++++---- .../encrypted_saved_objects.ts | 18 +- .../common/platform_security/feature_check.ts | 16 +- .../common/platform_security/misc.ts | 36 ++-- .../platform_security/response_headers.ts | 16 +- .../common/platform_security/role_mappings.ts | 41 +++-- .../common/platform_security/sessions.ts | 28 +++- .../common/platform_security/user_profiles.ts | 14 +- .../common/platform_security/users.ts | 155 +++++++++-------- .../common/platform_security/views.ts | 97 +++++++---- .../common/reporting/datastream.ts | 43 +++-- .../common/reporting/generate_csv_discover.ts | 156 +++++++++++++----- .../common/reporting/management.ts | 15 +- .../shared/services/svl_reporting.ts | 45 +++-- 18 files changed, 582 insertions(+), 286 deletions(-) diff --git a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/anonymous.ts b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/anonymous.ts index 0b08aa18ce1281..337e3d1c3988c5 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/anonymous.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/anonymous.ts @@ -6,25 +6,38 @@ */ import { FtrProviderContext } from '../../../ftr_provider_context'; +import { InternalRequestHeader, RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { const svlCommonApi = getService('svlCommonApi'); - const supertest = getService('supertest'); + const svlUserManager = getService('svlUserManager'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + let roleAuthc: RoleCredentials; + let internalReqHeader: InternalRequestHeader; describe('security/anonymous', function () { + before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + internalReqHeader = svlCommonApi.getInternalRequestHeader(); + }); + after(async () => { + await svlUserManager.invalidateApiKeyForRole(roleAuthc); + }); describe('route access', () => { describe('disabled', () => { it('get access capabilities', async () => { - const { body, status } = await supertest + const { body, status } = await supertestWithoutAuth .get('/internal/security/anonymous_access/capabilities') - .set(svlCommonApi.getCommonRequestHeader()); + .set(internalReqHeader) + .set(roleAuthc.apiKeyHeader); svlCommonApi.assertApiNotFound(body, status); }); it('get access state', async () => { - const { body, status } = await supertest + const { body, status } = await supertestWithoutAuth .get('/internal/security/anonymous_access/state') - .set(svlCommonApi.getCommonRequestHeader()); + .set(internalReqHeader) + .set(roleAuthc.apiKeyHeader); svlCommonApi.assertApiNotFound(body, status); }); }); diff --git a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/api_keys.ts b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/api_keys.ts index 691f448ca0ab2a..c61d01970ba78f 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/api_keys.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/api_keys.ts @@ -7,18 +7,28 @@ import expect from 'expect'; import { FtrProviderContext } from '../../../ftr_provider_context'; +import { RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { - const svlCommonApi = getService('svlCommonApi'); - const supertest = getService('supertest'); let roleMapping: { id: string; name: string; api_key: string; encoded: string }; - + const supertest = getService('supertest'); + const svlCommonApi = getService('svlCommonApi'); + const svlUserManager = getService('svlUserManager'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + let roleAuthc: RoleCredentials; describe('security/api_keys', function () { + before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + }); + after(async () => { + await svlUserManager.invalidateApiKeyForRole(roleAuthc); + }); describe('route access', () => { describe('internal', () => { before(async () => { - const { body, status } = await supertest + const { body, status } = await supertestWithoutAuth .post('/internal/security/api_key') + .set(roleAuthc.cookieHeader) .set(svlCommonApi.getInternalRequestHeader()) .send({ name: 'test', @@ -29,14 +39,16 @@ export default function ({ getService }: FtrProviderContext) { roleMapping = body; }); - after(async () => { - const { body, status } = await supertest + after(async function invalidateAll() { + const { body, status } = await supertestWithoutAuth .get('/internal/security/api_key?isAdmin=true') + .set(roleAuthc.cookieHeader) .set(svlCommonApi.getInternalRequestHeader()); if (status === 200) { - await supertest + await supertestWithoutAuth .post('/internal/security/api_key/invalidate') + .set(roleAuthc.cookieHeader) .set(svlCommonApi.getInternalRequestHeader()) .send({ apiKeys: body?.apiKeys, @@ -54,23 +66,22 @@ export default function ({ getService }: FtrProviderContext) { role_descriptors: {}, }; - ({ body, status } = await supertest + ({ body, status } = await supertestWithoutAuth .post('/internal/security/api_key') .set(svlCommonApi.getCommonRequestHeader()) .send(requestBody)); // expect a rejection because we're not using the internal header expect(body).toEqual({ - statusCode: 400, - error: 'Bad Request', - message: expect.stringContaining( - 'method [post] exists but is not available with the current configuration' - ), + statusCode: 401, + error: 'Unauthorized', + message: expect.stringContaining('Unauthorized'), }); - expect(status).toBe(400); + expect(status).toBe(401); - ({ body, status } = await supertest + ({ body, status } = await supertestWithoutAuth .post('/internal/security/api_key') .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.cookieHeader) .send(requestBody)); // expect success because we're using the internal header expect(body).toEqual(expect.objectContaining({ name: 'create_test' })); @@ -86,9 +97,10 @@ export default function ({ getService }: FtrProviderContext) { role_descriptors: {}, }; - ({ body, status } = await supertest + ({ body, status } = await supertestWithoutAuth .put('/internal/security/api_key') .set(svlCommonApi.getCommonRequestHeader()) + .set(roleAuthc.cookieHeader) .send(requestBody)); // expect a rejection because we're not using the internal header expect(body).toEqual({ @@ -100,9 +112,10 @@ export default function ({ getService }: FtrProviderContext) { }); expect(status).toBe(400); - ({ body, status } = await supertest + ({ body, status } = await supertestWithoutAuth .put('/internal/security/api_key') .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.cookieHeader) .send(requestBody)); // expect success because we're using the internal header expect(body).toEqual(expect.objectContaining({ updated: true })); @@ -115,7 +128,8 @@ export default function ({ getService }: FtrProviderContext) { ({ body, status } = await supertest .get('/internal/security/api_key/_enabled') - .set(svlCommonApi.getCommonRequestHeader())); + .set(svlCommonApi.getCommonRequestHeader()) + .set(roleAuthc.cookieHeader)); // expect a rejection because we're not using the internal header expect(body).toEqual({ statusCode: 400, @@ -126,8 +140,9 @@ export default function ({ getService }: FtrProviderContext) { }); expect(status).toBe(400); - ({ body, status } = await supertest + ({ body, status } = await supertestWithoutAuth .get('/internal/security/api_key/_enabled') + .set(roleAuthc.cookieHeader) .set(svlCommonApi.getInternalRequestHeader())); // expect success because we're using the internal header expect(body).toEqual({ apiKeysEnabled: true }); @@ -147,9 +162,10 @@ export default function ({ getService }: FtrProviderContext) { isAdmin: true, }; - ({ body, status } = await supertest + ({ body, status } = await supertestWithoutAuth .post('/internal/security/api_key/invalidate') .set(svlCommonApi.getCommonRequestHeader()) + .set(roleAuthc.cookieHeader) .send(requestBody)); // expect a rejection because we're not using the internal header expect(body).toEqual({ @@ -161,9 +177,10 @@ export default function ({ getService }: FtrProviderContext) { }); expect(status).toBe(400); - ({ body, status } = await supertest + ({ body, status } = await supertestWithoutAuth .post('/internal/security/api_key/invalidate') .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.cookieHeader) .send(requestBody)); // expect success because we're using the internal header expect(body).toEqual({ @@ -188,9 +205,10 @@ export default function ({ getService }: FtrProviderContext) { size: 1, }; - const { body } = await supertest + const { body } = await supertestWithoutAuth .post('/internal/security/api_key/_query') .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.cookieHeader) .send(requestBody) .expect(200); diff --git a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/authentication.ts b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/authentication.ts index da71d2ad4858ad..d1cb2b29b56b5a 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/authentication.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/authentication.ts @@ -7,27 +7,38 @@ import expect from 'expect'; import { FtrProviderContext } from '../../../ftr_provider_context'; +import { RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { - const svlCommonApi = getService('svlCommonApi'); const supertest = getService('supertest'); const config = getService('config'); + const svlCommonApi = getService('svlCommonApi'); + const svlUserManager = getService('svlUserManager'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + let roleAuthc: RoleCredentials; describe('security/authentication', function () { + before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + }); + after(async () => { + await svlUserManager.invalidateApiKeyForRole(roleAuthc); + }); describe('route access', () => { describe('disabled', () => { // ToDo: uncomment when we disable login // it('login', async () => { - // const { body, status } = await supertest + // const { body, status } = await supertestWithoutAuth // .post('/internal/security/login') - // .set(svlCommonApi.getInternalRequestHeader()); + // .set(svlCommonApi.getInternalRequestHeader()).set(roleAuthc.apiKeyHeader) // svlCommonApi.assertApiNotFound(body, status); // }); it('logout (deprecated)', async () => { - const { body, status } = await supertest + const { body, status } = await supertestWithoutAuth .get('/api/security/v1/logout') - .set(svlCommonApi.getInternalRequestHeader()); + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); svlCommonApi.assertApiNotFound(body, status); }); diff --git a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/authentication_http.ts b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/authentication_http.ts index 50148f28921544..6c7e939a3b6b08 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/authentication_http.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/authentication_http.ts @@ -9,7 +9,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const svlCommonApi = getService('svlCommonApi'); - const supertest = getService('supertestWithoutAuth'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); describe('security/authentication/http', function () { describe('JWT', () => { @@ -28,7 +28,7 @@ export default function ({ getService }: FtrProviderContext) { '/internal/task_manager/_background_task_utilization', '/api/task_manager/metrics', ]) { - await supertest + await supertestWithoutAuth .get(allowedPath) .set('Authorization', `Bearer ${jsonWebToken}`) .set('ES-Client-Authentication', 'SharedSecret my_super_secret') @@ -37,14 +37,14 @@ export default function ({ getService }: FtrProviderContext) { } // Make sure it's not possible to use JWT to have interactive sessions. - await supertest + await supertestWithoutAuth .get('/') .set('Authorization', `Bearer ${jsonWebToken}`) .set('ES-Client-Authentication', 'SharedSecret my_super_secret') .expect(401); // Make sure it's not possible to use JWT to access any other APIs. - await supertest + await supertestWithoutAuth .get('/internal/security/me') .set('Authorization', `Bearer ${jsonWebToken}`) .set('ES-Client-Authentication', 'SharedSecret my_super_secret') diff --git a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/authorization.ts b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/authorization.ts index d6ec69803b8f5e..672ff9cfdbedd8 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/authorization.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/authorization.ts @@ -8,6 +8,7 @@ import expect from 'expect'; import { KibanaFeatureConfig, SubFeaturePrivilegeConfig } from '@kbn/features-plugin/common'; import { FtrProviderContext } from '../../../ftr_provider_context'; +import { InternalRequestHeader, RoleCredentials } from '../../../../shared/services'; function collectSubFeaturesPrivileges(feature: KibanaFeatureConfig) { return new Map( @@ -22,60 +23,78 @@ function collectSubFeaturesPrivileges(feature: KibanaFeatureConfig) { } export default function ({ getService }: FtrProviderContext) { + const log = getService('log'); const svlCommonApi = getService('svlCommonApi'); + const svlUserManager = getService('svlUserManager'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); const supertest = getService('supertest'); - const log = getService('log'); + let roleAuthc: RoleCredentials; + let internalReqHeader: InternalRequestHeader; describe('security/authorization', function () { + before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + internalReqHeader = svlCommonApi.getInternalRequestHeader(); + }); + after(async () => { + await svlUserManager.invalidateApiKeyForRole(roleAuthc); + }); describe('route access', () => { describe('internal', () => { describe('disabled', () => { it('get all privileges', async () => { - const { body, status } = await supertest + const { body, status } = await supertestWithoutAuth .get('/api/security/privileges') - .set(svlCommonApi.getInternalRequestHeader()); + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); svlCommonApi.assertApiNotFound(body, status); }); it('get built-in elasticsearch privileges', async () => { - const { body, status } = await supertest + const { body, status } = await supertestWithoutAuth .get('/internal/security/esPrivileges/builtin') - .set(svlCommonApi.getInternalRequestHeader()); + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); svlCommonApi.assertApiNotFound(body, status); }); - it('create/update role', async () => { - const { body, status } = await supertest - .put('/api/security/role/test') - .set(svlCommonApi.getInternalRequestHeader()); + it('create/update roleAuthc', async () => { + const { body, status } = await supertestWithoutAuth + .put('/api/security/roleAuthc/test') + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); svlCommonApi.assertApiNotFound(body, status); }); - it('get role', async () => { - const { body, status } = await supertest - .get('/api/security/role/superuser') - .set(svlCommonApi.getInternalRequestHeader()); + it('get roleAuthc', async () => { + const { body, status } = await supertestWithoutAuth + .get('/api/security/roleAuthc/superuser') + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); svlCommonApi.assertApiNotFound(body, status); }); it('get all roles', async () => { - const { body, status } = await supertest - .get('/api/security/role') - .set(svlCommonApi.getInternalRequestHeader()); + const { body, status } = await supertestWithoutAuth + .get('/api/security/roleAuthc') + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); svlCommonApi.assertApiNotFound(body, status); }); - it('delete role', async () => { - const { body, status } = await supertest - .delete('/api/security/role/superuser') - .set(svlCommonApi.getInternalRequestHeader()); + it('delete roleAuthc', async () => { + const { body, status } = await supertestWithoutAuth + .delete('/api/security/roleAuthc/superuser') + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); svlCommonApi.assertApiNotFound(body, status); }); it('get shared saved object permissions', async () => { - const { body, status } = await supertest + const { body, status } = await supertestWithoutAuth .get('/internal/security/_share_saved_object_permissions') - .set(svlCommonApi.getInternalRequestHeader()); + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); svlCommonApi.assertApiNotFound(body, status); }); }); @@ -83,26 +102,25 @@ export default function ({ getService }: FtrProviderContext) { describe('public', () => { it('reset session page', async () => { - const { status } = await supertest + const { status } = await supertestWithoutAuth .get('/internal/security/reset_session_page.js') - .set(svlCommonApi.getCommonRequestHeader()); + .set(internalReqHeader) + .set(roleAuthc.apiKeyHeader); expect(status).toBe(200); }); }); }); describe('available features', () => { - const svlUserManager = getService('svlUserManager'); - const supertestWithoutAuth = getService('supertestWithoutAuth'); let adminCredentials: { Cookie: string }; before(async () => { - // get auth header for Viewer role + // get auth header for Viewer roleAuthc adminCredentials = await svlUserManager.getApiCredentialsForRole('admin'); }); it('all Dashboard and Discover sub-feature privileges are disabled', async () => { - const { body } = await supertestWithoutAuth + const { body } = await supertest .get('/api/features') .set(svlCommonApi.getInternalRequestHeader()) .set(adminCredentials) diff --git a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/encrypted_saved_objects.ts b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/encrypted_saved_objects.ts index 63d81773398cd9..55627e840fc17c 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/encrypted_saved_objects.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/encrypted_saved_objects.ts @@ -6,18 +6,30 @@ */ import { FtrProviderContext } from '../../../ftr_provider_context'; +import { InternalRequestHeader, RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { const svlCommonApi = getService('svlCommonApi'); - const supertest = getService('supertest'); + const svlUserManager = getService('svlUserManager'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + let roleAuthc: RoleCredentials; + let internalReqHeader: InternalRequestHeader; describe('encrypted saved objects', function () { + before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + internalReqHeader = svlCommonApi.getInternalRequestHeader(); + }); + after(async () => { + await svlUserManager.invalidateApiKeyForRole(roleAuthc); + }); describe('route access', () => { describe('disabled', () => { it('rotate key', async () => { - const { body, status } = await supertest + const { body, status } = await supertestWithoutAuth .post('/api/encrypted_saved_objects/_rotate_key') - .set(svlCommonApi.getCommonRequestHeader()); + .set(internalReqHeader) + .set(roleAuthc.apiKeyHeader); svlCommonApi.assertApiNotFound(body, status); }); }); diff --git a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/feature_check.ts b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/feature_check.ts index e42cb88eec0f80..3f79993262322f 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/feature_check.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/feature_check.ts @@ -6,16 +6,26 @@ */ import { FtrProviderContext } from '../../../ftr_provider_context'; +import { RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { const svlCommonApi = getService('svlCommonApi'); - const supertest = getService('supertest'); + const svlUserManager = getService('svlUserManager'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + let roleAuthc: RoleCredentials; describe('security/features', function () { + before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + }); + after(async () => { + await svlUserManager.invalidateApiKeyForRole(roleAuthc); + }); it('route access disabled', async () => { - const { body, status } = await supertest + const { body, status } = await supertestWithoutAuth .get('/internal/security/_check_security_features') - .set(svlCommonApi.getInternalRequestHeader()); + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); svlCommonApi.assertApiNotFound(body, status); }); }); diff --git a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/misc.ts b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/misc.ts index 2b49b3a96ab209..37c11fe6b59175 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/misc.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/misc.ts @@ -7,49 +7,63 @@ import expect from 'expect'; import { FtrProviderContext } from '../../../ftr_provider_context'; +import { RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { const svlCommonApi = getService('svlCommonApi'); - const supertest = getService('supertest'); + const svlUserManager = getService('svlUserManager'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + let roleAuthc: RoleCredentials; describe('security/misc', function () { + before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + }); + after(async () => { + await svlUserManager.invalidateApiKeyForRole(roleAuthc); + }); describe('route access', () => { describe('disabled', () => { it('get index fields', async () => { - const { body, status } = await supertest + const { body, status } = await supertestWithoutAuth .get('/internal/security/fields/test') .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader) .send({ params: 'params' }); svlCommonApi.assertApiNotFound(body, status); }); it('fix deprecated roles', async () => { - const { body, status } = await supertest + const { body, status } = await supertestWithoutAuth .post('/internal/security/deprecations/kibana_user_role/_fix_users') - .set(svlCommonApi.getInternalRequestHeader()); + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); svlCommonApi.assertApiNotFound(body, status); }); - it('fix deprecated role mappings', async () => { - const { body, status } = await supertest + it('fix deprecated roleAuthc mappings', async () => { + const { body, status } = await supertestWithoutAuth .post('/internal/security/deprecations/kibana_user_role/_fix_role_mappings') - .set(svlCommonApi.getInternalRequestHeader()); + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); svlCommonApi.assertApiNotFound(body, status); }); it('get security checkup state', async () => { - const { body, status } = await supertest + const { body, status } = await supertestWithoutAuth .get('/internal/security/security_checkup/state') - .set(svlCommonApi.getInternalRequestHeader()); + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); svlCommonApi.assertApiNotFound(body, status); }); }); describe('internal', () => { it('get record auth type', async () => { - const { status } = await supertest + const { status } = await supertestWithoutAuth .post('/internal/security/analytics/_record_auth_type') - .set(svlCommonApi.getInternalRequestHeader()); + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); expect(status).toBe(200); }); }); diff --git a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/response_headers.ts b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/response_headers.ts index 75413907fbd300..393645ba8b3609 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/response_headers.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/response_headers.ts @@ -8,10 +8,13 @@ import expect from 'expect'; import cspParser from 'content-security-policy-parser'; import { FtrProviderContext } from '../../../ftr_provider_context'; +import { RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { const svlCommonApi = getService('svlCommonApi'); - const supertest = getService('supertest'); + const svlUserManager = getService('svlUserManager'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + let roleAuthc: RoleCredentials; describe('security/response_headers', function () { const baseCSP = `script-src 'report-sample' 'self'; worker-src 'report-sample' 'self' blob:; style-src 'report-sample' 'self' 'unsafe-inline'; frame-ancestors 'self'`; @@ -23,9 +26,16 @@ export default function ({ getService }: FtrProviderContext) { const defaultXContentTypeOptions = 'nosniff'; const defaultXFrameOptions = 'SAMEORIGIN'; + before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + }); + after(async () => { + await svlUserManager.invalidateApiKeyForRole(roleAuthc); + }); it('API endpoint response contains default security headers', async () => { - const { header } = await supertest + const { header } = await supertestWithoutAuth .get(`/internal/security/me`) + .set(roleAuthc.apiKeyHeader) .set(svlCommonApi.getInternalRequestHeader()) .expect(200); @@ -40,7 +50,7 @@ export default function ({ getService }: FtrProviderContext) { }); it('redirect endpoint response contains default security headers', async () => { - const { header } = await supertest + const { header } = await supertestWithoutAuth .get(`/logout`) .set(svlCommonApi.getInternalRequestHeader()) .expect(200); diff --git a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/role_mappings.ts b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/role_mappings.ts index bfddf5b4a3267b..5e64dd88b1184c 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/role_mappings.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/role_mappings.ts @@ -6,40 +6,53 @@ */ import { FtrProviderContext } from '../../../ftr_provider_context'; +import { RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { const svlCommonApi = getService('svlCommonApi'); - const supertest = getService('supertest'); + const svlUserManager = getService('svlUserManager'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + let roleAuthc: RoleCredentials; describe('security/role_mappings', function () { + before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + }); + after(async () => { + await svlUserManager.invalidateApiKeyForRole(roleAuthc); + }); describe('route access', () => { describe('disabled', () => { - it('create/update role mapping', async () => { - const { body, status } = await supertest + it('create/update roleAuthc mapping', async () => { + const { body, status } = await supertestWithoutAuth .post('/internal/security/role_mapping/test') - .set(svlCommonApi.getInternalRequestHeader()); + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); svlCommonApi.assertApiNotFound(body, status); }); - it('get role mapping', async () => { - const { body, status } = await supertest + it('get roleAuthc mapping', async () => { + const { body, status } = await supertestWithoutAuth .get('/internal/security/role_mapping/test') - .set(svlCommonApi.getInternalRequestHeader()); + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); svlCommonApi.assertApiNotFound(body, status); }); - it('get all role mappings', async () => { - const { body, status } = await supertest + it('get all roleAuthc mappings', async () => { + const { body, status } = await supertestWithoutAuth .get('/internal/security/role_mapping') - .set(svlCommonApi.getInternalRequestHeader()); + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); svlCommonApi.assertApiNotFound(body, status); }); - it('delete role mapping', async () => { - // this test works because the message for a missing endpoint is different from a missing role mapping - const { body, status } = await supertest + it('delete roleAuthc mapping', async () => { + // this test works because the message for a missing endpoint is different from a missing roleAuthc mapping + const { body, status } = await supertestWithoutAuth .delete('/internal/security/role_mapping/test') - .set(svlCommonApi.getInternalRequestHeader()); + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); svlCommonApi.assertApiNotFound(body, status); }); }); diff --git a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/sessions.ts b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/sessions.ts index 2148447fa736f0..de2b1751c82c1a 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/sessions.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/sessions.ts @@ -7,18 +7,27 @@ import expect from 'expect'; import { FtrProviderContext } from '../../../ftr_provider_context'; +import { RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { const svlCommonApi = getService('svlCommonApi'); - const supertest = getService('supertest'); - + const svlUserManager = getService('svlUserManager'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + let roleAuthc: RoleCredentials; describe('security/sessions', function () { + before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + }); + after(async () => { + await svlUserManager.invalidateApiKeyForRole(roleAuthc); + }); describe('route access', () => { describe('disabled', () => { it('invalidate', async () => { - const { body, status } = await supertest + const { body, status } = await supertestWithoutAuth .post('/api/security/session/_invalidate') .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader) .send({ match: 'all' }); svlCommonApi.assertApiNotFound(body, status); }); @@ -29,9 +38,11 @@ export default function ({ getService }: FtrProviderContext) { let body: any; let status: number; - ({ body, status } = await supertest + ({ body, status } = await supertestWithoutAuth .get('/internal/security/session') + .set(roleAuthc.apiKeyHeader) .set(svlCommonApi.getCommonRequestHeader())); + // expect a rejection because we're not using the internal header expect(body).toEqual({ statusCode: 400, @@ -42,8 +53,9 @@ export default function ({ getService }: FtrProviderContext) { }); expect(status).toBe(400); - ({ body, status } = await supertest + ({ body, status } = await supertestWithoutAuth .get('/internal/security/session') + .set(roleAuthc.apiKeyHeader) .set(svlCommonApi.getInternalRequestHeader())); // expect 204 because there is no session expect(status).toBe(204); @@ -53,8 +65,9 @@ export default function ({ getService }: FtrProviderContext) { let body: any; let status: number; - ({ body, status } = await supertest + ({ body, status } = await supertestWithoutAuth .post('/internal/security/session') + .set(roleAuthc.apiKeyHeader) .set(svlCommonApi.getCommonRequestHeader())); // expect a rejection because we're not using the internal header expect(body).toEqual({ @@ -66,8 +79,9 @@ export default function ({ getService }: FtrProviderContext) { }); expect(status).toBe(400); - ({ body, status } = await supertest + ({ body, status } = await supertestWithoutAuth .post('/internal/security/session') + .set(roleAuthc.apiKeyHeader) .set(svlCommonApi.getInternalRequestHeader())); // expect redirect expect(status).toBe(302); diff --git a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/user_profiles.ts b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/user_profiles.ts index 83ef0c43356794..687a6ee453a2d7 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/user_profiles.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/user_profiles.ts @@ -8,13 +8,22 @@ import expect from 'expect'; import { kibanaTestUser } from '@kbn/test'; import { FtrProviderContext } from '../../../ftr_provider_context'; +import { RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { + const samlTools = getService('samlTools'); const svlCommonApi = getService('svlCommonApi'); + const svlUserManager = getService('svlUserManager'); const supertestWithoutAuth = getService('supertestWithoutAuth'); - const samlTools = getService('samlTools'); + let roleAuthc: RoleCredentials; describe('security/user_profiles', function () { + before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + }); + after(async () => { + await svlUserManager.invalidateApiKeyForRole(roleAuthc); + }); describe('route access', () => { describe('internal', () => { // When we run tests on MKI, SAML realm is configured differently, and we cannot handcraft SAML responses to @@ -25,6 +34,7 @@ export default function ({ getService }: FtrProviderContext) { const { status } = await supertestWithoutAuth .post(`/internal/security/user_profile/_data`) .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader) .set(await samlTools.login(kibanaTestUser.username)) .send({ key: 'value' }); expect(status).not.toBe(404); @@ -33,6 +43,7 @@ export default function ({ getService }: FtrProviderContext) { it('get current', async () => { const { status } = await supertestWithoutAuth .get(`/internal/security/user_profile`) + .set(roleAuthc.apiKeyHeader) .set(svlCommonApi.getInternalRequestHeader()) .set(await samlTools.login(kibanaTestUser.username)); expect(status).not.toBe(404); @@ -42,6 +53,7 @@ export default function ({ getService }: FtrProviderContext) { const { status } = await supertestWithoutAuth .get(`/internal/security/user_profile`) .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader) .set(await samlTools.login(kibanaTestUser.username)) .send({ uids: ['12345678'] }); expect(status).not.toBe(404); diff --git a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/users.ts b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/users.ts index 2feaa8878d1eff..b9979492ce417f 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/users.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/users.ts @@ -6,89 +6,105 @@ */ import expect from 'expect'; +import { RoleCredentials } from '../../../../shared/services'; import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const svlCommonApi = getService('svlCommonApi'); - const supertest = getService('supertest'); + const svlUserManager = getService('svlUserManager'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + let roleAuthc: RoleCredentials; describe('security/users', function () { + before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + }); + after(async () => { + await svlUserManager.invalidateApiKeyForRole(roleAuthc); + }); describe('route access', () => { // ToDo: uncomment when we disable user APIs - // describe('disabled', () => { - // it('get', async () => { - // const { body, status } = await supertest - // .get('/internal/security/users/elastic') - // .set(svlCommonApi.getInternalRequestHeader()); - // svlCommonApi.assertApiNotFound(body, status); - // }); - - // it('get all', async () => { - // const { body, status } = await supertest - // .get('/internal/security/users') - // .set(svlCommonApi.getInternalRequestHeader()); - // svlCommonApi.assertApiNotFound(body, status); - // }); - - // it('create/update', async () => { - // const { body, status } = await supertest - // .post(`/internal/security/users/some_testuser`) - // .set(svlCommonApi.getInternalRequestHeader()) - // .send({ username: 'some_testuser', password: 'testpassword', roles: [] }); - // svlCommonApi.assertApiNotFound(body, status); - // }); - - // it('delete', async () => { - // const { body, status } = await supertest - // .delete(`/internal/security/users/elastic`) - // .set(svlCommonApi.getInternalRequestHeader()); - // svlCommonApi.assertApiNotFound(body, status); - // }); - - // it('disable', async () => { - // const { body, status } = await supertest - // .post(`/internal/security/users/elastic/_disable`) - // .set(svlCommonApi.getInternalRequestHeader()); - // svlCommonApi.assertApiNotFound(body, status); - // }); - - // it('enable', async () => { - // const { body, status } = await supertest - // .post(`/internal/security/users/elastic/_enable`) - // .set(svlCommonApi.getInternalRequestHeader()); - // svlCommonApi.assertApiNotFound(body, status); - // }); - - // it('set password', async () => { - // const { body, status } = await supertest - // .post(`/internal/security/users/{username}/password`) - // .set(svlCommonApi.getInternalRequestHeader()) - // .send({ - // password: 'old_pw', - // newPassword: 'new_pw', - // }); - // svlCommonApi.assertApiNotFound(body, status); - // }); - // }); + describe.skip('disabled', () => { + it('get', async () => { + const { body, status } = await supertestWithoutAuth + .get('/internal/security/users/elastic') + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); + svlCommonApi.assertApiNotFound(body, status); + }); + + it('get all', async () => { + const { body, status } = await supertestWithoutAuth + .get('/internal/security/users') + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); + svlCommonApi.assertApiNotFound(body, status); + }); + + it('create/update', async () => { + const { body, status } = await supertestWithoutAuth + .post(`/internal/security/users/some_testuser`) + .set(svlCommonApi.getInternalRequestHeader()) + .send({ username: 'some_testuser', password: 'testpassword', roles: [] }); + svlCommonApi.assertApiNotFound(body, status); + }); + + it('delete', async () => { + const { body, status } = await supertestWithoutAuth + .delete(`/internal/security/users/elastic`) + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); + svlCommonApi.assertApiNotFound(body, status); + }); + + it('disable', async () => { + const { body, status } = await supertestWithoutAuth + .post(`/internal/security/users/elastic/_disable`) + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); + svlCommonApi.assertApiNotFound(body, status); + }); + + it('enable', async () => { + const { body, status } = await supertestWithoutAuth + .post(`/internal/security/users/elastic/_enable`) + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); + svlCommonApi.assertApiNotFound(body, status); + }); + + it('set password', async () => { + const { body, status } = await supertestWithoutAuth + .post(`/internal/security/users/{username}/password`) + .set(svlCommonApi.getInternalRequestHeader()) + .send({ + password: 'old_pw', + newPassword: 'new_pw', + }); + svlCommonApi.assertApiNotFound(body, status); + }); + }); // ToDo: remove when we disable user APIs describe('internal', () => { it('get', async () => { - const { status } = await supertest + const { status } = await supertestWithoutAuth .get('/internal/security/users/elastic') - .set(svlCommonApi.getInternalRequestHeader()); + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); expect(status).not.toBe(404); }); it('get all', async () => { - const { status } = await supertest + const { status } = await supertestWithoutAuth .get('/internal/security/users') - .set(svlCommonApi.getInternalRequestHeader()); + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); expect(status).not.toBe(404); }); it('create/update', async () => { - const { status } = await supertest + const { status } = await supertestWithoutAuth .post(`/internal/security/users/some_testuser`) .set(svlCommonApi.getInternalRequestHeader()) .send({ username: 'some_testuser', password: 'testpassword', roles: [] }); @@ -96,28 +112,31 @@ export default function ({ getService }: FtrProviderContext) { }); it('delete', async () => { - const { status } = await supertest + const { status } = await supertestWithoutAuth .delete(`/internal/security/users/elastic`) - .set(svlCommonApi.getInternalRequestHeader()); + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); expect(status).not.toBe(404); }); it('disable', async () => { - const { status } = await supertest + const { status } = await supertestWithoutAuth .post(`/internal/security/users/elastic/_disable`) - .set(svlCommonApi.getInternalRequestHeader()); + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); expect(status).not.toBe(404); }); it('enable', async () => { - const { status } = await supertest + const { status } = await supertestWithoutAuth .post(`/internal/security/users/elastic/_enable`) - .set(svlCommonApi.getInternalRequestHeader()); + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); expect(status).not.toBe(404); }); it('set password', async () => { - const { status } = await supertest + const { status } = await supertestWithoutAuth .post(`/internal/security/users/{username}/password`) .set(svlCommonApi.getInternalRequestHeader()) .send({ diff --git a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/views.ts b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/views.ts index ac1d994252c578..3800d1f06b1340 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/views.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/views.ts @@ -6,106 +6,131 @@ */ import expect from 'expect'; +import { InternalRequestHeader, RoleCredentials } from '../../../../shared/services'; import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const svlCommonApi = getService('svlCommonApi'); - const supertest = getService('supertest'); + const svlUserManager = getService('svlUserManager'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + let roleAuthc: RoleCredentials; + let internalReqHeader: InternalRequestHeader; describe('security/views', function () { + before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + internalReqHeader = svlCommonApi.getInternalRequestHeader(); + }); + after(async () => { + await svlUserManager.invalidateApiKeyForRole(roleAuthc); + }); describe('route access', () => { describe('disabled', () => { - // ToDo: uncomment these when we disable login routes - // it('login', async () => { - // const { body, status } = await supertest - // .get('/login') - // .set(svlCommonApi.getInternalRequestHeader()); - // svlCommonApi.assertApiNotFound(body, status); - // }); + // ToDo: unskip these when we disable login routes + xit('login', async () => { + const { body, status } = await supertestWithoutAuth + .get('/login') + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); + svlCommonApi.assertApiNotFound(body, status); + }); - // it('get login state', async () => { - // const { body, status } = await supertest - // .get('/internal/security/login_state') - // .set(svlCommonApi.getInternalRequestHeader()); - // svlCommonApi.assertApiNotFound(body, status); - // }); + // ToDo: unskip these when we disable login routes + xit('get login state', async () => { + const { body, status } = await supertestWithoutAuth + .get('/internal/security/login_state') + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); + svlCommonApi.assertApiNotFound(body, status); + }); it('access agreement', async () => { - const { body, status } = await supertest + const { body, status } = await supertestWithoutAuth .get('/security/access_agreement') - .set(svlCommonApi.getInternalRequestHeader()); + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); svlCommonApi.assertApiNotFound(body, status); }); it('get access agreement state', async () => { - const { body, status } = await supertest + const { body, status } = await supertestWithoutAuth .get('/internal/security/access_agreement/state') - .set(svlCommonApi.getInternalRequestHeader()); + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); svlCommonApi.assertApiNotFound(body, status); }); }); describe('public', () => { it('login', async () => { - const { status } = await supertest + const { status } = await supertestWithoutAuth .get('/login') - .set(svlCommonApi.getInternalRequestHeader()); + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); expect(status).toBe(302); }); it('get login state', async () => { - const { status } = await supertest + const { status } = await supertestWithoutAuth .get('/internal/security/login_state') - .set(svlCommonApi.getInternalRequestHeader()); + .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader); expect(status).toBe(200); }); it('capture URL', async () => { - const { status } = await supertest + const { status } = await supertestWithoutAuth .get('/internal/security/capture-url') - .set(svlCommonApi.getCommonRequestHeader()); + .set(internalReqHeader) + .set(roleAuthc.apiKeyHeader); expect(status).toBe(200); }); it('space selector', async () => { - const { status } = await supertest + const { status } = await supertestWithoutAuth .get('/spaces/space_selector') - .set(svlCommonApi.getCommonRequestHeader()); + .set(internalReqHeader) + .set(roleAuthc.apiKeyHeader); expect(status).toBe(200); }); it('enter space', async () => { - const { status } = await supertest + const { status } = await supertestWithoutAuth .get('/spaces/enter') - .set(svlCommonApi.getCommonRequestHeader()); + .set(internalReqHeader) + .set(roleAuthc.apiKeyHeader); expect(status).toBe(302); }); it('account', async () => { - const { status } = await supertest + const { status } = await supertestWithoutAuth .get('/security/account') - .set(svlCommonApi.getCommonRequestHeader()); + .set(internalReqHeader) + .set(roleAuthc.apiKeyHeader); expect(status).toBe(200); }); it('logged out', async () => { - const { status } = await supertest + const { status } = await supertestWithoutAuth .get('/security/logged_out') - .set(svlCommonApi.getCommonRequestHeader()); + .set(internalReqHeader) + .set(roleAuthc.apiKeyHeader); expect(status).toBe(200); }); it('logout', async () => { - const { status } = await supertest + const { status } = await supertestWithoutAuth .get('/logout') - .set(svlCommonApi.getCommonRequestHeader()); + .set(internalReqHeader) + .set(roleAuthc.apiKeyHeader); expect(status).toBe(200); }); it('overwritten session', async () => { - const { status } = await supertest + const { status } = await supertestWithoutAuth .get('/security/overwritten_session') - .set(svlCommonApi.getCommonRequestHeader()); + .set(internalReqHeader) + .set(roleAuthc.apiKeyHeader); expect(status).toBe(200); }); }); diff --git a/x-pack/test_serverless/api_integration/test_suites/common/reporting/datastream.ts b/x-pack/test_serverless/api_integration/test_suites/common/reporting/datastream.ts index 1d336ec504250e..6cec7b7c2fcfbb 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/reporting/datastream.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/reporting/datastream.ts @@ -7,12 +7,17 @@ import { expect } from 'expect'; import { FtrProviderContext } from '../../../ftr_provider_context'; +import { InternalRequestHeader, RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); const reportingAPI = getService('svlReportingApi'); - const supertest = getService('supertest'); + const svlCommonApi = getService('svlCommonApi'); + const svlUserManager = getService('svlUserManager'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + let roleAuthc: RoleCredentials; + let internalReqHeader: InternalRequestHeader; const archives: Record = { ecommerce: { @@ -23,34 +28,42 @@ export default function ({ getService }: FtrProviderContext) { describe('Data Stream', () => { before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + internalReqHeader = svlCommonApi.getInternalRequestHeader(); await esArchiver.load(archives.ecommerce.data); await kibanaServer.importExport.load(archives.ecommerce.savedObjects); // for this test, we don't need to wait for the job to finish or verify the result - await reportingAPI.createReportJobInternal('csv_searchsource', { - browserTimezone: 'UTC', - objectType: 'search', - searchSource: { - index: '5193f870-d861-11e9-a311-0fa548c5f953', - query: { language: 'kuery', query: '' }, - version: true, + await reportingAPI.createReportJobInternal( + 'csv_searchsource', + { + browserTimezone: 'UTC', + objectType: 'search', + searchSource: { + index: '5193f870-d861-11e9-a311-0fa548c5f953', + query: { language: 'kuery', query: '' }, + version: true, + }, + title: 'Ecommerce Data', + version: '8.15.0', }, - title: 'Ecommerce Data', - version: '8.15.0', - }); + roleAuthc, + internalReqHeader + ); }); after(async () => { - await reportingAPI.deleteAllReports(); + await reportingAPI.deleteAllReports(roleAuthc, internalReqHeader); await esArchiver.unload(archives.ecommerce.data); await kibanaServer.importExport.unload(archives.ecommerce.savedObjects); + await svlUserManager.invalidateApiKeyForRole(roleAuthc); }); it('uses the datastream configuration with set ILM policy', async () => { - const { body } = await supertest + const { body } = await supertestWithoutAuth .get(`/api/index_management/data_streams/.kibana-reporting`) - .set('kbn-xsrf', 'xxx') - .set('x-elastic-internal-origin', 'xxx') + .set(internalReqHeader) + .set(roleAuthc.apiKeyHeader) .expect(200); expect(body).toEqual({ diff --git a/x-pack/test_serverless/api_integration/test_suites/common/reporting/generate_csv_discover.ts b/x-pack/test_serverless/api_integration/test_suites/common/reporting/generate_csv_discover.ts index 6fe25028cb3e7f..16342c37fc5792 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/reporting/generate_csv_discover.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/reporting/generate_csv_discover.ts @@ -9,12 +9,17 @@ import expect from '@kbn/expect'; import type { SortDirection } from '@kbn/data-plugin/common'; import type { JobParamsCSV } from '@kbn/reporting-export-types-csv-common'; import type { Filter } from '@kbn/es-query'; +import { InternalRequestHeader, RoleCredentials } from '../../../../shared/services'; import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); const kibanaServer = getService('kibanaServer'); const reportingAPI = getService('svlReportingApi'); + const svlCommonApi = getService('svlCommonApi'); + const svlUserManager = getService('svlUserManager'); + let roleAuthc: RoleCredentials; + let internalReqHeader: InternalRequestHeader; /* * Helper function to decorate with common fields needed in the API call @@ -73,6 +78,11 @@ export default function ({ getService }: FtrProviderContext) { // see kibanaReportCompletion config this.timeout(12 * 60 * 1000); + before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + internalReqHeader = svlCommonApi.getInternalRequestHeader(); + }); + beforeEach(async () => { await kibanaServer.uiSettings.update({ 'csv:quoteValues': true, @@ -80,6 +90,10 @@ export default function ({ getService }: FtrProviderContext) { }); }); + after(async () => { + await svlUserManager.invalidateApiKeyForRole(roleAuthc); + }); + describe('exported CSV', () => { before(async () => { await esArchiver.load(archives.ecommerce.data); @@ -87,7 +101,7 @@ export default function ({ getService }: FtrProviderContext) { }); after(async () => { - await reportingAPI.deleteAllReports(); + await reportingAPI.deleteAllReports(roleAuthc, internalReqHeader); await esArchiver.unload(archives.ecommerce.data); await kibanaServer.importExport.unload(archives.ecommerce.savedObjects); }); @@ -155,10 +169,16 @@ export default function ({ getService }: FtrProviderContext) { }, title: 'Ecommerce Data', version: '8.14.0', - }) + }), + roleAuthc, + internalReqHeader + ); + await reportingAPI.waitForJobToFinish(res.path, roleAuthc, internalReqHeader); + const csvFile = await reportingAPI.getCompletedJobOutput( + res.path, + roleAuthc, + internalReqHeader ); - await reportingAPI.waitForJobToFinish(res.path); - const csvFile = await reportingAPI.getCompletedJobOutput(res.path); expect((csvFile as string).length).to.be(124183); expectSnapshot(createPartialCsv(csvFile)).toMatch(); }); @@ -192,10 +212,12 @@ export default function ({ getService }: FtrProviderContext) { }, title: 'Untitled discover search', version: '8.14.0', - }) + }), + roleAuthc, + internalReqHeader ); - await reportingAPI.waitForJobToFinish(res.path); - return reportingAPI.getCompletedJobOutput(res.path); + await reportingAPI.waitForJobToFinish(res.path, roleAuthc, internalReqHeader); + return reportingAPI.getCompletedJobOutput(res.path, roleAuthc, internalReqHeader); } it('includes an unmapped field to the report', async () => { @@ -337,10 +359,16 @@ export default function ({ getService }: FtrProviderContext) { }, }, }, - }) + }), + roleAuthc, + internalReqHeader + ); + await reportingAPI.waitForJobToFinish(res.path, roleAuthc, internalReqHeader); + const csvFile = await reportingAPI.getCompletedJobOutput( + res.path, + roleAuthc, + internalReqHeader ); - await reportingAPI.waitForJobToFinish(res.path); - const csvFile = await reportingAPI.getCompletedJobOutput(res.path); expect((csvFile as string).length).to.be(1270683); expectSnapshot(createPartialCsv(csvFile)).toMatch(); }); @@ -383,10 +411,16 @@ export default function ({ getService }: FtrProviderContext) { }, }, }, - }) + }), + roleAuthc, + internalReqHeader + ); + await reportingAPI.waitForJobToFinish(res.path, roleAuthc, internalReqHeader); + const csvFile = await reportingAPI.getCompletedJobOutput( + res.path, + roleAuthc, + internalReqHeader ); - await reportingAPI.waitForJobToFinish(res.path); - const csvFile = await reportingAPI.getCompletedJobOutput(res.path); expect((csvFile as string).length).to.be(918298); expectSnapshot(createPartialCsv(csvFile)).toMatch(); }); @@ -435,10 +469,16 @@ export default function ({ getService }: FtrProviderContext) { sort: [{ '@timestamp': 'desc' as SortDirection }], }, columns: ['@timestamp', 'clientip', 'extension'], - }) + }), + roleAuthc, + internalReqHeader + ); + await reportingAPI.waitForJobToFinish(res.path, roleAuthc, internalReqHeader); + const csvFile = await reportingAPI.getCompletedJobOutput( + res.path, + roleAuthc, + internalReqHeader ); - await reportingAPI.waitForJobToFinish(res.path); - const csvFile = await reportingAPI.getCompletedJobOutput(res.path); expect((csvFile as string).length).to.be(3020); expectSnapshot(createPartialCsv(csvFile)).toMatch(); }); @@ -475,10 +515,16 @@ export default function ({ getService }: FtrProviderContext) { sort: [{ '@timestamp': 'desc' as SortDirection }], }, columns: ['@timestamp', 'clientip', 'extension'], - }) + }), + roleAuthc, + internalReqHeader + ); + await reportingAPI.waitForJobToFinish(res.path, roleAuthc, internalReqHeader); + const csvFile = await reportingAPI.getCompletedJobOutput( + res.path, + roleAuthc, + internalReqHeader ); - await reportingAPI.waitForJobToFinish(res.path); - const csvFile = await reportingAPI.getCompletedJobOutput(res.path); expect((csvFile as string).length).to.be(3020); expectSnapshot(createPartialCsv(csvFile)).toMatch(); }); @@ -509,10 +555,16 @@ export default function ({ getService }: FtrProviderContext) { filter: [], }, columns: ['date', 'message'], - }) + }), + roleAuthc, + internalReqHeader + ); + await reportingAPI.waitForJobToFinish(res.path, roleAuthc, internalReqHeader); + const csvFile = await reportingAPI.getCompletedJobOutput( + res.path, + roleAuthc, + internalReqHeader ); - await reportingAPI.waitForJobToFinish(res.path); - const csvFile = await reportingAPI.getCompletedJobOutput(res.path); expect((csvFile as string).length).to.be(103); expectSnapshot(createPartialCsv(csvFile)).toMatch(); }); @@ -532,10 +584,16 @@ export default function ({ getService }: FtrProviderContext) { filter: [], }, columns: ['date', 'message'], - }) + }), + roleAuthc, + internalReqHeader + ); + await reportingAPI.waitForJobToFinish(res.path, roleAuthc, internalReqHeader); + const csvFile = await reportingAPI.getCompletedJobOutput( + res.path, + roleAuthc, + internalReqHeader ); - await reportingAPI.waitForJobToFinish(res.path); - const csvFile = await reportingAPI.getCompletedJobOutput(res.path); expect((csvFile as string).length).to.be(103); expectSnapshot(createPartialCsv(csvFile)).toMatch(); }); @@ -569,10 +627,16 @@ export default function ({ getService }: FtrProviderContext) { filter: [], }, columns: ['date', 'message', '_id', '_index'], - }) + }), + roleAuthc, + internalReqHeader + ); + await reportingAPI.waitForJobToFinish(res.path, roleAuthc, internalReqHeader); + const csvFile = await reportingAPI.getCompletedJobOutput( + res.path, + roleAuthc, + internalReqHeader ); - await reportingAPI.waitForJobToFinish(res.path); - const csvFile = await reportingAPI.getCompletedJobOutput(res.path); expect((csvFile as string).length).to.be(134); expectSnapshot(createPartialCsv(csvFile)).toMatch(); }); @@ -595,10 +659,16 @@ export default function ({ getService }: FtrProviderContext) { ] as unknown as Filter[], }, columns: ['name', 'power'], - }) + }), + roleAuthc, + internalReqHeader + ); + await reportingAPI.waitForJobToFinish(res.path, roleAuthc, internalReqHeader); + const csvFile = await reportingAPI.getCompletedJobOutput( + res.path, + roleAuthc, + internalReqHeader ); - await reportingAPI.waitForJobToFinish(res.path); - const csvFile = await reportingAPI.getCompletedJobOutput(res.path); expect((csvFile as string).length).to.be(274); expectSnapshot(createPartialCsv(csvFile)).toMatch(); }); @@ -673,10 +743,16 @@ export default function ({ getService }: FtrProviderContext) { }, }, columns: [], - }) + }), + roleAuthc, + internalReqHeader + ); + await reportingAPI.waitForJobToFinish(res.path, roleAuthc, internalReqHeader); + const csvFile = await reportingAPI.getCompletedJobOutput( + res.path, + roleAuthc, + internalReqHeader ); - await reportingAPI.waitForJobToFinish(res.path); - const csvFile = await reportingAPI.getCompletedJobOutput(res.path); expect((csvFile as string).length).to.be(356); expectSnapshot(createPartialCsv(csvFile)).toMatch(); }); @@ -733,10 +809,16 @@ export default function ({ getService }: FtrProviderContext) { }, }, }, - }) + }), + roleAuthc, + internalReqHeader + ); + await reportingAPI.waitForJobToFinish(res.path, roleAuthc, internalReqHeader); + const csvFile = await reportingAPI.getCompletedJobOutput( + res.path, + roleAuthc, + internalReqHeader ); - await reportingAPI.waitForJobToFinish(res.path); - const csvFile = await reportingAPI.getCompletedJobOutput(res.path); expect((csvFile as string).length).to.be(4845684); expectSnapshot(createPartialCsv(csvFile)).toMatch(); }); diff --git a/x-pack/test_serverless/functional/test_suites/common/reporting/management.ts b/x-pack/test_serverless/functional/test_suites/common/reporting/management.ts index 6d23ef5512b764..be4c365263dbdb 100644 --- a/x-pack/test_serverless/functional/test_suites/common/reporting/management.ts +++ b/x-pack/test_serverless/functional/test_suites/common/reporting/management.ts @@ -11,6 +11,7 @@ import { JobParamsCsvFromSavedObject, } from '@kbn/reporting-export-types-csv-common'; import { FtrProviderContext } from '../../../ftr_provider_context'; +import { InternalRequestHeader, RoleCredentials } from '../../../../shared/services'; export default ({ getPageObjects, getService }: FtrProviderContext) => { const kibanaServer = getService('kibanaServer'); @@ -20,6 +21,10 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const PageObjects = getPageObjects(['common', 'svlCommonPage', 'header']); const reportingAPI = getService('svlReportingApi'); const config = getService('config'); + const svlCommonApi = getService('svlCommonApi'); + const svlUserManager = getService('svlUserManager'); + let roleAuthc: RoleCredentials; + let internalReqHeader: InternalRequestHeader; const navigateToReportingManagement = async () => { log.debug(`navigating to reporting management app`); @@ -55,19 +60,27 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => { const TEST_PASSWORD = config.get('servers.kibana.password'); before('initialize saved object archive', async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + internalReqHeader = svlCommonApi.getInternalRequestHeader(); // add test saved search object await kibanaServer.importExport.load(savedObjectsArchive); }); after('clean up archives', async () => { await kibanaServer.importExport.unload(savedObjectsArchive); + await svlUserManager.invalidateApiKeyForRole(roleAuthc); }); // Cant auth into the route as it's structured currently xit(`user sees a job they've created`, async () => { const { job: { id: jobId }, - } = await reportingAPI.createReportJobInternal(CSV_REPORT_TYPE_V2, job); + } = await reportingAPI.createReportJobInternal( + CSV_REPORT_TYPE_V2, + job, + roleAuthc, + internalReqHeader + ); await navigateToReportingManagement(); await testSubjects.existOrFail(`viewReportingLink-${jobId}`); diff --git a/x-pack/test_serverless/shared/services/svl_reporting.ts b/x-pack/test_serverless/shared/services/svl_reporting.ts index 4a1a2535aeced6..f3cf4065c31f15 100644 --- a/x-pack/test_serverless/shared/services/svl_reporting.ts +++ b/x-pack/test_serverless/shared/services/svl_reporting.ts @@ -5,29 +5,26 @@ * 2.0. */ -import { X_ELASTIC_INTERNAL_ORIGIN_REQUEST } from '@kbn/core-http-common'; import expect from '@kbn/expect'; import { INTERNAL_ROUTES } from '@kbn/reporting-common'; import type { ReportingJobResponse } from '@kbn/reporting-plugin/server/types'; import { REPORTING_DATA_STREAM_WILDCARD_WITH_LEGACY } from '@kbn/reporting-server'; import rison from '@kbn/rison'; import { FtrProviderContext } from '../../functional/ftr_provider_context'; +import { RoleCredentials } from './svl_user_manager'; +import { InternalRequestHeader } from './svl_common_api'; const API_HEADER: [string, string] = ['kbn-xsrf', 'reporting']; -const INTERNAL_HEADER: [string, string] = [X_ELASTIC_INTERNAL_ORIGIN_REQUEST, 'Kibana']; /** * Services to create roles and users for security testing */ export function SvlReportingServiceProvider({ getService }: FtrProviderContext) { const log = getService('log'); - const supertest = getService('supertestWithoutAuth'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); const retry = getService('retry'); const config = getService('config'); - const REPORTING_USER_USERNAME = config.get('servers.kibana.username'); - const REPORTING_USER_PASSWORD = config.get('servers.kibana.password'); - return { /** * Use the internal API to create any kind of report job @@ -35,17 +32,16 @@ export function SvlReportingServiceProvider({ getService }: FtrProviderContext) async createReportJobInternal( jobType: string, job: object, - username: string = REPORTING_USER_USERNAME, - password: string = REPORTING_USER_PASSWORD + roleAuthc: RoleCredentials, + internalReqHeader: InternalRequestHeader ) { const requestPath = `${INTERNAL_ROUTES.GENERATE_PREFIX}/${jobType}`; log.debug(`POST request to ${requestPath}`); - const { status, body } = await supertest + const { status, body } = await supertestWithoutAuth .post(requestPath) - .auth(username, password) - .set(...API_HEADER) - .set(...INTERNAL_HEADER) + .set(internalReqHeader) + .set(roleAuthc.apiKeyHeader) .send({ jobParams: rison.encode(job) }); expect(status).to.be(200); @@ -61,20 +57,20 @@ export function SvlReportingServiceProvider({ getService }: FtrProviderContext) */ async waitForJobToFinish( downloadReportPath: string, - username = REPORTING_USER_USERNAME, - password = REPORTING_USER_PASSWORD, + roleAuthc: RoleCredentials, + internalReqHeader: InternalRequestHeader, options?: { timeout?: number } ) { await retry.waitForWithTimeout( `job ${downloadReportPath} finished`, options?.timeout ?? config.get('timeouts.kibanaReportCompletion'), async () => { - const response = await supertest + const response = await supertestWithoutAuth .get(`${downloadReportPath}?elasticInternalOrigin=true`) - .auth(username, password) .responseType('blob') .set(...API_HEADER) - .set(...INTERNAL_HEADER); + .set(internalReqHeader) + .set(roleAuthc.apiKeyHeader); if (response.status === 500) { throw new Error(`Report at path ${downloadReportPath} has failed`); @@ -106,21 +102,24 @@ export function SvlReportingServiceProvider({ getService }: FtrProviderContext) */ async getCompletedJobOutput( downloadReportPath: string, - username = REPORTING_USER_USERNAME, - password = REPORTING_USER_PASSWORD + roleAuthc: RoleCredentials, + internalReqHeader: InternalRequestHeader ) { - const response = await supertest + const response = await supertestWithoutAuth .get(`${downloadReportPath}?elasticInternalOrigin=true`) - .auth(username, password); + .set(internalReqHeader) + .set(roleAuthc.apiKeyHeader); return response.text as unknown; }, - async deleteAllReports() { + async deleteAllReports(roleAuthc: RoleCredentials, internalReqHeader: InternalRequestHeader) { log.debug('ReportingAPI.deleteAllReports'); // ignores 409 errs and keeps retrying await retry.tryForTime(5000, async () => { - await supertest + await supertestWithoutAuth .post(`/${REPORTING_DATA_STREAM_WILDCARD_WITH_LEGACY}/_delete_by_query`) + .set(internalReqHeader) + .set(roleAuthc.apiKeyHeader) .send({ query: { match_all: {} } }); }); },