From 95e7451149ddc93b435002b93a91d49a7e1de747 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Thu, 12 Sep 2024 16:02:34 +0200 Subject: [PATCH 01/18] do not return admin cookie with api_key --- .../services/saml_auth/saml_auth_provider.ts | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/kbn-ftr-common-functional-services/services/saml_auth/saml_auth_provider.ts b/packages/kbn-ftr-common-functional-services/services/saml_auth/saml_auth_provider.ts index 9a8db8260923..e624d4ab921a 100644 --- a/packages/kbn-ftr-common-functional-services/services/saml_auth/saml_auth_provider.ts +++ b/packages/kbn-ftr-common-functional-services/services/saml_auth/saml_auth_provider.ts @@ -18,7 +18,6 @@ import { InternalRequestHeader } from './default_request_headers'; export interface RoleCredentials { apiKey: { id: string; name: string }; apiKeyHeader: { Authorization: string }; - cookieHeader: { Cookie: string }; } export function SamlAuthProvider({ getService }: FtrProviderContext) { @@ -110,23 +109,21 @@ export function SamlAuthProvider({ getService }: FtrProviderContext) { const apiKeyHeader = { Authorization: 'ApiKey ' + apiKey.encoded }; log.debug(`Created api key for role: [${role}]`); - return { apiKey, apiKeyHeader, cookieHeader: adminCookieHeader }; + return { apiKey, apiKeyHeader }; }, async invalidateM2mApiKeyWithRoleScope(roleCredentials: RoleCredentials) { + // Get admin credentials in order to invalidate the API key + const adminCookieHeader = await this.getM2MApiCredentialsWithRoleScope('admin'); + const requestBody = { - apiKeys: [ - { - id: roleCredentials.apiKey.id, - name: roleCredentials.apiKey.name, - }, - ], + apiKeys: [roleCredentials.apiKey], isAdmin: true, }; const { status } = await supertestWithoutAuth .post('/internal/security/api_key/invalidate') .set(INTERNAL_REQUEST_HEADERS) - .set(roleCredentials.cookieHeader) + .set(adminCookieHeader) .send(requestBody); expect(status).to.be(200); From 2bcec5c54e26cad5889a5efddec3774927dda33d Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Thu, 12 Sep 2024 17:12:24 +0200 Subject: [PATCH 02/18] update SupertestWithRoleScope to support both API key and cookie header --- .../services/role_scoped_supertest.ts | 45 ++++++++++++++----- 1 file changed, 33 insertions(+), 12 deletions(-) diff --git a/x-pack/test/api_integration/deployment_agnostic/services/role_scoped_supertest.ts b/x-pack/test/api_integration/deployment_agnostic/services/role_scoped_supertest.ts index 2661fc7682ad..5927b0185c37 100644 --- a/x-pack/test/api_integration/deployment_agnostic/services/role_scoped_supertest.ts +++ b/x-pack/test/api_integration/deployment_agnostic/services/role_scoped_supertest.ts @@ -14,44 +14,54 @@ import { Test } from 'supertest'; import { DeploymentAgnosticFtrProviderContext } from '../ftr_provider_context'; export interface RequestHeadersOptions { + useCookieHeader?: boolean; withInternalHeaders?: boolean; withCommonHeaders?: boolean; withCustomHeaders?: Record; } export class SupertestWithRoleScope { - private roleAuthc: RoleCredentials | null; + private authValue: RoleCredentials | { Cookie: string } | null; private readonly supertestWithoutAuth: SupertestWithoutAuthProviderType; private samlAuth: SamlAuthProviderType; private readonly options: RequestHeadersOptions; constructor( - roleAuthc: RoleCredentials, + authValue: RoleCredentials | { Cookie: string } | null, supertestWithoutAuth: SupertestWithoutAuthProviderType, samlAuth: SamlAuthProviderType, options: RequestHeadersOptions ) { - this.roleAuthc = roleAuthc; + this.authValue = authValue; this.supertestWithoutAuth = supertestWithoutAuth; this.samlAuth = samlAuth; this.options = options; } async destroy() { - if (this.roleAuthc) { - await this.samlAuth.invalidateM2mApiKeyWithRoleScope(this.roleAuthc); - this.roleAuthc = null; + if (this.authValue && 'apiKeyHeader' in this.authValue) { + await this.samlAuth.invalidateM2mApiKeyWithRoleScope(this.authValue); + this.authValue = null; } } private addHeaders(agent: Test): Test { - const { withInternalHeaders, withCommonHeaders, withCustomHeaders } = this.options; + const { useCookieHeader, withInternalHeaders, withCommonHeaders, withCustomHeaders } = + this.options; - if (!this.roleAuthc) { - throw new Error('The instance has already been destroyed.'); + if (useCookieHeader) { + if (!this.authValue || !('Cookie' in this.authValue)) { + throw new Error('The instance has already been destroyed or cookieHeader is missing.'); + } + // set cookie header + void agent.set(this.authValue); + } else { + if (!this.authValue || !('apiKeyHeader' in this.authValue)) { + throw new Error('The instance has already been destroyed or roleAuthc is missing.'); + } + // set API key header + void agent.set(this.authValue.apiKeyHeader); } - // set role-based API key by default - void agent.set(this.roleAuthc.apiKeyHeader); if (withInternalHeaders) { void agent.set(this.samlAuth.getInternalRequestHeader()); @@ -69,7 +79,7 @@ export class SupertestWithRoleScope { } private request(method: 'post' | 'get' | 'put' | 'delete', url: string): Test { - if (!this.roleAuthc) { + if (!this.authValue) { throw new Error('Instance has been destroyed and cannot be used for making requests.'); } const agent = this.supertestWithoutAuth[method](url); @@ -101,6 +111,9 @@ export class SupertestWithRoleScope { * * Use this service to easily test API endpoints with role-specific authorization and * custom headers, both in serverless and stateful environments. + * + * Pass '{ useCookieHeader: true }' to use Cookie header for authentication instead of API key. + * It is the correct way to perform HTTP requests for internal end-points. */ export function RoleScopedSupertestProvider({ getService }: DeploymentAgnosticFtrProviderContext) { const supertestWithoutAuth = getService('supertestWithoutAuth'); @@ -110,10 +123,18 @@ export function RoleScopedSupertestProvider({ getService }: DeploymentAgnosticFt async getSupertestWithRoleScope( role: string, options: RequestHeadersOptions = { + useCookieHeader: false, withCommonHeaders: false, withInternalHeaders: false, } ) { + // if 'useCookieHeader' set to 'true', HTTP requests will be called with cookie Header (like in browser) + if (options.useCookieHeader) { + const cookieHeader = await samlAuth.getM2MApiCredentialsWithRoleScope(role); + return new SupertestWithRoleScope(cookieHeader, supertestWithoutAuth, samlAuth, options); + } + + // HTTP requests will be called with API key in header by default const roleAuthc = await samlAuth.createM2mApiKeyWithRoleScope(role); return new SupertestWithRoleScope(roleAuthc, supertestWithoutAuth, samlAuth, options); }, From 5d5e449eb49538d7677b4b912e9e274ca50030f4 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Thu, 12 Sep 2024 18:42:55 +0200 Subject: [PATCH 03/18] revert requestBody for API key invalidation --- .../services/saml_auth/saml_auth_provider.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/kbn-ftr-common-functional-services/services/saml_auth/saml_auth_provider.ts b/packages/kbn-ftr-common-functional-services/services/saml_auth/saml_auth_provider.ts index e624d4ab921a..a052c5f2f1c5 100644 --- a/packages/kbn-ftr-common-functional-services/services/saml_auth/saml_auth_provider.ts +++ b/packages/kbn-ftr-common-functional-services/services/saml_auth/saml_auth_provider.ts @@ -116,7 +116,12 @@ export function SamlAuthProvider({ getService }: FtrProviderContext) { const adminCookieHeader = await this.getM2MApiCredentialsWithRoleScope('admin'); const requestBody = { - apiKeys: [roleCredentials.apiKey], + apiKeys: [ + { + id: roleCredentials.apiKey.id, + name: roleCredentials.apiKey.name, + }, + ], isAdmin: true, }; From 21a8fa09d94ce7286c53c9d14a355d48c8537814 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Fri, 13 Sep 2024 11:17:54 +0200 Subject: [PATCH 04/18] fix types in tests --- .../apis/cloud_security_posture/helper.ts | 7 +-- .../common/platform_security/api_keys.ts | 63 +++++++++---------- 2 files changed, 31 insertions(+), 39 deletions(-) diff --git a/x-pack/test/api_integration/apis/cloud_security_posture/helper.ts b/x-pack/test/api_integration/apis/cloud_security_posture/helper.ts index 7c21e6df09f8..9ab91cf0d60c 100644 --- a/x-pack/test/api_integration/apis/cloud_security_posture/helper.ts +++ b/x-pack/test/api_integration/apis/cloud_security_posture/helper.ts @@ -12,12 +12,7 @@ import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; import type { IndexDetails } from '@kbn/cloud-security-posture-common'; import { CLOUD_SECURITY_PLUGIN_VERSION } from '@kbn/cloud-security-posture-plugin/common/constants'; import { SecurityService } from '@kbn/ftr-common-functional-ui-services'; - -export interface RoleCredentials { - apiKey: { id: string; name: string }; - apiKeyHeader: { Authorization: string }; - cookieHeader: { Cookie: string }; -} +import { RoleCredentials } from '@kbn/ftr-common-functional-services'; export const deleteIndex = async (es: Client, indexToBeDeleted: string[]) => { return Promise.all([ 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 694428bc57d9..728c7c08ebab 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 @@ -6,30 +6,27 @@ */ import expect from 'expect'; +import { CookieCredentials } from '@kbn/ftr-common-functional-services'; import { FtrProviderContext } from '../../../ftr_provider_context'; -import { RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { let roleMapping: { id: string; name: string; api_key: string; encoded: string }; - const supertest = getService('supertest'); - const svlCommonApi = getService('svlCommonApi'); - const svlUserManager = getService('svlUserManager'); + const samlAuth = getService('samlAuth'); const supertestWithoutAuth = getService('supertestWithoutAuth'); - let roleAuthc: RoleCredentials; + let cookieHeader: CookieCredentials; + describe('security/api_keys', function () { before(async () => { - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin'); - }); - after(async () => { - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); + cookieHeader = await samlAuth.getM2MApiCredentialsWithRoleScope('admin'); }); + describe('route access', () => { describe('internal', () => { before(async () => { const { body, status } = await supertestWithoutAuth .post('/internal/security/api_key') - .set(roleAuthc.cookieHeader) - .set(svlCommonApi.getInternalRequestHeader()) + .set(cookieHeader) + .set(samlAuth.getInternalRequestHeader()) .send({ name: 'test', metadata: {}, @@ -42,14 +39,14 @@ export default function ({ getService }: FtrProviderContext) { after(async function invalidateAll() { const { body, status } = await supertestWithoutAuth .get('/internal/security/api_key?isAdmin=true') - .set(roleAuthc.cookieHeader) - .set(svlCommonApi.getInternalRequestHeader()); + .set(cookieHeader) + .set(samlAuth.getInternalRequestHeader()); if (status === 200) { await supertestWithoutAuth .post('/internal/security/api_key/invalidate') - .set(roleAuthc.cookieHeader) - .set(svlCommonApi.getInternalRequestHeader()) + .set(cookieHeader) + .set(samlAuth.getInternalRequestHeader()) .send({ apiKeys: body?.apiKeys, isAdmin: true, @@ -68,7 +65,7 @@ export default function ({ getService }: FtrProviderContext) { ({ body, status } = await supertestWithoutAuth .post('/internal/security/api_key') - .set(svlCommonApi.getCommonRequestHeader()) + .set(samlAuth.getCommonRequestHeader()) .send(requestBody)); // expect a rejection because we're not using the internal header expect(body).toEqual({ @@ -80,8 +77,8 @@ export default function ({ getService }: FtrProviderContext) { ({ body, status } = await supertestWithoutAuth .post('/internal/security/api_key') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.cookieHeader) + .set(samlAuth.getInternalRequestHeader()) + .set(cookieHeader) .send(requestBody)); // expect success because we're using the internal header expect(body).toEqual(expect.objectContaining({ name: 'create_test' })); @@ -99,8 +96,8 @@ export default function ({ getService }: FtrProviderContext) { ({ body, status } = await supertestWithoutAuth .put('/internal/security/api_key') - .set(svlCommonApi.getCommonRequestHeader()) - .set(roleAuthc.cookieHeader) + .set(samlAuth.getCommonRequestHeader()) + .set(cookieHeader) .send(requestBody)); // expect a rejection because we're not using the internal header expect(body).toEqual({ @@ -114,8 +111,8 @@ export default function ({ getService }: FtrProviderContext) { ({ body, status } = await supertestWithoutAuth .put('/internal/security/api_key') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.cookieHeader) + .set(samlAuth.getInternalRequestHeader()) + .set(cookieHeader) .send(requestBody)); // expect success because we're using the internal header expect(body).toEqual(expect.objectContaining({ updated: true })); @@ -126,10 +123,10 @@ export default function ({ getService }: FtrProviderContext) { let body: unknown; let status: number; - ({ body, status } = await supertest + ({ body, status } = await supertestWithoutAuth .get('/internal/security/api_key/_enabled') - .set(svlCommonApi.getCommonRequestHeader()) - .set(roleAuthc.cookieHeader)); + .set(samlAuth.getCommonRequestHeader()) + .set(cookieHeader)); // expect a rejection because we're not using the internal header expect(body).toEqual({ statusCode: 400, @@ -142,8 +139,8 @@ export default function ({ getService }: FtrProviderContext) { ({ body, status } = await supertestWithoutAuth .get('/internal/security/api_key/_enabled') - .set(roleAuthc.cookieHeader) - .set(svlCommonApi.getInternalRequestHeader())); + .set(cookieHeader) + .set(samlAuth.getInternalRequestHeader())); // expect success because we're using the internal header expect(body).toEqual({ apiKeysEnabled: true }); expect(status).toBe(200); @@ -164,8 +161,8 @@ export default function ({ getService }: FtrProviderContext) { ({ body, status } = await supertestWithoutAuth .post('/internal/security/api_key/invalidate') - .set(svlCommonApi.getCommonRequestHeader()) - .set(roleAuthc.cookieHeader) + .set(samlAuth.getCommonRequestHeader()) + .set(cookieHeader) .send(requestBody)); // expect a rejection because we're not using the internal header expect(body).toEqual({ @@ -179,8 +176,8 @@ export default function ({ getService }: FtrProviderContext) { ({ body, status } = await supertestWithoutAuth .post('/internal/security/api_key/invalidate') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.cookieHeader) + .set(samlAuth.getInternalRequestHeader()) + .set(cookieHeader) .send(requestBody)); // expect success because we're using the internal header expect(body).toEqual({ @@ -207,8 +204,8 @@ export default function ({ getService }: FtrProviderContext) { const { body } = await supertestWithoutAuth .post('/internal/security/api_key/_query') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.cookieHeader) + .set(samlAuth.getInternalRequestHeader()) + .set(cookieHeader) .send(requestBody) .expect(200); From 1fd3ead49e5ee798c94b77dcca9083e1c2b31797 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Fri, 13 Sep 2024 11:19:32 +0200 Subject: [PATCH 05/18] update samlUath service --- .../services/saml_auth/saml_auth_provider.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/kbn-ftr-common-functional-services/services/saml_auth/saml_auth_provider.ts b/packages/kbn-ftr-common-functional-services/services/saml_auth/saml_auth_provider.ts index e624d4ab921a..899cfd78db1f 100644 --- a/packages/kbn-ftr-common-functional-services/services/saml_auth/saml_auth_provider.ts +++ b/packages/kbn-ftr-common-functional-services/services/saml_auth/saml_auth_provider.ts @@ -20,6 +20,13 @@ export interface RoleCredentials { apiKeyHeader: { Authorization: string }; } +export interface CookieCredentials { + Cookie: string; + // supertest.set() expects an object that matches IncomingHttpHeaders type, that needs to accept arbitrary key-value pairs as headers + // We extende the interface with an index signature to resolve this. + [header: string]: string; +} + export function SamlAuthProvider({ getService }: FtrProviderContext) { const config = getService('config'); const log = getService('log'); @@ -59,7 +66,7 @@ export function SamlAuthProvider({ getService }: FtrProviderContext) { async getInteractiveUserSessionCookieWithRoleScope(role: string) { return sessionManager.getInteractiveUserSessionCookieWithRoleScope(role); }, - async getM2MApiCredentialsWithRoleScope(role: string) { + async getM2MApiCredentialsWithRoleScope(role: string): Promise { return sessionManager.getApiCredentialsForRole(role); }, async getEmail(role: string) { From a7874f68c160b27fc0e3b8b3cdd99555fa819561 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Fri, 13 Sep 2024 11:34:50 +0200 Subject: [PATCH 06/18] fix type export --- .../kbn-ftr-common-functional-services/index.ts | 6 +++++- .../services/saml_auth/index.ts | 2 +- .../services/role_scoped_supertest.ts | 13 +++++++++---- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/packages/kbn-ftr-common-functional-services/index.ts b/packages/kbn-ftr-common-functional-services/index.ts index e156949f0daf..ac5b33edce1a 100644 --- a/packages/kbn-ftr-common-functional-services/index.ts +++ b/packages/kbn-ftr-common-functional-services/index.ts @@ -26,7 +26,11 @@ export type Es = ProvidedType; import { SupertestWithoutAuthProvider } from './services/supertest_without_auth'; export type SupertestWithoutAuthProviderType = ProvidedType; -export type { InternalRequestHeader, RoleCredentials } from './services/saml_auth'; +export type { + InternalRequestHeader, + RoleCredentials, + CookieCredentials, +} from './services/saml_auth'; import { SamlAuthProvider } from './services/saml_auth/saml_auth_provider'; export type SamlAuthProviderType = ProvidedType; diff --git a/packages/kbn-ftr-common-functional-services/services/saml_auth/index.ts b/packages/kbn-ftr-common-functional-services/services/saml_auth/index.ts index d8227b797e24..f379a3dc761e 100644 --- a/packages/kbn-ftr-common-functional-services/services/saml_auth/index.ts +++ b/packages/kbn-ftr-common-functional-services/services/saml_auth/index.ts @@ -8,5 +8,5 @@ */ export { SamlAuthProvider } from './saml_auth_provider'; -export type { RoleCredentials } from './saml_auth_provider'; +export type { RoleCredentials, CookieCredentials } from './saml_auth_provider'; export type { InternalRequestHeader } from './default_request_headers'; diff --git a/x-pack/test/api_integration/deployment_agnostic/services/role_scoped_supertest.ts b/x-pack/test/api_integration/deployment_agnostic/services/role_scoped_supertest.ts index 5927b0185c37..8f6ee6d53f07 100644 --- a/x-pack/test/api_integration/deployment_agnostic/services/role_scoped_supertest.ts +++ b/x-pack/test/api_integration/deployment_agnostic/services/role_scoped_supertest.ts @@ -7,6 +7,7 @@ import { RoleCredentials, + CookieCredentials, SupertestWithoutAuthProviderType, SamlAuthProviderType, } from '@kbn/ftr-common-functional-services'; @@ -21,13 +22,13 @@ export interface RequestHeadersOptions { } export class SupertestWithRoleScope { - private authValue: RoleCredentials | { Cookie: string } | null; + private authValue: RoleCredentials | CookieCredentials | null; private readonly supertestWithoutAuth: SupertestWithoutAuthProviderType; private samlAuth: SamlAuthProviderType; private readonly options: RequestHeadersOptions; constructor( - authValue: RoleCredentials | { Cookie: string } | null, + authValue: RoleCredentials | CookieCredentials | null, supertestWithoutAuth: SupertestWithoutAuthProviderType, samlAuth: SamlAuthProviderType, options: RequestHeadersOptions @@ -38,8 +39,12 @@ export class SupertestWithRoleScope { this.options = options; } + private isRoleCredentials(value: any): value is RoleCredentials { + return value && typeof value === 'object' && 'apiKey' in value && 'apiKeyHeader' in value; + } + async destroy() { - if (this.authValue && 'apiKeyHeader' in this.authValue) { + if (this.isRoleCredentials(this.authValue)) { await this.samlAuth.invalidateM2mApiKeyWithRoleScope(this.authValue); this.authValue = null; } @@ -56,7 +61,7 @@ export class SupertestWithRoleScope { // set cookie header void agent.set(this.authValue); } else { - if (!this.authValue || !('apiKeyHeader' in this.authValue)) { + if (!this.authValue || !this.isRoleCredentials(this.authValue)) { throw new Error('The instance has already been destroyed or roleAuthc is missing.'); } // set API key header From ae1c51659af796873ff0abca088866f072f8fc22 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Fri, 13 Sep 2024 11:36:03 +0200 Subject: [PATCH 07/18] fix typo --- .../services/saml_auth/saml_auth_provider.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/kbn-ftr-common-functional-services/services/saml_auth/saml_auth_provider.ts b/packages/kbn-ftr-common-functional-services/services/saml_auth/saml_auth_provider.ts index 28aebe5dc218..51a0ed992b9e 100644 --- a/packages/kbn-ftr-common-functional-services/services/saml_auth/saml_auth_provider.ts +++ b/packages/kbn-ftr-common-functional-services/services/saml_auth/saml_auth_provider.ts @@ -23,7 +23,7 @@ export interface RoleCredentials { export interface CookieCredentials { Cookie: string; // supertest.set() expects an object that matches IncomingHttpHeaders type, that needs to accept arbitrary key-value pairs as headers - // We extende the interface with an index signature to resolve this. + // We extend the interface with an index signature to resolve this. [header: string]: string; } From 3dddbb71e8b03b1b817a9385a78c0c7f7ba1be4b Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Fri, 13 Sep 2024 15:01:48 +0200 Subject: [PATCH 08/18] migrate tests to use cookieHeader --- .../test_suites/common/core/ui_settings.ts | 76 ++++++---------- .../create_enrich_policies.ts | 34 ++++---- .../common/index_management/indices.ts | 36 ++++---- .../common/kql_telemetry/kql_telemetry.ts | 87 +++++-------------- .../management/multiple_spaces_enabled.ts | 51 ++++++----- .../common/scripts_tests/languages.ts | 33 ++++--- .../test_suites/common/search_oss/bsearch.ts | 86 ++++++++---------- .../test_suites/common/search_oss/search.ts | 75 +++++----------- .../common/telemetry/telemetry_config.ts | 65 ++++++-------- 9 files changed, 207 insertions(+), 336 deletions(-) diff --git a/x-pack/test_serverless/api_integration/test_suites/common/core/ui_settings.ts b/x-pack/test_serverless/api_integration/test_suites/common/core/ui_settings.ts index e6c2274f83b1..228ba1f3ad28 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/core/ui_settings.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/core/ui_settings.ts @@ -6,8 +6,8 @@ */ import expect from '@kbn/expect'; +import { SupertestWithRoleScopeType } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services'; import { FtrProviderContext } from '../../../ftr_provider_context'; -import { RoleCredentials } from '../../../../shared/services'; // To test setting validations we are using the existing 'defaultColumns' setting that is available in all serverless projects // (See list of common serverless settings in /packages/serverless/settings/common/index.ts) @@ -18,34 +18,32 @@ const DEFAULT_COLUMNS_SETTING = 'defaultColumns'; const TEST_SETTING = 'testSetting'; export default function ({ getService }: FtrProviderContext) { - const svlCommonApi = getService('svlCommonApi'); - const svlUserManager = getService('svlUserManager'); - let roleAuthc: RoleCredentials; - const supertestWithoutAuth = getService('supertestWithoutAuth'); + const roleScopedSupertest = getService('roleScopedSupertest'); + let supertestAdminWithCookieCredentials: SupertestWithRoleScopeType; describe('ui settings service', () => { before(async () => { - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin'); + supertestAdminWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope( + 'admin', + { + useCookieHeader: true, + withInternalHeaders: true, + } + ); + // Creating a test setting - await supertestWithoutAuth + await supertestAdminWithCookieCredentials .post(`/internal/kibana/settings/${TEST_SETTING}`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send({ value: 100 }) .expect(200); }); - after(async () => { - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); - }); // We don't test the public routes as they are not available in serverless describe('internal routes', () => { describe('get', () => { it('returns list of settings', async () => { - const { body } = await supertestWithoutAuth + const { body } = await supertestAdminWithCookieCredentials .get('/internal/kibana/settings') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .expect(200); // The returned list of settings should contain the created test setting @@ -56,10 +54,8 @@ export default function ({ getService }: FtrProviderContext) { describe('set', () => { it('validates value', async () => { - const { body } = await supertestWithoutAuth + const { body } = await supertestAdminWithCookieCredentials .post(`/internal/kibana/settings/${DEFAULT_COLUMNS_SETTING}`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send({ value: 100 }) .expect(400); @@ -72,18 +68,14 @@ export default function ({ getService }: FtrProviderContext) { }); it('sets value of a setting', async () => { - await supertestWithoutAuth + await supertestAdminWithCookieCredentials .post(`/internal/kibana/settings/${TEST_SETTING}`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send({ value: 999 }) .expect(200); // Verify that the setting has a new value - const { body } = await supertestWithoutAuth + const { body } = await supertestAdminWithCookieCredentials .get('/internal/kibana/settings') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .expect(200); // The returned list of settings should contain the created test setting @@ -93,10 +85,8 @@ export default function ({ getService }: FtrProviderContext) { describe('set many', () => { it('validates value', async () => { - const { body } = await supertestWithoutAuth + const { body } = await supertestAdminWithCookieCredentials .post('/internal/kibana/settings') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send({ changes: { [TEST_SETTING]: 100, [DEFAULT_COLUMNS_SETTING]: 100 } }) .expect(400); @@ -109,18 +99,14 @@ export default function ({ getService }: FtrProviderContext) { }); it('sets values of settings', async () => { - await supertestWithoutAuth + await supertestAdminWithCookieCredentials .post(`/internal/kibana/settings`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send({ changes: { [TEST_SETTING]: 500 } }) .expect(200); // Verify that the setting has a new value - const { body } = await supertestWithoutAuth + const { body } = await supertestAdminWithCookieCredentials .get('/internal/kibana/settings') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .expect(200); // The returned list of settings should contain the created test setting @@ -130,10 +116,8 @@ export default function ({ getService }: FtrProviderContext) { describe('validate', () => { it('returns correct validation error message for invalid value', async () => { - const { body } = await supertestWithoutAuth + const { body } = await supertestAdminWithCookieCredentials .post(`/internal/kibana/settings/${DEFAULT_COLUMNS_SETTING}/validate`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send({ value: 100 }) .expect(200); @@ -144,10 +128,8 @@ export default function ({ getService }: FtrProviderContext) { }); it('returns no validation error message for valid value', async () => { - const { body } = await supertestWithoutAuth + const { body } = await supertestAdminWithCookieCredentials .post(`/internal/kibana/settings/${DEFAULT_COLUMNS_SETTING}/validate`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send({ value: ['test'] }) .expect(200); @@ -157,10 +139,8 @@ export default function ({ getService }: FtrProviderContext) { }); it('returns a 404 for non-existing key', async () => { - const { body } = await supertestWithoutAuth + const { body } = await supertestAdminWithCookieCredentials .post(`/internal/kibana/settings/nonExisting/validate`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send({ value: ['test'] }) .expect(404); @@ -172,10 +152,8 @@ export default function ({ getService }: FtrProviderContext) { }); it('returns a 400 for a null value', async () => { - const { body } = await supertestWithoutAuth + const { body } = await supertestAdminWithCookieCredentials .post(`/internal/kibana/settings/${DEFAULT_COLUMNS_SETTING}/validate`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send({ value: null }) .expect(400); @@ -189,17 +167,13 @@ export default function ({ getService }: FtrProviderContext) { describe('delete', () => { it('deletes setting', async () => { - await supertestWithoutAuth + await supertestAdminWithCookieCredentials .delete(`/internal/kibana/settings/${TEST_SETTING}`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .expect(200); // Verify that the setting is not returned in the Get response anymore - const { body } = await supertestWithoutAuth + const { body } = await supertestAdminWithCookieCredentials .get('/internal/kibana/settings') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .expect(200); // The returned list of settings should contain the created test setting diff --git a/x-pack/test_serverless/api_integration/test_suites/common/index_management/create_enrich_policies.ts b/x-pack/test_serverless/api_integration/test_suites/common/index_management/create_enrich_policies.ts index aa44e364e1e3..6f8d921ff993 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/index_management/create_enrich_policies.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/index_management/create_enrich_policies.ts @@ -6,29 +6,32 @@ */ import expect from 'expect'; +import { SupertestWithRoleScopeType } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services'; import { FtrProviderContext } from '../../../ftr_provider_context'; -import { InternalRequestHeader, RoleCredentials } from '../../../../shared/services'; const INTERNAL_API_BASE_PATH = '/internal/index_management'; export default function ({ getService }: FtrProviderContext) { + const svlCommonApi = getService('svlCommonApi'); + const roleScopedSupertest = getService('roleScopedSupertest'); + let supertestAdminWithCookieCredentials: SupertestWithRoleScopeType; const es = getService('es'); const log = getService('log'); - const svlCommonApi = getService('svlCommonApi'); - const svlUserManager = getService('svlUserManager'); - const supertestWithoutAuth = getService('supertestWithoutAuth'); - let roleAuthc: RoleCredentials; - let internalReqHeader: InternalRequestHeader; - describe('Create enrich policy', function () { const INDEX_A_NAME = `index-${Math.random()}`; const INDEX_B_NAME = `index-${Math.random()}`; const POLICY_NAME = `policy-${Math.random()}`; before(async () => { - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin'); - internalReqHeader = svlCommonApi.getInternalRequestHeader(); + supertestAdminWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope( + 'admin', + { + useCookieHeader: true, + withInternalHeaders: true, + } + ); + try { await es.indices.create({ index: INDEX_A_NAME, @@ -74,14 +77,11 @@ export default function ({ getService }: FtrProviderContext) { log.debug('[Cleanup error] Error deleting test index'); throw err; } - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); }); it('Allows to create an enrich policy', async () => { - const { body } = await supertestWithoutAuth + const { body } = await supertestAdminWithCookieCredentials .post(`${INTERNAL_API_BASE_PATH}/enrich_policies`) - .set(internalReqHeader) - .set(roleAuthc.apiKeyHeader) .send({ policy: { name: POLICY_NAME, @@ -97,10 +97,8 @@ export default function ({ getService }: FtrProviderContext) { }); it('Can retrieve fields from indices', async () => { - const { body } = await supertestWithoutAuth + const { body } = await supertestAdminWithCookieCredentials .post(`${INTERNAL_API_BASE_PATH}/enrich_policies/get_fields_from_indices`) - .set(internalReqHeader) - .set(roleAuthc.apiKeyHeader) .send({ indices: [INDEX_A_NAME, INDEX_B_NAME] }) .expect(200); @@ -126,10 +124,8 @@ export default function ({ getService }: FtrProviderContext) { }); it('Can retrieve matching indices', async () => { - const { body, status } = await supertestWithoutAuth + const { body, status } = await supertestAdminWithCookieCredentials .post(`${INTERNAL_API_BASE_PATH}/enrich_policies/get_matching_indices`) - .set(internalReqHeader) - .set(roleAuthc.apiKeyHeader) .send({ pattern: 'index-' }); svlCommonApi.assertResponseStatusCode(200, status, body); diff --git a/x-pack/test_serverless/api_integration/test_suites/common/index_management/indices.ts b/x-pack/test_serverless/api_integration/test_suites/common/index_management/indices.ts index 72b3a4a2e143..3e2a7630fef1 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/index_management/indices.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/index_management/indices.ts @@ -6,7 +6,8 @@ */ import expect from '@kbn/expect'; -import { InternalRequestHeader, RoleCredentials } from '../../../../shared/services'; +import { SupertestWithRoleScopeType } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services'; +import { RoleCredentials } from '../../../../shared/services'; import { FtrProviderContext } from '../../../ftr_provider_context'; const INTERNAL_API_BASE_PATH = '/internal/index_management'; @@ -18,17 +19,22 @@ export default function ({ getService }: FtrProviderContext) { const svlUserManager = getService('svlUserManager'); const svlIndicesApi = getService('svlIndicesApi'); const svlIndicesHelpers = getService('svlIndicesHelpers'); - - const supertestWithoutAuth = getService('supertestWithoutAuth'); + const roleScopedSupertest = getService('roleScopedSupertest'); + let supertestAdminWithCookieCredentials: SupertestWithRoleScopeType; let roleAuthc: RoleCredentials; - let internalReqHeader: InternalRequestHeader; describe('Indices', function () { let indexName: string; before(async () => { + supertestAdminWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope( + 'admin', + { + useCookieHeader: true, + withInternalHeaders: true, + } + ); roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin'); - internalReqHeader = svlCommonApi.getInternalRequestHeader(); log.debug(`Creating index: '${indexName}'`); try { indexName = await svlIndicesHelpers.createIndex(); @@ -76,10 +82,8 @@ export default function ({ getService }: FtrProviderContext) { describe('get index', () => { it('returns index details for the specified index name', async () => { - const { body: index } = await supertestWithoutAuth + const { body: index } = await supertestAdminWithCookieCredentials .get(`${INTERNAL_API_BASE_PATH}/indices/${indexName}`) - .set(internalReqHeader) - .set(roleAuthc.apiKeyHeader) .expect(200); expect(index).to.be.ok(); @@ -95,10 +99,8 @@ export default function ({ getService }: FtrProviderContext) { }); it('throws 404 for a non-existent index', async () => { - await supertestWithoutAuth + await supertestAdminWithCookieCredentials .get(`${INTERNAL_API_BASE_PATH}/indices/non_existent`) - .set(internalReqHeader) - .set(roleAuthc.apiKeyHeader) .expect(404); }); }); @@ -118,19 +120,15 @@ export default function ({ getService }: FtrProviderContext) { }); it('can create a new index', async () => { - await supertestWithoutAuth + await supertestAdminWithCookieCredentials .put(`${INTERNAL_API_BASE_PATH}/indices/create`) - .set(internalReqHeader) - .set(roleAuthc.apiKeyHeader) .send({ indexName: createIndexName, }) .expect(200); - const { body: index } = await supertestWithoutAuth + const { body: index } = await supertestAdminWithCookieCredentials .get(`${INTERNAL_API_BASE_PATH}/indices/${createIndexName}`) - .set(internalReqHeader) - .set(roleAuthc.apiKeyHeader) .expect(200); expect(index).to.be.ok(); @@ -146,10 +144,8 @@ export default function ({ getService }: FtrProviderContext) { }); it('fails to re-create the same index', async () => { - await supertestWithoutAuth + await supertestAdminWithCookieCredentials .put(`${INTERNAL_API_BASE_PATH}/indices/create`) - .set(internalReqHeader) - .set(roleAuthc.apiKeyHeader) .send({ indexName: createIndexName, }) diff --git a/x-pack/test_serverless/api_integration/test_suites/common/kql_telemetry/kql_telemetry.ts b/x-pack/test_serverless/api_integration/test_suites/common/kql_telemetry/kql_telemetry.ts index a45addf4a32a..abb5f8c0d25f 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/kql_telemetry/kql_telemetry.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/kql_telemetry/kql_telemetry.ts @@ -9,21 +9,29 @@ import expect from '@kbn/expect'; import { get } from 'lodash'; import { ANALYTICS_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server'; import { KQL_TELEMETRY_ROUTE_LATEST_VERSION } from '@kbn/data-plugin/common'; +import { SupertestWithRoleScopeType } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services'; import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; import type { FtrProviderContext } from '../../../ftr_provider_context'; -import { RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { const kibanaServer = getService('kibanaServer'); const es = getService('es'); - const svlCommonApi = getService('svlCommonApi'); - const svlUserManager = getService('svlUserManager'); - const supertestWithoutAuth = getService('supertestWithoutAuth'); - let roleAuthc: RoleCredentials; + const roleScopedSupertest = getService('roleScopedSupertest'); + let supertestAdminWithCookieCredentials: SupertestWithRoleScopeType; describe('telemetry API', () => { before(async () => { - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin'); + supertestAdminWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope( + 'admin', + { + useCookieHeader: true, + withInternalHeaders: true, + withCustomHeaders: { + [ELASTIC_HTTP_VERSION_HEADER]: KQL_TELEMETRY_ROUTE_LATEST_VERSION, + 'content-type': 'application/json', + }, + } + ); // TODO: Clean `kql-telemetry` before running the tests await kibanaServer.savedObjects.clean({ types: ['kql-telemetry'] }); await kibanaServer.importExport.load( @@ -34,18 +42,12 @@ export default function ({ getService }: FtrProviderContext) { await kibanaServer.importExport.unload( 'test/api_integration/fixtures/kbn_archiver/saved_objects/basic.json' ); - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); }); it('should increment the opt *in* counter in the .kibana_analytics/kql-telemetry document', async () => { - await supertestWithoutAuth + await supertestAdminWithCookieCredentials .post('/internal/kql_opt_in_stats') - .set('content-type', 'application/json') - .set(ELASTIC_HTTP_VERSION_HEADER, KQL_TELEMETRY_ROUTE_LATEST_VERSION) - // TODO: API requests in Serverless require internal request headers - .set(svlCommonApi.getInternalRequestHeader()) .send({ opt_in: true }) - .set(roleAuthc.apiKeyHeader) .expect(200); return es @@ -60,14 +62,9 @@ export default function ({ getService }: FtrProviderContext) { }); it('should increment the opt *out* counter in the .kibana_analytics/kql-telemetry document', async () => { - await supertestWithoutAuth + await supertestAdminWithCookieCredentials .post('/internal/kql_opt_in_stats') - .set('content-type', 'application/json') - .set(ELASTIC_HTTP_VERSION_HEADER, KQL_TELEMETRY_ROUTE_LATEST_VERSION) - // TODO: API requests in Serverless require internal request headers - .set(svlCommonApi.getInternalRequestHeader()) .send({ opt_in: false }) - .set(roleAuthc.apiKeyHeader) .expect(200); return es @@ -82,80 +79,42 @@ export default function ({ getService }: FtrProviderContext) { }); it('should report success when opt *in* is incremented successfully', async () => { - const { body } = await supertestWithoutAuth + const { body } = await supertestAdminWithCookieCredentials .post('/internal/kql_opt_in_stats') - .set('content-type', 'application/json') - .set(ELASTIC_HTTP_VERSION_HEADER, KQL_TELEMETRY_ROUTE_LATEST_VERSION) - // TODO: API requests in Serverless require internal request headers - .set(svlCommonApi.getInternalRequestHeader()) .send({ opt_in: true }) .expect('Content-Type', /json/) - .set(roleAuthc.apiKeyHeader) .expect(200); expect(body.success).to.be(true); }); it('should report success when opt *out* is incremented successfully', async () => { - const { body } = await supertestWithoutAuth + const { body } = await supertestAdminWithCookieCredentials .post('/internal/kql_opt_in_stats') - .set('content-type', 'application/json') - .set(ELASTIC_HTTP_VERSION_HEADER, KQL_TELEMETRY_ROUTE_LATEST_VERSION) - // TODO: API requests in Serverless require internal request headers - .set(svlCommonApi.getInternalRequestHeader()) .send({ opt_in: false }) .expect('Content-Type', /json/) - .set(roleAuthc.apiKeyHeader) .expect(200); expect(body.success).to.be(true); }); it('should only accept literal boolean values for the opt_in POST body param', function () { return Promise.all([ - supertestWithoutAuth + supertestAdminWithCookieCredentials .post('/internal/kql_opt_in_stats') - .set('content-type', 'application/json') - .set(ELASTIC_HTTP_VERSION_HEADER, KQL_TELEMETRY_ROUTE_LATEST_VERSION) - // TODO: API requests in Serverless require internal request headers - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send({ opt_in: 'notabool' }) .expect(400), - supertestWithoutAuth + supertestAdminWithCookieCredentials .post('/internal/kql_opt_in_stats') - .set('content-type', 'application/json') - .set(ELASTIC_HTTP_VERSION_HEADER, KQL_TELEMETRY_ROUTE_LATEST_VERSION) - // TODO: API requests in Serverless require internal request headers - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send({ opt_in: 0 }) .expect(400), - supertestWithoutAuth + supertestAdminWithCookieCredentials .post('/internal/kql_opt_in_stats') - .set('content-type', 'application/json') - .set(ELASTIC_HTTP_VERSION_HEADER, KQL_TELEMETRY_ROUTE_LATEST_VERSION) - // TODO: API requests in Serverless require internal request headers - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send({ opt_in: null }) .expect(400), - supertestWithoutAuth + supertestAdminWithCookieCredentials .post('/internal/kql_opt_in_stats') - .set('content-type', 'application/json') - .set(ELASTIC_HTTP_VERSION_HEADER, KQL_TELEMETRY_ROUTE_LATEST_VERSION) - // TODO: API requests in Serverless require internal request headers - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send({ opt_in: undefined }) .expect(400), - supertestWithoutAuth - .post('/internal/kql_opt_in_stats') - .set('content-type', 'application/json') - .set(ELASTIC_HTTP_VERSION_HEADER, KQL_TELEMETRY_ROUTE_LATEST_VERSION) - // TODO: API requests in Serverless require internal request headers - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) - .send({}) - .expect(400), + supertestAdminWithCookieCredentials.post('/internal/kql_opt_in_stats').send({}).expect(400), ]); }); }); diff --git a/x-pack/test_serverless/api_integration/test_suites/common/management/multiple_spaces_enabled.ts b/x-pack/test_serverless/api_integration/test_suites/common/management/multiple_spaces_enabled.ts index 5466829f30bf..0c62e64912fc 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/management/multiple_spaces_enabled.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/management/multiple_spaces_enabled.ts @@ -26,10 +26,11 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const svlCommonApi = getService('svlCommonApi'); const roleScopedSupertest = getService('roleScopedSupertest'); - let supertestWithAdminScope: SupertestWithRoleScopeType; + let supertestAdminWithApiKey: SupertestWithRoleScopeType; + let supertestAdminWithCookieCredentials: SupertestWithRoleScopeType; async function createSpace(id: string) { - await supertestWithAdminScope + await supertestAdminWithApiKey .post('/api/spaces/space') .send({ id, @@ -40,19 +41,25 @@ export default function ({ getService }: FtrProviderContext) { } async function deleteSpace(id: string) { - await supertestWithAdminScope.delete(`/api/spaces/space/${id}`).expect(204); + await supertestAdminWithApiKey.delete(`/api/spaces/space/${id}`).expect(204); } describe('spaces', function () { before(async () => { supertestWithAdminScope = await roleScopedSupertest.getSupertestWithRoleScope('admin', { withInternalHeaders: true, - withCustomHeaders: { 'kbn-xsrf': 'true' }, }); + supertestWithAdminScopeAndCookieHeader = await roleScopedSupertest.getSupertestWithRoleScope( + 'admin', + { + useCookieHeader: true, + withInternalHeaders: true, + } + ); }); after(async () => { // delete any lingering spaces - const { body } = await supertestWithAdminScope.get('/api/spaces/space').send().expect(200); + const { body } = await supertestAdminWithApiKey.get('/api/spaces/space').send().expect(200); const toDelete = (body as Array<{ id: string }>).filter((f) => f.id !== 'default'); @@ -63,7 +70,7 @@ export default function ({ getService }: FtrProviderContext) { describe('Create (POST /api/spaces/space)', () => { it('should allow us to create a space', async () => { - await supertestWithAdminScope + await supertestAdminWithApiKey .post('/api/spaces/space') .send({ id: 'custom_space_1', @@ -74,7 +81,7 @@ export default function ({ getService }: FtrProviderContext) { }); it('should not allow us to create a space with disabled features', async () => { - await supertestWithAdminScope + await supertestAdminWithApiKey .post('/api/spaces/space') .send({ id: 'custom_space_2', @@ -99,7 +106,7 @@ export default function ({ getService }: FtrProviderContext) { }); it('should allow us to get a space', async () => { - await supertestWithAdminScope.get('/api/spaces/space/space_to_get_1').send().expect(200, { + await supertestAdminWithApiKey.get('/api/spaces/space/space_to_get_1').send().expect(200, { id: 'space_to_get_1', name: 'space_to_get_1', disabledFeatures: [], @@ -107,7 +114,7 @@ export default function ({ getService }: FtrProviderContext) { }); it('should allow us to get all spaces', async () => { - const { body } = await supertestWithAdminScope.get('/api/spaces/space').send().expect(200); + const { body } = await supertestAdminWithApiKey.get('/api/spaces/space').send().expect(200); expect(body).toEqual( expect.arrayContaining([ @@ -137,7 +144,7 @@ export default function ({ getService }: FtrProviderContext) { }); it('should allow us to update a space', async () => { - await supertestWithAdminScope + await supertestAdminWithApiKey .put('/api/spaces/space/space_to_update') .send({ id: 'space_to_update', @@ -147,7 +154,7 @@ export default function ({ getService }: FtrProviderContext) { }) .expect(200); - await supertestWithAdminScope.get('/api/spaces/space/space_to_update').send().expect(200, { + await supertestAdminWithApiKey.get('/api/spaces/space/space_to_update').send().expect(200, { id: 'space_to_update', name: 'some new name', initials: 'SN', @@ -156,7 +163,7 @@ export default function ({ getService }: FtrProviderContext) { }); it('should not allow us to update a space with disabled features', async () => { - await supertestWithAdminScope + await supertestAdminWithApiKey .put('/api/spaces/space/space_to_update') .send({ id: 'space_to_update', @@ -172,7 +179,7 @@ export default function ({ getService }: FtrProviderContext) { it('should allow us to delete a space', async () => { await createSpace('space_to_delete'); - await supertestWithAdminScope.delete(`/api/spaces/space/space_to_delete`).expect(204); + await supertestAdminWithApiKey.delete(`/api/spaces/space/space_to_delete`).expect(204); }); }); @@ -186,7 +193,7 @@ export default function ({ getService }: FtrProviderContext) { }); it('returns the default space', async () => { - const response = await supertestWithAdminScope + const response = await supertestAdminWithCookieCredentials .get('/internal/spaces/_active_space') .expect(200); @@ -199,7 +206,7 @@ export default function ({ getService }: FtrProviderContext) { }); it('returns the default space when explicitly referenced', async () => { - const response = await supertestWithAdminScope + const response = await supertestAdminWithCookieCredentials .get('/s/default/internal/spaces/_active_space') .expect(200); @@ -212,7 +219,7 @@ export default function ({ getService }: FtrProviderContext) { }); it('returns the foo space', async () => { - await supertestWithAdminScope + await supertestAdminWithCookieCredentials .get('/s/foo-space/internal/spaces/_active_space') .expect(200, { id: 'foo-space', @@ -222,7 +229,7 @@ export default function ({ getService }: FtrProviderContext) { }); it('returns 404 when the space is not found', async () => { - await supertestWithAdminScope + await supertestAdminWithCookieCredentials .get('/s/not-found-space/internal/spaces/_active_space') .expect(404, { statusCode: 404, @@ -237,25 +244,25 @@ export default function ({ getService }: FtrProviderContext) { // are enabled in production. describe(`Access`, () => { it('#copyToSpace', async () => { - const { body, status } = await supertestWithAdminScope.post( + const { body, status } = await supertestAdminWithApiKey.post( '/api/spaces/_copy_saved_objects' ); svlCommonApi.assertResponseStatusCode(400, status, body); }); it('#resolveCopyToSpaceErrors', async () => { - const { body, status } = await supertestWithAdminScope.post( + const { body, status } = await supertestAdminWithApiKey.post( '/api/spaces/_resolve_copy_saved_objects_errors' ); svlCommonApi.assertResponseStatusCode(400, status, body); }); it('#updateObjectsSpaces', async () => { - const { body, status } = await supertestWithAdminScope.post( + const { body, status } = await supertestAdminWithApiKey.post( '/api/spaces/_update_objects_spaces' ); svlCommonApi.assertResponseStatusCode(400, status, body); }); it('#getShareableReferences', async () => { - const { body, status } = await supertestWithAdminScope + const { body, status } = await supertestAdminWithApiKey .post('/api/spaces/_get_shareable_references') .send({ objects: [{ type: 'a', id: 'a' }], @@ -263,7 +270,7 @@ export default function ({ getService }: FtrProviderContext) { svlCommonApi.assertResponseStatusCode(200, status, body); }); it('#disableLegacyUrlAliases', async () => { - const { body, status } = await supertestWithAdminScope.post( + const { body, status } = await supertestAdminWithApiKey.post( '/api/spaces/_disable_legacy_url_aliases' ); // without a request body we would normally a 400 bad request if the endpoint was registered diff --git a/x-pack/test_serverless/api_integration/test_suites/common/scripts_tests/languages.ts b/x-pack/test_serverless/api_integration/test_suites/common/scripts_tests/languages.ts index 9a2131b5defa..93a0359bfe2c 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/scripts_tests/languages.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/scripts_tests/languages.ts @@ -9,38 +9,37 @@ import expect from '@kbn/expect'; import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; import { SCRIPT_LANGUAGES_ROUTE_LATEST_VERSION } from '@kbn/data-plugin/common/constants'; +import { SupertestWithRoleScopeType } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services'; import { FtrProviderContext } from '../../../ftr_provider_context'; -import { RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { - const svlCommonApi = getService('svlCommonApi'); - const svlUserManager = getService('svlUserManager'); - let roleAuthc: RoleCredentials; - const supertestWithoutAuth = getService('supertestWithoutAuth'); + const roleScopedSupertest = getService('roleScopedSupertest'); + let supertestAdminWithCookieCredentials: SupertestWithRoleScopeType; describe('Script Languages API', function getLanguages() { before(async () => { - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin'); - }); - after(async () => { - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); + supertestAdminWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope( + 'admin', + { + useCookieHeader: true, + withInternalHeaders: true, + withCustomHeaders: { + [ELASTIC_HTTP_VERSION_HEADER]: SCRIPT_LANGUAGES_ROUTE_LATEST_VERSION, + }, + } + ); }); + it('should return 200 with an array of languages', async () => { - const response = await supertestWithoutAuth + const response = await supertestAdminWithCookieCredentials .get('/internal/scripts/languages') - .set(ELASTIC_HTTP_VERSION_HEADER, SCRIPT_LANGUAGES_ROUTE_LATEST_VERSION) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .expect(200); expect(response.body).to.be.an('array'); }); it.skip('should only return langs enabled for inline scripting', async () => { - const response = await supertestWithoutAuth + const response = await supertestAdminWithCookieCredentials .get('/internal/scripts/languages') - .set(ELASTIC_HTTP_VERSION_HEADER, SCRIPT_LANGUAGES_ROUTE_LATEST_VERSION) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .expect(200); expect(response.body).to.contain('expression'); expect(response.body).to.contain('painless'); diff --git a/x-pack/test_serverless/api_integration/test_suites/common/search_oss/bsearch.ts b/x-pack/test_serverless/api_integration/test_suites/common/search_oss/bsearch.ts index 718f40d812f8..93da25aed600 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/search_oss/bsearch.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/search_oss/bsearch.ts @@ -10,7 +10,7 @@ import request from 'superagent'; import { inflateResponse } from '@kbn/bfetch-plugin/public/streaming'; import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; import { BFETCH_ROUTE_VERSION_LATEST } from '@kbn/bfetch-plugin/common'; -import { RoleCredentials } from '../../../../shared/services'; +import { SupertestWithRoleScopeType } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services'; import type { FtrProviderContext } from '../../../ftr_provider_context'; import { painlessErrReq } from './painless_err_req'; import { verifyErrorResponse } from './verify_error'; @@ -26,46 +26,44 @@ function parseBfetchResponse(resp: request.Response, compressed: boolean = false export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); - const svlCommonApi = getService('svlCommonApi'); - - const svlUserManager = getService('svlUserManager'); - const supertestWithoutAuth = getService('supertestWithoutAuth'); - let roleAuthc: RoleCredentials; + const roleScopedSupertest = getService('roleScopedSupertest'); + let supertestAdminWithCookieCredentials: SupertestWithRoleScopeType; describe('bsearch', () => { before(async () => { - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin'); - }); - after(async () => { - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); + supertestAdminWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope( + 'admin', + { + useCookieHeader: true, + withInternalHeaders: true, + withCustomHeaders: { + [ELASTIC_HTTP_VERSION_HEADER]: BFETCH_ROUTE_VERSION_LATEST, + }, + } + ); }); + describe('post', () => { it('should return 200 a single response', async () => { - const resp = await supertestWithoutAuth - .post(`/internal/bsearch`) - .set(ELASTIC_HTTP_VERSION_HEADER, BFETCH_ROUTE_VERSION_LATEST) - // TODO: API requests in Serverless require internal request headers - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) - .send({ - batch: [ - { - request: { - params: { - index: '.kibana', - body: { - query: { - match_all: {}, - }, + const resp = await supertestAdminWithCookieCredentials.post(`/internal/bsearch`).send({ + batch: [ + { + request: { + params: { + index: '.kibana', + body: { + query: { + match_all: {}, }, }, }, - options: { - strategy: 'es', - }, }, - ], - }); + options: { + strategy: 'es', + }, + }, + ], + }); const jsonBody = parseBfetchResponse(resp); @@ -77,12 +75,8 @@ export default function ({ getService }: FtrProviderContext) { }); it('should return 200 a single response from compressed', async () => { - const resp = await supertestWithoutAuth + const resp = await supertestAdminWithCookieCredentials .post(`/internal/bsearch?compress=true`) - .set(ELASTIC_HTTP_VERSION_HEADER, BFETCH_ROUTE_VERSION_LATEST) - // TODO: API requests in Serverless require internal request headers - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send({ batch: [ { @@ -113,12 +107,9 @@ export default function ({ getService }: FtrProviderContext) { }); it('should return a batch of successful responses', async () => { - const resp = await supertestWithoutAuth + const resp = await supertestAdminWithCookieCredentials .post(`/internal/bsearch`) .set(ELASTIC_HTTP_VERSION_HEADER, BFETCH_ROUTE_VERSION_LATEST) - // TODO: API requests in Serverless require internal request headers - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send({ batch: [ { @@ -159,12 +150,9 @@ export default function ({ getService }: FtrProviderContext) { }); it('should return error for not found strategy', async () => { - const resp = await supertestWithoutAuth + const resp = await supertestAdminWithCookieCredentials .post(`/internal/bsearch`) .set(ELASTIC_HTTP_VERSION_HEADER, BFETCH_ROUTE_VERSION_LATEST) - // TODO: API requests in Serverless require internal request headers - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send({ batch: [ { @@ -193,12 +181,9 @@ export default function ({ getService }: FtrProviderContext) { }); it('should return 400 when index type is provided in "es" strategy', async () => { - const resp = await supertestWithoutAuth + const resp = await supertestAdminWithCookieCredentials .post(`/internal/bsearch`) .set(ELASTIC_HTTP_VERSION_HEADER, BFETCH_ROUTE_VERSION_LATEST) - // TODO: API requests in Serverless require internal request headers - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send({ batch: [ { @@ -236,12 +221,9 @@ export default function ({ getService }: FtrProviderContext) { await esArchiver.unload('test/functional/fixtures/es_archiver/logstash_functional'); }); it('should return 400 "search_phase_execution_exception" for Painless error in "es" strategy', async () => { - const resp = await supertestWithoutAuth + const resp = await supertestAdminWithCookieCredentials .post(`/internal/bsearch`) .set(ELASTIC_HTTP_VERSION_HEADER, BFETCH_ROUTE_VERSION_LATEST) - // TODO: API requests in Serverless require internal request headers - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send({ batch: [ { diff --git a/x-pack/test_serverless/api_integration/test_suites/common/search_oss/search.ts b/x-pack/test_serverless/api_integration/test_suites/common/search_oss/search.ts index 88772826e920..2d4e7190b93b 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/search_oss/search.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/search_oss/search.ts @@ -7,23 +7,29 @@ import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; import expect from '@kbn/expect'; -import { RoleCredentials } from '../../../../shared/services'; +import { SupertestWithRoleScopeType } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services'; import type { FtrProviderContext } from '../../../ftr_provider_context'; import { painlessErrReq } from './painless_err_req'; import { verifyErrorResponse } from './verify_error'; export default function ({ getService }: FtrProviderContext) { const esArchiver = getService('esArchiver'); - const svlCommonApi = getService('svlCommonApi'); const kibanaServer = getService('kibanaServer'); - - const svlUserManager = getService('svlUserManager'); - const supertestWithoutAuth = getService('supertestWithoutAuth'); - let roleAuthc: RoleCredentials; + const roleScopedSupertest = getService('roleScopedSupertest'); + let supertestAdminWithCookieCredentials: SupertestWithRoleScopeType; describe('search', () => { before(async () => { - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin'); + supertestAdminWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope( + 'admin', + { + useCookieHeader: true, + withInternalHeaders: true, + withCustomHeaders: { + [ELASTIC_HTTP_VERSION_HEADER]: '1', + }, + } + ); // TODO: emptyKibanaIndex fails in Serverless with // "index_not_found_exception: no such index [.kibana_ingest]", // so it was switched to `savedObjects.cleanStandardList()` @@ -32,17 +38,12 @@ export default function ({ getService }: FtrProviderContext) { }); after(async () => { await esArchiver.unload('test/functional/fixtures/es_archiver/logstash_functional'); - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); }); describe('post', () => { it('should return 200 when correctly formatted searches are provided', async () => { - const resp = await supertestWithoutAuth + const resp = await supertestAdminWithCookieCredentials .post(`/internal/search/es`) - .set(ELASTIC_HTTP_VERSION_HEADER, '1') - // TODO: API requests in Serverless require internal request headers - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send({ params: { body: { @@ -62,12 +63,8 @@ export default function ({ getService }: FtrProviderContext) { }); it('should return 200 if terminated early', async () => { - const resp = await supertestWithoutAuth + const resp = await supertestAdminWithCookieCredentials .post(`/internal/search/es`) - .set(ELASTIC_HTTP_VERSION_HEADER, '1') - // TODO: API requests in Serverless require internal request headers - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send({ params: { terminateAfter: 1, @@ -90,12 +87,8 @@ export default function ({ getService }: FtrProviderContext) { }); it('should return 404 when if no strategy is provided', async () => { - const resp = await supertestWithoutAuth + const resp = await supertestAdminWithCookieCredentials .post(`/internal/search`) - .set(ELASTIC_HTTP_VERSION_HEADER, '1') - // TODO: API requests in Serverless require internal request headers - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send({ body: { query: { @@ -109,12 +102,8 @@ export default function ({ getService }: FtrProviderContext) { }); it('should return 404 when if unknown strategy is provided', async () => { - const resp = await supertestWithoutAuth + const resp = await supertestAdminWithCookieCredentials .post(`/internal/search/banana`) - .set(ELASTIC_HTTP_VERSION_HEADER, '1') - // TODO: API requests in Serverless require internal request headers - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send({ body: { query: { @@ -130,12 +119,8 @@ export default function ({ getService }: FtrProviderContext) { }); it('should return 400 with illegal ES argument', async () => { - const resp = await supertestWithoutAuth + const resp = await supertestAdminWithCookieCredentials .post(`/internal/search/es`) - .set(ELASTIC_HTTP_VERSION_HEADER, '1') - // TODO: API requests in Serverless require internal request headers - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send({ params: { timeout: 1, // This should be a time range string! @@ -154,12 +139,8 @@ export default function ({ getService }: FtrProviderContext) { }); it('should return 400 with a bad body', async () => { - const resp = await supertestWithoutAuth + const resp = await supertestAdminWithCookieCredentials .post(`/internal/search/es`) - .set(ELASTIC_HTTP_VERSION_HEADER, '1') - // TODO: API requests in Serverless require internal request headers - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send({ params: { body: { @@ -174,12 +155,8 @@ export default function ({ getService }: FtrProviderContext) { }); it('should return 400 for a painless error', async () => { - const resp = await supertestWithoutAuth + const resp = await supertestAdminWithCookieCredentials .post(`/internal/search/es`) - .set(ELASTIC_HTTP_VERSION_HEADER, '1') - // TODO: API requests in Serverless require internal request headers - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send(painlessErrReq) .expect(400); @@ -189,24 +166,16 @@ export default function ({ getService }: FtrProviderContext) { describe('delete', () => { it('should return 404 when no search id provided', async () => { - const resp = await supertestWithoutAuth + const resp = await supertestAdminWithCookieCredentials .delete(`/internal/search/es`) - .set(ELASTIC_HTTP_VERSION_HEADER, '1') - // TODO: API requests in Serverless require internal request headers - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send() .expect(404); verifyErrorResponse(resp.body, 404); }); it('should return 400 when trying a delete on a non supporting strategy', async () => { - const resp = await supertestWithoutAuth + const resp = await supertestAdminWithCookieCredentials .delete(`/internal/search/es/123`) - .set(ELASTIC_HTTP_VERSION_HEADER, '1') - // TODO: API requests in Serverless require internal request headers - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .send() .expect(400); verifyErrorResponse(resp.body, 400); diff --git a/x-pack/test_serverless/api_integration/test_suites/common/telemetry/telemetry_config.ts b/x-pack/test_serverless/api_integration/test_suites/common/telemetry/telemetry_config.ts index 6518dcd30f14..b6ca1666181f 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/telemetry/telemetry_config.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/telemetry/telemetry_config.ts @@ -6,23 +6,30 @@ */ import { expect } from 'expect'; -import type { RoleCredentials } from '../../../../shared/services'; +import { SupertestWithRoleScopeType } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services'; import { FtrProviderContext } from '../../../ftr_provider_context'; export default function telemetryConfigTest({ getService }: FtrProviderContext) { - const svlCommonApi = getService('svlCommonApi'); - const svlUserManager = getService('svlUserManager'); - const supertestWithoutAuth = getService('supertestWithoutAuth'); + const roleScopedSupertest = getService('roleScopedSupertest'); + let supertestAdminWithApiKey: SupertestWithRoleScopeType; + let supertestAdminWithCookieCredentials: SupertestWithRoleScopeType; describe('/api/telemetry/v2/config API Telemetry config', function () { - let roleAuthc: RoleCredentials; - before(async () => { - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin'); + supertestAdminWithApiKey = await roleScopedSupertest.getSupertestWithRoleScope('admin', { + withCommonHeaders: true, + }); + supertestAdminWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope( + 'admin', + { + useCookieHeader: true, + withInternalHeaders: true, + } + ); }); after(async () => { - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); + await supertestAdminWithApiKey.destroy(); }); const baseConfig = { @@ -33,56 +40,38 @@ export default function telemetryConfigTest({ getService }: FtrProviderContext) }; it('GET should get the default config', async () => { - const { body } = await supertestWithoutAuth - .get('/api/telemetry/v2/config') - .set(svlCommonApi.getCommonRequestHeader()) - .set(roleAuthc.apiKeyHeader) - .expect(200); + const { body } = await supertestAdminWithApiKey.get('/api/telemetry/v2/config').expect(200); expect(body).toMatchObject(baseConfig); }); it('GET should get updated labels after dynamically updating them', async () => { - const { body: initialConfig } = await supertestWithoutAuth + const { body: initialConfig } = await supertestAdminWithApiKey .get('/api/telemetry/v2/config') - .set(svlCommonApi.getCommonRequestHeader()) - .set(roleAuthc.apiKeyHeader) .expect(200); - await supertestWithoutAuth + await supertestAdminWithCookieCredentials .put('/internal/core/_settings') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .set('elastic-api-version', '1') .send({ 'telemetry.labels.journeyName': 'my-ftr-test' }) .expect(200, { ok: true }); - await supertestWithoutAuth - .get('/api/telemetry/v2/config') - .set(svlCommonApi.getCommonRequestHeader()) - .set(roleAuthc.apiKeyHeader) - .expect(200, { - ...initialConfig, - labels: { - ...initialConfig.labels, - journeyName: 'my-ftr-test', - }, - }); + await supertestAdminWithApiKey.get('/api/telemetry/v2/config').expect(200, { + ...initialConfig, + labels: { + ...initialConfig.labels, + journeyName: 'my-ftr-test', + }, + }); // Sends "null" to remove the label - await supertestWithoutAuth + await supertestAdminWithCookieCredentials .put('/internal/core/_settings') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .set('elastic-api-version', '1') .send({ 'telemetry.labels.journeyName': null }) .expect(200, { ok: true }); - await supertestWithoutAuth - .get('/api/telemetry/v2/config') - .set(svlCommonApi.getCommonRequestHeader()) - .set(roleAuthc.apiKeyHeader) - .expect(200, initialConfig); + await supertestAdminWithApiKey.get('/api/telemetry/v2/config').expect(200, initialConfig); }); }); } From 166eacfeffdd6ca36c2d1da3ecfe90a8dd92f0cf Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Fri, 13 Sep 2024 16:02:48 +0200 Subject: [PATCH 09/18] update more tests --- .../management/multiple_spaces_enabled.ts | 6 +- .../test_suites/common/management/spaces.ts | 93 ++++++++----------- .../common/platform_security/anonymous.ts | 37 ++++---- .../common/platform_security/authorization.ts | 87 +++++++---------- .../platform_security/response_headers.ts | 26 +++--- .../roles_routes_feature_flag.ts | 45 +++++---- .../search/serverless_search/api_key.ts | 47 +++++----- 7 files changed, 162 insertions(+), 179 deletions(-) diff --git a/x-pack/test_serverless/api_integration/test_suites/common/management/multiple_spaces_enabled.ts b/x-pack/test_serverless/api_integration/test_suites/common/management/multiple_spaces_enabled.ts index 0c62e64912fc..1fed5a62b9db 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/management/multiple_spaces_enabled.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/management/multiple_spaces_enabled.ts @@ -46,10 +46,10 @@ export default function ({ getService }: FtrProviderContext) { describe('spaces', function () { before(async () => { - supertestWithAdminScope = await roleScopedSupertest.getSupertestWithRoleScope('admin', { + supertestAdminWithApiKey = await roleScopedSupertest.getSupertestWithRoleScope('admin', { withInternalHeaders: true, }); - supertestWithAdminScopeAndCookieHeader = await roleScopedSupertest.getSupertestWithRoleScope( + supertestAdminWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope( 'admin', { useCookieHeader: true, @@ -66,6 +66,8 @@ export default function ({ getService }: FtrProviderContext) { await asyncForEach(toDelete, async (space) => { await deleteSpace(space.id); }); + + await supertestAdminWithApiKey.destroy(); }); describe('Create (POST /api/spaces/space)', () => { diff --git a/x-pack/test_serverless/api_integration/test_suites/common/management/spaces.ts b/x-pack/test_serverless/api_integration/test_suites/common/management/spaces.ts index 5c1e22811bdc..7014dcd6100d 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/management/spaces.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/management/spaces.ts @@ -6,35 +6,37 @@ */ import expect from 'expect'; +import { SupertestWithRoleScopeType } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services'; import { FtrProviderContext } from '../../../ftr_provider_context'; -import { RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { const svlCommonApi = getService('svlCommonApi'); - const svlUserManager = getService('svlUserManager'); - const supertestWithoutAuth = getService('supertestWithoutAuth'); - let commonRequestHeader: Record; - let internalRequestHeader: Record; - let roleAuthc: RoleCredentials; + const samlAuth = getService('samlAuth'); + const roleScopedSupertest = getService('roleScopedSupertest'); + let supertestAdminWithApiKey: SupertestWithRoleScopeType; + let supertestAdminWithCookieCredentials: SupertestWithRoleScopeType; describe('spaces', function () { before(async () => { // admin is the only predefined role that will work for all 3 solutions - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin'); - commonRequestHeader = svlCommonApi.getCommonRequestHeader(); - internalRequestHeader = svlCommonApi.getInternalRequestHeader(); + supertestAdminWithApiKey = await roleScopedSupertest.getSupertestWithRoleScope('admin'); + supertestAdminWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope( + 'admin', + { + useCookieHeader: true, + } + ); }); after(async () => { - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); + await supertestAdminWithApiKey.destroy(); }); describe('route access', () => { it('#delete', async () => { - const { body, status } = await supertestWithoutAuth + const { body, status } = await supertestAdminWithApiKey .delete('/api/spaces/space/default') - .set(internalRequestHeader) - .set(roleAuthc.apiKeyHeader); + .set(samlAuth.getInternalRequestHeader()); svlCommonApi.assertResponseStatusCode(400, status, body); }); @@ -42,10 +44,9 @@ export default function ({ getService }: FtrProviderContext) { // Skipped due to change in QA environment for role management and spaces // TODO: revisit once the change is rolled out to all environments it.skip('#create', async () => { - const { body, status } = await supertestWithoutAuth + const { body, status } = await supertestAdminWithApiKey .post('/api/spaces/space') - .set(internalRequestHeader) - .set(roleAuthc.apiKeyHeader) + .set(samlAuth.getInternalRequestHeader()) .send({ id: 'custom', name: 'Custom', @@ -56,10 +57,9 @@ export default function ({ getService }: FtrProviderContext) { }); it('#update requires internal header', async () => { - const { body, status } = await supertestWithoutAuth + const { body, status } = await supertestAdminWithApiKey .put('/api/spaces/space/default') - .set(internalRequestHeader) - .set(roleAuthc.apiKeyHeader) + .set(samlAuth.getInternalRequestHeader()) .send({ id: 'default', name: 'UPDATED!', @@ -70,37 +70,33 @@ export default function ({ getService }: FtrProviderContext) { }); it('#copyToSpace', async () => { - const { body, status } = await supertestWithoutAuth + const { body, status } = await supertestAdminWithApiKey .post('/api/spaces/_copy_saved_objects') - .set(internalRequestHeader) - .set(roleAuthc.apiKeyHeader); + .set(samlAuth.getInternalRequestHeader()); svlCommonApi.assertResponseStatusCode(400, status, body); }); it('#resolveCopyToSpaceErrors', async () => { - const { body, status } = await supertestWithoutAuth + const { body, status } = await supertestAdminWithApiKey .post('/api/spaces/_resolve_copy_saved_objects_errors') - .set(internalRequestHeader) - .set(roleAuthc.apiKeyHeader); + .set(samlAuth.getInternalRequestHeader()); svlCommonApi.assertResponseStatusCode(400, status, body); }); it('#updateObjectsSpaces', async () => { - const { body, status } = await supertestWithoutAuth + const { body, status } = await supertestAdminWithApiKey .post('/api/spaces/_update_objects_spaces') - .set(internalRequestHeader) - .set(roleAuthc.apiKeyHeader); + .set(samlAuth.getInternalRequestHeader()); svlCommonApi.assertResponseStatusCode(400, status, body); }); it('#getShareableReferences', async () => { - const { body, status } = await supertestWithoutAuth + const { body, status } = await supertestAdminWithApiKey .post('/api/spaces/_get_shareable_references') - .set(internalRequestHeader) - .set(roleAuthc.apiKeyHeader) + .set(samlAuth.getInternalRequestHeader()) .send({ objects: [{ type: 'a', id: 'a' }], }); @@ -109,10 +105,9 @@ export default function ({ getService }: FtrProviderContext) { }); it('#disableLegacyUrlAliases', async () => { - const { body, status } = await supertestWithoutAuth + const { body, status } = await supertestAdminWithApiKey .post('/api/spaces/_disable_legacy_url_aliases') - .set(internalRequestHeader) - .set(roleAuthc.apiKeyHeader); + .set(samlAuth.getInternalRequestHeader()); // without a request body we would normally a 400 bad request if the endpoint was registered svlCommonApi.assertApiNotFound(body, status); @@ -123,10 +118,9 @@ export default function ({ getService }: FtrProviderContext) { let body: any; let status: number; - ({ body, status } = await supertestWithoutAuth + ({ body, status } = await supertestAdminWithApiKey .get('/api/spaces/space/default') - .set(commonRequestHeader) - .set(roleAuthc.apiKeyHeader)); + .set(samlAuth.getCommonRequestHeader())); // expect a rejection because we're not using the internal header expect(body).toEqual({ statusCode: 400, @@ -137,10 +131,9 @@ export default function ({ getService }: FtrProviderContext) { }); expect(status).toBe(400); - ({ body, status } = await supertestWithoutAuth + ({ body, status } = await supertestAdminWithApiKey .get('/api/spaces/space/default') - .set(internalRequestHeader) - .set(roleAuthc.apiKeyHeader)); + .set(samlAuth.getInternalRequestHeader())); // expect success because we're using the internal header expect(body).toEqual( expect.objectContaining({ @@ -154,10 +147,9 @@ export default function ({ getService }: FtrProviderContext) { let body: any; let status: number; - ({ body, status } = await supertestWithoutAuth + ({ body, status } = await supertestAdminWithApiKey .get('/api/spaces/space') - .set(commonRequestHeader) - .set(roleAuthc.apiKeyHeader)); + .set(samlAuth.getCommonRequestHeader())); // expect a rejection because we're not using the internal header expect(body).toEqual({ statusCode: 400, @@ -168,10 +160,9 @@ export default function ({ getService }: FtrProviderContext) { }); expect(status).toBe(400); - ({ body, status } = await supertestWithoutAuth + ({ body, status } = await supertestAdminWithApiKey .get('/api/spaces/space') - .set(internalRequestHeader) - .set(roleAuthc.apiKeyHeader)); + .set(samlAuth.getInternalRequestHeader())); // expect success because we're using the internal header expect(body).toEqual( expect.arrayContaining([ @@ -187,10 +178,9 @@ export default function ({ getService }: FtrProviderContext) { let body: any; let status: number; - ({ body, status } = await supertestWithoutAuth + ({ body, status } = await supertestAdminWithCookieCredentials .get('/internal/spaces/_active_space') - .set(commonRequestHeader) - .set(roleAuthc.apiKeyHeader)); + .set(samlAuth.getCommonRequestHeader())); // expect a rejection because we're not using the internal header expect(body).toEqual({ statusCode: 400, @@ -201,10 +191,9 @@ export default function ({ getService }: FtrProviderContext) { }); expect(status).toBe(400); - ({ body, status } = await supertestWithoutAuth + ({ body, status } = await supertestAdminWithCookieCredentials .get('/internal/spaces/_active_space') - .set(internalRequestHeader) - .set(roleAuthc.apiKeyHeader)); + .set(samlAuth.getInternalRequestHeader())); // expect success because we're using the internal header expect(body).toEqual( expect.objectContaining({ 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 765c2a8c30c5..dc4cddd0d984 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 @@ -5,39 +5,40 @@ * 2.0. */ +import { SupertestWithRoleScopeType } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services'; import { FtrProviderContext } from '../../../ftr_provider_context'; -import { InternalRequestHeader, RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { const svlCommonApi = getService('svlCommonApi'); - const svlUserManager = getService('svlUserManager'); - const supertestWithoutAuth = getService('supertestWithoutAuth'); - let roleAuthc: RoleCredentials; - let internalReqHeader: InternalRequestHeader; + const roleScopedSupertest = getService('roleScopedSupertest'); + let supertestAdminWithCookieCredentials: SupertestWithRoleScopeType; describe('security/anonymous', function () { before(async () => { - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin'); - internalReqHeader = svlCommonApi.getInternalRequestHeader(); - }); - after(async () => { - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); + supertestAdminWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope( + 'admin', + { + useCookieHeader: true, + withInternalHeaders: true, + } + ); }); + describe('route access', () => { describe('disabled', () => { it('get access capabilities', async () => { - const { body, status } = await supertestWithoutAuth - .get('/internal/security/anonymous_access/capabilities') - .set(internalReqHeader) - .set(roleAuthc.apiKeyHeader); + const { body, status } = await supertestAdminWithCookieCredentials.get( + '/internal/security/anonymous_access/capabilities' + ); + svlCommonApi.assertApiNotFound(body, status); }); it('get access state', async () => { - const { body, status } = await supertestWithoutAuth - .get('/internal/security/anonymous_access/state') - .set(internalReqHeader) - .set(roleAuthc.apiKeyHeader); + const { body, status } = await supertestAdminWithCookieCredentials.get( + '/internal/security/anonymous_access/state' + ); + svlCommonApi.assertApiNotFound(body, status); }); }); 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 c4245985a245..4c77607d7d84 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 @@ -7,8 +7,8 @@ import expect from 'expect'; import { KibanaFeatureConfig, SubFeaturePrivilegeConfig } from '@kbn/features-plugin/common'; +import { SupertestWithRoleScopeType } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services'; import { FtrProviderContext } from '../../../ftr_provider_context'; -import { InternalRequestHeader, RoleCredentials } from '../../../../shared/services'; function collectSubFeaturesPrivileges(feature: KibanaFeatureConfig) { return new Map( @@ -25,21 +25,27 @@ 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'); - let roleAuthc: RoleCredentials; - let internalReqHeader: InternalRequestHeader; + const roleScopedSupertest = getService('roleScopedSupertest'); + let supertestAdminWithCookieCredentials: SupertestWithRoleScopeType; + let supertestAdminWithApiKey: SupertestWithRoleScopeType; describe('security/authorization', function () { // see details: https://github.com/elastic/kibana/issues/192282 this.tags(['failsOnMKI']); before(async () => { - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin'); - internalReqHeader = svlCommonApi.getInternalRequestHeader(); + supertestAdminWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope( + 'admin', + { + useCookieHeader: true, + withInternalHeaders: true, + } + ); + supertestAdminWithApiKey = await roleScopedSupertest.getSupertestWithRoleScope('admin', { + withInternalHeaders: true, + }); }); after(async () => { - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); + await supertestAdminWithApiKey.destroy(); }); describe('route access', () => { describe('internal', () => { @@ -47,60 +53,47 @@ export default function ({ getService }: FtrProviderContext) { // Skipped due to change in QA environment for role management and spaces // TODO: revisit once the change is rolled out to all environments it.skip('get all privileges', async () => { - const { body, status } = await supertestWithoutAuth - .get('/api/security/privileges') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { body, status } = await supertestAdminWithApiKey.get('/api/security/privileges'); svlCommonApi.assertApiNotFound(body, status); }); // Skipped due to change in QA environment for role management and spaces // TODO: revisit once the change is rolled out to all environments it.skip('get built-in elasticsearch privileges', async () => { - const { body, status } = await supertestWithoutAuth - .get('/internal/security/esPrivileges/builtin') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { body, status } = await supertestAdminWithCookieCredentials.get( + '/internal/security/esPrivileges/builtin' + ); svlCommonApi.assertApiNotFound(body, status); }); it('create/update roleAuthc', async () => { - const { body, status } = await supertestWithoutAuth - .put('/api/security/role/test') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { body, status } = await supertestAdminWithApiKey.put('/api/security/role/test'); svlCommonApi.assertApiNotFound(body, status); }); it('get roleAuthc', async () => { - const { body, status } = await supertestWithoutAuth - .get('/api/security/role/superuser') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { body, status } = await supertestAdminWithApiKey.get( + '/api/security/role/superuser' + ); svlCommonApi.assertApiNotFound(body, status); }); it('get all roles', async () => { - const { body, status } = await supertestWithoutAuth - .get('/api/security/role') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { body, status } = await supertestAdminWithApiKey.get('/api/security/role'); svlCommonApi.assertApiNotFound(body, status); }); it('delete roleAuthc', async () => { - const { body, status } = await supertestWithoutAuth - .delete('/api/security/role/superuser') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { body, status } = await supertestAdminWithApiKey.delete( + '/api/security/role/superuser' + ); svlCommonApi.assertApiNotFound(body, status); }); it('get shared saved object permissions', async () => { - const { body, status } = await supertestWithoutAuth - .get('/internal/security/_share_saved_object_permissions') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { body, status } = await supertestAdminWithCookieCredentials.get( + '/internal/security/_share_saved_object_permissions' + ); svlCommonApi.assertApiNotFound(body, status); }); }); @@ -108,29 +101,17 @@ export default function ({ getService }: FtrProviderContext) { describe('public', () => { it('reset session page', async () => { - const { status } = await supertestWithoutAuth - .get('/internal/security/reset_session_page.js') - .set(internalReqHeader) - .set(roleAuthc.apiKeyHeader); + const { status } = await supertestAdminWithCookieCredentials.get( + '/internal/security/reset_session_page.js' + ); expect(status).toBe(200); }); }); }); describe('available features', () => { - let adminCredentials: { Cookie: string }; - - before(async () => { - // get auth header for Viewer roleAuthc - adminCredentials = await svlUserManager.getM2MApiCredentialsWithRoleScope('admin'); - }); - it('all Dashboard and Discover sub-feature privileges are disabled', async () => { - const { body } = await supertest - .get('/api/features') - .set(svlCommonApi.getInternalRequestHeader()) - .set(adminCredentials) - .expect(200); + const { body } = await supertestAdminWithCookieCredentials.get('/api/features').expect(200); // We should make sure that neither Discover nor Dashboard displays any sub-feature privileges in Serverless. // If any of these features adds a new sub-feature privilege we should make an explicit decision whether it 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 562e98d33866..ea37efd75d6d 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 @@ -7,14 +7,14 @@ import expect from 'expect'; import cspParser from 'content-security-policy-parser'; +import { SupertestWithRoleScopeType } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services'; import { FtrProviderContext } from '../../../ftr_provider_context'; -import { RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { - const svlCommonApi = getService('svlCommonApi'); - const svlUserManager = getService('svlUserManager'); + const samlAuth = getService('samlAuth'); const supertestWithoutAuth = getService('supertestWithoutAuth'); - let roleAuthc: RoleCredentials; + const roleScopedSupertest = getService('roleScopedSupertest'); + let supertestViewerWithCookieCredentials: SupertestWithRoleScopeType; 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'`; @@ -27,16 +27,18 @@ export default function ({ getService }: FtrProviderContext) { const defaultXFrameOptions = 'SAMEORIGIN'; before(async () => { - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('viewer'); - }); - after(async () => { - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); + supertestViewerWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope( + 'viewer', + { + useCookieHeader: true, + withInternalHeaders: true, + } + ); }); + it('API endpoint response contains default security headers', async () => { - const { header } = await supertestWithoutAuth + const { header } = await supertestViewerWithCookieCredentials .get(`/internal/security/me`) - .set(roleAuthc.apiKeyHeader) - .set(svlCommonApi.getInternalRequestHeader()) .expect(200); expect(header).toBeDefined(); @@ -52,7 +54,7 @@ export default function ({ getService }: FtrProviderContext) { it('redirect endpoint response contains default security headers', async () => { const { header } = await supertestWithoutAuth .get(`/logout`) - .set(svlCommonApi.getInternalRequestHeader()) + .set(samlAuth.getInternalRequestHeader()) .expect(200); expect(header).toBeDefined(); diff --git a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/roles_routes_feature_flag.ts b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/roles_routes_feature_flag.ts index 6d5a6f93b118..da03ad14047b 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/platform_security/roles_routes_feature_flag.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/platform_security/roles_routes_feature_flag.ts @@ -26,15 +26,22 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const platformSecurityUtils = getService('platformSecurityUtils'); const roleScopedSupertest = getService('roleScopedSupertest'); - let supertestWithAdminScope: SupertestWithRoleScopeType; + let supertestAdminWithApiKey: SupertestWithRoleScopeType; + let supertestAdminWithCookieCredentials: SupertestWithRoleScopeType; const es = getService('es'); describe('security', function () { describe('Roles', () => { before(async () => { - supertestWithAdminScope = await roleScopedSupertest.getSupertestWithRoleScope('admin', { + supertestAdminWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope( + 'admin', + { + useCookieHeader: true, + withInternalHeaders: true, + } + ); + supertestAdminWithApiKey = await roleScopedSupertest.getSupertestWithRoleScope('admin', { withInternalHeaders: true, - withCustomHeaders: { 'kbn-xsrf': 'true' }, }); }); after(async () => { @@ -43,11 +50,11 @@ export default function ({ getService }: FtrProviderContext) { describe('Create Role', () => { it('should allow us to create an empty role', async () => { - await supertestWithAdminScope.put('/api/security/role/empty_role').send({}).expect(204); + await supertestAdminWithApiKey.put('/api/security/role/empty_role').send({}).expect(204); }); it('should create a role with kibana and elasticsearch privileges', async () => { - await supertestWithAdminScope + await supertestAdminWithApiKey .put('/api/security/role/role_with_privileges') .send({ metadata: { @@ -113,7 +120,7 @@ export default function ({ getService }: FtrProviderContext) { }); it(`should create a role with kibana and FLS/DLS elasticsearch privileges`, async () => { - await supertestWithAdminScope + await supertestAdminWithApiKey .put('/api/security/role/role_with_privileges_dls_fls') .send({ metadata: { @@ -139,7 +146,7 @@ export default function ({ getService }: FtrProviderContext) { // serverless only (stateful will allow) it(`should not create a role with 'run as' privileges`, async () => { - await supertestWithAdminScope + await supertestAdminWithApiKey .put('/api/security/role/role_with_privileges') .send({ metadata: { @@ -174,7 +181,7 @@ export default function ({ getService }: FtrProviderContext) { // serverless only (stateful will allow) it(`should not create a role with remote cluster privileges`, async () => { - await supertestWithAdminScope + await supertestAdminWithApiKey .put('/api/security/role/role_with_privileges') .send({ metadata: { @@ -214,7 +221,7 @@ export default function ({ getService }: FtrProviderContext) { // serverless only (stateful will allow) it(`should not create a role with remote index privileges`, async () => { - await supertestWithAdminScope + await supertestAdminWithApiKey .put('/api/security/role/role_with_privileges') .send({ metadata: { @@ -268,14 +275,14 @@ export default function ({ getService }: FtrProviderContext) { }, }); - await supertestWithAdminScope + await supertestAdminWithApiKey .put('/api/security/role/test_role?createOnly=true') .send({}) .expect(409); }); it('should succeed when role does not exist', async () => { - await supertestWithAdminScope + await supertestAdminWithApiKey .put('/api/security/role/new_role?createOnly=true') .send({}) .expect(204); @@ -321,7 +328,7 @@ export default function ({ getService }: FtrProviderContext) { }, }); - await supertestWithAdminScope.get('/api/security/role/role_to_get').expect(200, { + await supertestAdminWithApiKey.get('/api/security/role/role_to_get').expect(200, { name: 'role_to_get', metadata: { foo: 'test-metadata', @@ -413,7 +420,7 @@ export default function ({ getService }: FtrProviderContext) { }, }); - await supertestWithAdminScope + await supertestAdminWithCookieCredentials .get('/internal/security/roles/engineering') .expect(200) .expect((res: { body: Role[] }) => { @@ -469,7 +476,7 @@ export default function ({ getService }: FtrProviderContext) { }, }); - await supertestWithAdminScope + await supertestAdminWithApiKey .put('/api/security/role/role_to_update') .send({ metadata: { @@ -553,7 +560,7 @@ export default function ({ getService }: FtrProviderContext) { }, }); - await supertestWithAdminScope + await supertestAdminWithApiKey .put('/api/security/role/role_to_update_with_dls_fls') .send({ elasticsearch: { @@ -612,7 +619,7 @@ export default function ({ getService }: FtrProviderContext) { }, }); - await supertestWithAdminScope + await supertestAdminWithApiKey .put('/api/security/role/role_to_update') .send({ metadata: { @@ -708,7 +715,7 @@ export default function ({ getService }: FtrProviderContext) { }, }); - await supertestWithAdminScope + await supertestAdminWithApiKey .put('/api/security/role/role_to_update') .send({ metadata: { @@ -809,7 +816,7 @@ export default function ({ getService }: FtrProviderContext) { }, }); - await supertestWithAdminScope + await supertestAdminWithApiKey .put('/api/security/role/role_to_update') .send({ metadata: { @@ -911,7 +918,7 @@ export default function ({ getService }: FtrProviderContext) { }, }, }); - await supertestWithAdminScope.delete('/api/security/role/role_to_delete').expect(204); + await supertestAdminWithApiKey.delete('/api/security/role/role_to_delete').expect(204); const deletedRole = await es.security.getRole( { name: 'role_to_delete' }, diff --git a/x-pack/test_serverless/api_integration/test_suites/search/serverless_search/api_key.ts b/x-pack/test_serverless/api_integration/test_suites/search/serverless_search/api_key.ts index 3c94acc039c3..3e43093c6d09 100644 --- a/x-pack/test_serverless/api_integration/test_suites/search/serverless_search/api_key.ts +++ b/x-pack/test_serverless/api_integration/test_suites/search/serverless_search/api_key.ts @@ -8,32 +8,32 @@ import expect from 'expect'; import { kibanaTestSuperuserServerless } from '@kbn/test'; import { SecurityApiKey } from '@elastic/elasticsearch/lib/api/types'; -import { RoleCredentials } from '../../../../shared/services'; +import { SupertestWithRoleScopeType } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services'; import { FtrProviderContext } from '../../../ftr_provider_context'; const API_BASE_PATH = '/internal/serverless_search'; export default function ({ getService }: FtrProviderContext) { - const svlCommonApi = getService('svlCommonApi'); - const supertestWithoutAuth = getService('supertestWithoutAuth'); - const svlUserManager = getService('svlUserManager'); + const roleScopedSupertest = getService('roleScopedSupertest'); const es = getService('es'); const log = getService('log'); - let roleAuthc: RoleCredentials; + let supertestDeveloperWithApiKey: SupertestWithRoleScopeType; describe('API Key routes', function () { describe('GET api_keys', function () { before(async () => { - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('developer'); - }); - after(async () => { - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); + supertestDeveloperWithApiKey = await roleScopedSupertest.getSupertestWithRoleScope( + 'developer', + { + useCookieHeader: true, + withInternalHeaders: true, + } + ); }); + it('return apiKeys', async () => { - const { body } = await supertestWithoutAuth + const { body } = await supertestDeveloperWithApiKey .get(`${API_BASE_PATH}/api_keys`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .expect(200); expect(body).toBeDefined(); @@ -43,6 +43,8 @@ export default function ({ getService }: FtrProviderContext) { }); describe('POST api_key', function () { + let supertestAdminWithCookieCredentials: SupertestWithRoleScopeType; + const deleteAllApiKeys = async () => { let apiKeys: SecurityApiKey[]; // Delete existing API keys @@ -66,21 +68,24 @@ export default function ({ getService }: FtrProviderContext) { }; before(async () => { await deleteAllApiKeys(); - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('developer'); + supertestAdminWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope( + 'admin', + { + useCookieHeader: true, + withInternalHeaders: true, + } + ); }); after(async () => { await deleteAllApiKeys(); - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); }); it('can create a key that expires', async () => { const createBody = { name: 'test-api-key-001', expiration: '60d', }; - const { body } = await supertestWithoutAuth + const { body } = await supertestAdminWithCookieCredentials .post(`${API_BASE_PATH}/api_key`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.cookieHeader) .send(createBody) .expect(200); @@ -90,10 +95,8 @@ export default function ({ getService }: FtrProviderContext) { const createBody = { name: 'test-api-key-002', }; - const { body } = await supertestWithoutAuth + const { body } = await supertestAdminWithCookieCredentials .post(`${API_BASE_PATH}/api_key`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.cookieHeader) .send(createBody) .expect(200); @@ -103,11 +106,9 @@ export default function ({ getService }: FtrProviderContext) { const createBody = { name: 'test-api-key-003', }; - const { body } = await supertestWithoutAuth + const { body } = await supertestAdminWithCookieCredentials .post(`${API_BASE_PATH}/api_key`) - .set(svlCommonApi.getInternalRequestHeader()) .send(createBody) - .set(roleAuthc.cookieHeader) .expect(200); expect(body).toMatchObject({ From d89d46832228931aaf90238e491238313e7bfa37 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Fri, 13 Sep 2024 17:30:48 +0200 Subject: [PATCH 10/18] update more platform_security tests --- .../common/platform_security/feature_check.ts | 26 ++--- .../common/platform_security/misc.ts | 51 +++++----- .../common/platform_security/role_mappings.ts | 47 +++++---- .../common/platform_security/sessions.ts | 50 +++++----- .../common/platform_security/user_profiles.ts | 32 +++--- .../common/platform_security/users.ts | 99 +++++++++---------- .../common/platform_security/views.ts | 96 +++++++----------- 7 files changed, 182 insertions(+), 219 deletions(-) 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 cb925947473f..97922157dab3 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 @@ -5,27 +5,29 @@ * 2.0. */ +import { SupertestWithRoleScopeType } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services'; import { FtrProviderContext } from '../../../ftr_provider_context'; -import { RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { const svlCommonApi = getService('svlCommonApi'); - const svlUserManager = getService('svlUserManager'); - const supertestWithoutAuth = getService('supertestWithoutAuth'); - let roleAuthc: RoleCredentials; + const roleScopedSupertest = getService('roleScopedSupertest'); + let supertestAdminWithCookieCredentials: SupertestWithRoleScopeType; describe('security/features', function () { before(async () => { - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin'); - }); - after(async () => { - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); + supertestAdminWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope( + 'admin', + { + useCookieHeader: true, + withInternalHeaders: true, + } + ); }); + it('route access disabled', async () => { - const { body, status } = await supertestWithoutAuth - .get('/internal/security/_check_security_features') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { body, status } = await supertestAdminWithCookieCredentials.get( + '/internal/security/_check_security_features' + ); 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 c289720f93d2..46615e3c7a0d 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 @@ -6,64 +6,61 @@ */ import expect from 'expect'; +import { SupertestWithRoleScopeType } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services'; import { FtrProviderContext } from '../../../ftr_provider_context'; -import { RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { const svlCommonApi = getService('svlCommonApi'); - const svlUserManager = getService('svlUserManager'); - const supertestWithoutAuth = getService('supertestWithoutAuth'); - let roleAuthc: RoleCredentials; + const roleScopedSupertest = getService('roleScopedSupertest'); + let supertestAdminWithCookieCredentials: SupertestWithRoleScopeType; describe('security/misc', function () { before(async () => { - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin'); - }); - after(async () => { - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); + supertestAdminWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope( + 'admin', + { + useCookieHeader: true, + withInternalHeaders: true, + } + ); }); + describe('route access', () => { describe('disabled', () => { it('get index fields', async () => { - const { body, status } = await supertestWithoutAuth + const { body, status } = await supertestAdminWithCookieCredentials .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 supertestWithoutAuth - .post('/internal/security/deprecations/kibana_user_role/_fix_users') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { body, status } = await supertestAdminWithCookieCredentials.post( + '/internal/security/deprecations/kibana_user_role/_fix_users' + ); svlCommonApi.assertApiNotFound(body, status); }); 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(roleAuthc.apiKeyHeader); + const { body, status } = await supertestAdminWithCookieCredentials.post( + '/internal/security/deprecations/kibana_user_role/_fix_role_mappings' + ); svlCommonApi.assertApiNotFound(body, status); }); it('get security checkup state', async () => { - const { body, status } = await supertestWithoutAuth - .get('/internal/security/security_checkup/state') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { body, status } = await supertestAdminWithCookieCredentials.get( + '/internal/security/security_checkup/state' + ); svlCommonApi.assertApiNotFound(body, status); }); }); describe('internal', () => { it('get record auth type', async () => { - const { status } = await supertestWithoutAuth - .post('/internal/security/analytics/_record_auth_type') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { status } = await supertestAdminWithCookieCredentials.post( + '/internal/security/analytics/_record_auth_type' + ); expect(status).toBe(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 3fdabba673ff..b5b51dcef569 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 @@ -5,54 +5,53 @@ * 2.0. */ +import { SupertestWithRoleScopeType } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services'; import { FtrProviderContext } from '../../../ftr_provider_context'; -import { RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { const svlCommonApi = getService('svlCommonApi'); - const svlUserManager = getService('svlUserManager'); - const supertestWithoutAuth = getService('supertestWithoutAuth'); - let roleAuthc: RoleCredentials; + const roleScopedSupertest = getService('roleScopedSupertest'); + let supertestAdminWithCookieCredentials: SupertestWithRoleScopeType; describe('security/role_mappings', function () { before(async () => { - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin'); - }); - after(async () => { - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); + supertestAdminWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope( + 'admin', + { + useCookieHeader: true, + withInternalHeaders: true, + } + ); }); + describe('route access', () => { describe('disabled', () => { it('create/update roleAuthc mapping', async () => { - const { body, status } = await supertestWithoutAuth - .post('/internal/security/role_mapping/test') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { body, status } = await supertestAdminWithCookieCredentials.post( + '/internal/security/role_mapping/test' + ); svlCommonApi.assertApiNotFound(body, status); }); it('get roleAuthc mapping', async () => { - const { body, status } = await supertestWithoutAuth - .get('/internal/security/role_mapping/test') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { body, status } = await supertestAdminWithCookieCredentials.get( + '/internal/security/role_mapping/test' + ); svlCommonApi.assertApiNotFound(body, status); }); it('get all roleAuthc mappings', async () => { - const { body, status } = await supertestWithoutAuth - .get('/internal/security/role_mapping') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { body, status } = await supertestAdminWithCookieCredentials.get( + '/internal/security/role_mapping' + ); svlCommonApi.assertApiNotFound(body, status); }); 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(roleAuthc.apiKeyHeader); + const { body, status } = await supertestAdminWithCookieCredentials.delete( + '/internal/security/role_mapping/test' + ); 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 386d1b3cb770..c76ccb81f8ce 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 @@ -6,28 +6,31 @@ */ import expect from 'expect'; +import { SupertestWithRoleScopeType } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services'; import { FtrProviderContext } from '../../../ftr_provider_context'; -import { RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { const svlCommonApi = getService('svlCommonApi'); - const svlUserManager = getService('svlUserManager'); - const supertestWithoutAuth = getService('supertestWithoutAuth'); - let roleAuthc: RoleCredentials; + const samlAuth = getService('samlAuth'); + const roleScopedSupertest = getService('roleScopedSupertest'); + let supertestViewerWithCookieCredentials: SupertestWithRoleScopeType; + describe('security/sessions', function () { before(async () => { - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('viewer'); - }); - after(async () => { - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); + supertestViewerWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope( + 'viewer', + { + useCookieHeader: true, + } + ); }); + describe('route access', () => { describe('disabled', () => { it('invalidate', async () => { - const { body, status } = await supertestWithoutAuth + const { body, status } = await supertestViewerWithCookieCredentials .post('/api/security/session/_invalidate') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) + .set(samlAuth.getInternalRequestHeader()) .send({ match: 'all' }); svlCommonApi.assertApiNotFound(body, status); }); @@ -38,11 +41,9 @@ export default function ({ getService }: FtrProviderContext) { let body: any; let status: number; - ({ body, status } = await supertestWithoutAuth + ({ body, status } = await supertestViewerWithCookieCredentials .get('/internal/security/session') - .set(roleAuthc.apiKeyHeader) - .set(svlCommonApi.getCommonRequestHeader())); - + .set(samlAuth.getCommonRequestHeader())); // expect a rejection because we're not using the internal header expect(body).toEqual({ statusCode: 400, @@ -53,22 +54,20 @@ export default function ({ getService }: FtrProviderContext) { }); expect(status).toBe(400); - ({ body, status } = await supertestWithoutAuth + ({ body, status } = await supertestViewerWithCookieCredentials .get('/internal/security/session') - .set(roleAuthc.apiKeyHeader) - .set(svlCommonApi.getInternalRequestHeader())); - // expect 204 because there is no session - expect(status).toBe(204); + .set(samlAuth.getInternalRequestHeader())); + // expect 200 because there is a session + expect(status).toBe(200); }); it('extend', async () => { let body: any; let status: number; - ({ body, status } = await supertestWithoutAuth + ({ body, status } = await supertestViewerWithCookieCredentials .post('/internal/security/session') - .set(roleAuthc.apiKeyHeader) - .set(svlCommonApi.getCommonRequestHeader())); + .set(samlAuth.getCommonRequestHeader())); // expect a rejection because we're not using the internal header expect(body).toEqual({ statusCode: 400, @@ -79,10 +78,9 @@ export default function ({ getService }: FtrProviderContext) { }); expect(status).toBe(400); - ({ body, status } = await supertestWithoutAuth + ({ body, status } = await supertestViewerWithCookieCredentials .post('/internal/security/session') - .set(roleAuthc.apiKeyHeader) - .set(svlCommonApi.getInternalRequestHeader())); + .set(samlAuth.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 0217eb39017c..481e5d9394d2 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 @@ -7,23 +7,25 @@ import expect from 'expect'; import { kibanaTestUser } from '@kbn/test'; +import { SupertestWithRoleScopeType } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services'; 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'); - let roleAuthc: RoleCredentials; + const roleScopedSupertest = getService('roleScopedSupertest'); + let supertestViewerWithCookieCredentials: SupertestWithRoleScopeType; describe('security/user_profiles', function () { before(async () => { - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('viewer'); - }); - after(async () => { - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); + supertestViewerWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope( + 'viewer', + { + useCookieHeader: true, + withInternalHeaders: true, + } + ); }); + describe('route access', () => { describe('internal', () => { // When we run tests on MKI, SAML realm is configured differently, and we cannot handcraft SAML responses to @@ -31,29 +33,23 @@ export default function ({ getService }: FtrProviderContext) { this.tags(['skipMKI']); it('update', async () => { - const { status } = await supertestWithoutAuth + const { status } = await supertestViewerWithCookieCredentials .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); }); it('get current', async () => { - const { status } = await supertestWithoutAuth + const { status } = await supertestViewerWithCookieCredentials .get(`/internal/security/user_profile`) - .set(roleAuthc.apiKeyHeader) - .set(svlCommonApi.getInternalRequestHeader()) .set(await samlTools.login(kibanaTestUser.username)); expect(status).not.toBe(404); }); it('bulk get', async () => { - const { status } = await supertestWithoutAuth + const { status } = await supertestViewerWithCookieCredentials .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 a94fc609ea49..58d8e1b6eee9 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,77 +6,77 @@ */ import expect from 'expect'; -import { RoleCredentials } from '../../../../shared/services'; +import { SupertestWithRoleScopeType } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services'; import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { - const svlCommonApi = getService('svlCommonApi'); - const svlUserManager = getService('svlUserManager'); + const samlAuth = getService('samlAuth'); const supertestWithoutAuth = getService('supertestWithoutAuth'); - let roleAuthc: RoleCredentials; + const svlCommonApi = getService('svlCommonApi'); + const roleScopedSupertest = getService('roleScopedSupertest'); + let supertestAdminWithCookieCredentials: SupertestWithRoleScopeType; describe('security/users', function () { before(async () => { - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin'); - }); - after(async () => { - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); + supertestAdminWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope( + 'admin', + { + useCookieHeader: true, + withInternalHeaders: true, + } + ); }); + describe('route access', () => { // ToDo: uncomment when we disable user APIs describe.skip('disabled', () => { it('get', async () => { - const { body, status } = await supertestWithoutAuth - .get('/internal/security/users/elastic') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { body, status } = await supertestAdminWithCookieCredentials.get( + '/internal/security/users/elastic' + ); svlCommonApi.assertApiNotFound(body, status); }); it('get all', async () => { - const { body, status } = await supertestWithoutAuth - .get('/internal/security/users') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { body, status } = await supertestAdminWithCookieCredentials.get( + '/internal/security/users' + ); svlCommonApi.assertApiNotFound(body, status); }); it('create/update', async () => { const { body, status } = await supertestWithoutAuth .post(`/internal/security/users/some_testuser`) - .set(svlCommonApi.getInternalRequestHeader()) + .set(samlAuth.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); + const { body, status } = await supertestAdminWithCookieCredentials.delete( + `/internal/security/users/elastic` + ); svlCommonApi.assertApiNotFound(body, status); }); it('disable', async () => { - const { body, status } = await supertestWithoutAuth - .post(`/internal/security/users/elastic/_disable`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { body, status } = await supertestAdminWithCookieCredentials.post( + `/internal/security/users/elastic/_disable` + ); svlCommonApi.assertApiNotFound(body, status); }); it('enable', async () => { - const { body, status } = await supertestWithoutAuth - .post(`/internal/security/users/elastic/_enable`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { body, status } = await supertestAdminWithCookieCredentials.post( + `/internal/security/users/elastic/_enable` + ); svlCommonApi.assertApiNotFound(body, status); }); it('set password', async () => { const { body, status } = await supertestWithoutAuth .post(`/internal/security/users/{username}/password`) - .set(svlCommonApi.getInternalRequestHeader()) + .set(samlAuth.getInternalRequestHeader()) .send({ password: 'old_pw', newPassword: 'new_pw', @@ -88,57 +88,52 @@ export default function ({ getService }: FtrProviderContext) { // ToDo: remove when we disable user APIs describe('internal', () => { it('get', async () => { - const { status } = await supertestWithoutAuth - .get('/internal/security/users/elastic') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { status } = await supertestAdminWithCookieCredentials.get( + '/internal/security/users/elastic' + ); expect(status).not.toBe(404); }); it('get all', async () => { - const { status } = await supertestWithoutAuth - .get('/internal/security/users') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { status } = await supertestAdminWithCookieCredentials.get( + '/internal/security/users' + ); expect(status).not.toBe(404); }); it('create/update', async () => { const { status } = await supertestWithoutAuth .post(`/internal/security/users/some_testuser`) - .set(svlCommonApi.getInternalRequestHeader()) + .set(samlAuth.getInternalRequestHeader()) .send({ username: 'some_testuser', password: 'testpassword', roles: [] }); expect(status).not.toBe(404); }); it('delete', async () => { - const { status } = await supertestWithoutAuth - .delete(`/internal/security/users/elastic`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { status } = await supertestAdminWithCookieCredentials.delete( + `/internal/security/users/elastic` + ); expect(status).not.toBe(404); }); it('disable', async () => { - const { status } = await supertestWithoutAuth - .post(`/internal/security/users/elastic/_disable`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { status } = await supertestAdminWithCookieCredentials.post( + `/internal/security/users/elastic/_disable` + ); expect(status).not.toBe(404); }); it('enable', async () => { - const { status } = await supertestWithoutAuth - .post(`/internal/security/users/elastic/_enable`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { status } = await supertestAdminWithCookieCredentials.post( + `/internal/security/users/elastic/_enable` + ); expect(status).not.toBe(404); }); it('set password', async () => { const { status } = await supertestWithoutAuth .post(`/internal/security/users/{username}/password`) - .set(svlCommonApi.getInternalRequestHeader()) + .set(samlAuth.getInternalRequestHeader()) .send({ password: 'old_pw', newPassword: 'new_pw', 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 76cf863034d0..5b35e46803b2 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,131 +6,107 @@ */ import expect from 'expect'; -import { InternalRequestHeader, RoleCredentials } from '../../../../shared/services'; +import { SupertestWithRoleScopeType } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services'; import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const svlCommonApi = getService('svlCommonApi'); - const svlUserManager = getService('svlUserManager'); - const supertestWithoutAuth = getService('supertestWithoutAuth'); - let roleAuthc: RoleCredentials; - let internalReqHeader: InternalRequestHeader; + const roleScopedSupertest = getService('roleScopedSupertest'); + let supertestAdminWithCookieCredentials: SupertestWithRoleScopeType; + let supertestAdminWithApiKey: SupertestWithRoleScopeType; describe('security/views', function () { before(async () => { - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin'); - internalReqHeader = svlCommonApi.getInternalRequestHeader(); + supertestAdminWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope( + 'admin', + { + useCookieHeader: true, + withInternalHeaders: true, + } + ); + supertestAdminWithApiKey = await roleScopedSupertest.getSupertestWithRoleScope('admin', { + withInternalHeaders: true, + }); }); after(async () => { - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); + await supertestAdminWithApiKey.destroy(); }); describe('route access', () => { describe('disabled', () => { // ToDo: unskip these when we disable login routes xit('login', async () => { - const { body, status } = await supertestWithoutAuth - .get('/login') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { body, status } = await supertestAdminWithApiKey.get('/login'); 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); + const { body, status } = await supertestAdminWithCookieCredentials.get( + '/internal/security/login_state' + ); svlCommonApi.assertApiNotFound(body, status); }); it('access agreement', async () => { - const { body, status } = await supertestWithoutAuth - .get('/security/access_agreement') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { body, status } = await supertestAdminWithApiKey.get('/security/access_agreement'); svlCommonApi.assertApiNotFound(body, status); }); it('get access agreement state', async () => { - const { body, status } = await supertestWithoutAuth - .get('/internal/security/access_agreement/state') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { body, status } = await supertestAdminWithCookieCredentials.get( + '/internal/security/access_agreement/state' + ); svlCommonApi.assertApiNotFound(body, status); }); }); describe('public', () => { it('login', async () => { - const { status } = await supertestWithoutAuth - .get('/login') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { status } = await supertestAdminWithApiKey.get('/login'); expect(status).toBe(302); }); it('get login state', async () => { - const { status } = await supertestWithoutAuth - .get('/internal/security/login_state') - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader); + const { status } = await supertestAdminWithCookieCredentials.get( + '/internal/security/login_state' + ); expect(status).toBe(200); }); it('capture URL', async () => { - const { status } = await supertestWithoutAuth - .get('/internal/security/capture-url') - .set(internalReqHeader) - .set(roleAuthc.apiKeyHeader); + const { status } = await supertestAdminWithCookieCredentials.get( + '/internal/security/capture-url' + ); expect(status).toBe(200); }); it('space selector', async () => { - const { status } = await supertestWithoutAuth - .get('/spaces/space_selector') - .set(internalReqHeader) - .set(roleAuthc.apiKeyHeader); + const { status } = await supertestAdminWithApiKey.get('/spaces/space_selector'); expect(status).toBe(200); }); it('enter space', async () => { - const { status } = await supertestWithoutAuth - .get('/spaces/enter') - .set(internalReqHeader) - .set(roleAuthc.apiKeyHeader); + const { status } = await supertestAdminWithApiKey.get('/spaces/enter'); expect(status).toBe(302); }); it('account', async () => { - const { status } = await supertestWithoutAuth - .get('/security/account') - .set(internalReqHeader) - .set(roleAuthc.apiKeyHeader); + const { status } = await supertestAdminWithApiKey.get('/security/account'); expect(status).toBe(200); }); it('logged out', async () => { - const { status } = await supertestWithoutAuth - .get('/security/logged_out') - .set(internalReqHeader) - .set(roleAuthc.apiKeyHeader); + const { status } = await supertestAdminWithApiKey.get('/security/logged_out'); expect(status).toBe(200); }); it('logout', async () => { - const { status } = await supertestWithoutAuth - .get('/logout') - .set(internalReqHeader) - .set(roleAuthc.apiKeyHeader); + const { status } = await supertestAdminWithApiKey.get('/logout'); expect(status).toBe(200); }); it('overwritten session', async () => { - const { status } = await supertestWithoutAuth - .get('/security/overwritten_session') - .set(internalReqHeader) - .set(roleAuthc.apiKeyHeader); + const { status } = await supertestAdminWithApiKey.get('/security/overwritten_session'); expect(status).toBe(200); }); }); From fe64f44a74370d0e54faa988470317b5cc41fafb Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Mon, 16 Sep 2024 10:31:41 +0200 Subject: [PATCH 11/18] convert more tests to use cookie credentials --- .../search/search_indices/indices.ts | 41 +++++----- .../search/search_indices/status.ts | 39 ++++------ .../search/serverless_search/api_key.ts | 12 ++- .../search/serverless_search/connectors.ts | 24 +++--- .../search/serverless_search/indices.ts | 32 ++++---- .../cloud_security_posture/telemetry.ts | 77 ++++++++----------- 6 files changed, 99 insertions(+), 126 deletions(-) diff --git a/x-pack/test_serverless/api_integration/test_suites/search/search_indices/indices.ts b/x-pack/test_serverless/api_integration/test_suites/search/search_indices/indices.ts index 4ece36301855..9dae19886f3c 100644 --- a/x-pack/test_serverless/api_integration/test_suites/search/search_indices/indices.ts +++ b/x-pack/test_serverless/api_integration/test_suites/search/search_indices/indices.ts @@ -6,31 +6,30 @@ */ import expect from 'expect'; -import { InternalRequestHeader, RoleCredentials } from '../../../../shared/services'; +import { SupertestWithRoleScopeType } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services'; import { FtrProviderContext } from '../../../ftr_provider_context'; const INTERNAL_API_BASE_PATH = '/internal/search_indices'; export default function ({ getService }: FtrProviderContext) { const log = getService('log'); - const svlCommonApi = getService('svlCommonApi'); - const svlUserManager = getService('svlUserManager'); const esDeleteAllIndices = getService('esDeleteAllIndices'); - const supertestWithoutAuth = getService('supertestWithoutAuth'); - let roleAuthc: RoleCredentials; - let internalReqHeader: InternalRequestHeader; + const roleScopedSupertest = getService('roleScopedSupertest'); + let supertestDeveloperWithCookieCredentials: SupertestWithRoleScopeType; + let supertestViewerWithCookieCredentials: SupertestWithRoleScopeType; describe('search_indices Indices APIs', function () { - before(function () { - internalReqHeader = svlCommonApi.getInternalRequestHeader(); - }); describe('create index', function () { const createIndexName = 'a-test-index'; describe('developer', function () { before(async () => { - // get auth header for Viewer role - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('developer'); + supertestDeveloperWithCookieCredentials = + await roleScopedSupertest.getSupertestWithRoleScope('developer', { + useCookieHeader: true, + withInternalHeaders: true, + }); }); + after(async () => { // Cleanup index created for testing purposes try { @@ -39,14 +38,11 @@ export default function ({ getService }: FtrProviderContext) { log.debug('[Cleanup error] Error deleting index'); throw err; } - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); }); it('can create a new index', async () => { - const { body } = await supertestWithoutAuth + const { body } = await supertestDeveloperWithCookieCredentials .post(`${INTERNAL_API_BASE_PATH}/indices/create`) - .set(internalReqHeader) - .set(roleAuthc.apiKeyHeader) .send({ indexName: createIndexName, }) @@ -55,10 +51,8 @@ export default function ({ getService }: FtrProviderContext) { expect(body?.index).toBe(createIndexName); }); it('gives a conflict error if the index exists already', async () => { - await supertestWithoutAuth + await supertestDeveloperWithCookieCredentials .post(`${INTERNAL_API_BASE_PATH}/indices/create`) - .set(internalReqHeader) - .set(roleAuthc.apiKeyHeader) .send({ indexName: createIndexName, }) @@ -67,15 +61,16 @@ export default function ({ getService }: FtrProviderContext) { }); describe('viewer', function () { before(async () => { - // get auth header for Viewer role - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('viewer'); + supertestViewerWithCookieCredentials = + await roleScopedSupertest.getSupertestWithRoleScope('viwer', { + useCookieHeader: true, + withInternalHeaders: true, + }); }); it('cannot create a new index', async () => { - await supertestWithoutAuth + await supertestViewerWithCookieCredentials .post(`${INTERNAL_API_BASE_PATH}/indices/create`) - .set(internalReqHeader) - .set(roleAuthc.apiKeyHeader) .send({ indexName: 'a-new-index', }) diff --git a/x-pack/test_serverless/api_integration/test_suites/search/search_indices/status.ts b/x-pack/test_serverless/api_integration/test_suites/search/search_indices/status.ts index b9e9fedbb039..0bdf328dbc2a 100644 --- a/x-pack/test_serverless/api_integration/test_suites/search/search_indices/status.ts +++ b/x-pack/test_serverless/api_integration/test_suites/search/search_indices/status.ts @@ -6,25 +6,26 @@ */ import expect from 'expect'; +import { SupertestWithRoleScopeType } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services'; import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { - const svlCommonApi = getService('svlCommonApi'); - const svlUserManager = getService('svlUserManager'); - const supertestWithoutAuth = getService('supertestWithoutAuth'); - let credentials: { Cookie: string }; + const roleScopedSupertest = getService('roleScopedSupertest'); + let supertestDeveloperWithCookieCredentials: SupertestWithRoleScopeType; + let supertestViewerWithCookieCredentials: SupertestWithRoleScopeType; describe('search_indices Status APIs', function () { describe('indices status', function () { before(async () => { - // get auth header for Viewer role - credentials = await svlUserManager.getM2MApiCredentialsWithRoleScope('developer'); + supertestDeveloperWithCookieCredentials = + await roleScopedSupertest.getSupertestWithRoleScope('developer', { + useCookieHeader: true, + withInternalHeaders: true, + }); }); it('returns list of index names', async () => { - const { body } = await supertestWithoutAuth + const { body } = await supertestDeveloperWithCookieCredentials .get('/internal/search_indices/status') - .set(svlCommonApi.getInternalRequestHeader()) - .set(credentials) .expect(200); expect(body.indexNames).toBeDefined(); @@ -34,16 +35,9 @@ export default function ({ getService }: FtrProviderContext) { describe('user privileges', function () { // GET /internal/search_indices/start_privileges describe('developer', function () { - before(async () => { - // get auth header for Viewer role - credentials = await svlUserManager.getM2MApiCredentialsWithRoleScope('developer'); - }); - it('returns expected privileges', async () => { - const { body } = await supertestWithoutAuth + const { body } = await supertestDeveloperWithCookieCredentials .get('/internal/search_indices/start_privileges') - .set(svlCommonApi.getInternalRequestHeader()) - .set(credentials) .expect(200); expect(body).toEqual({ @@ -56,15 +50,16 @@ export default function ({ getService }: FtrProviderContext) { }); describe('viewer', function () { before(async () => { - // get auth header for Viewer role - credentials = await svlUserManager.getM2MApiCredentialsWithRoleScope('viewer'); + supertestViewerWithCookieCredentials = + await roleScopedSupertest.getSupertestWithRoleScope('viwer', { + useCookieHeader: true, + withInternalHeaders: true, + }); }); it('returns expected privileges', async () => { - const { body } = await supertestWithoutAuth + const { body } = await supertestViewerWithCookieCredentials .get('/internal/search_indices/start_privileges') - .set(svlCommonApi.getInternalRequestHeader()) - .set(credentials) .expect(200); expect(body).toEqual({ diff --git a/x-pack/test_serverless/api_integration/test_suites/search/serverless_search/api_key.ts b/x-pack/test_serverless/api_integration/test_suites/search/serverless_search/api_key.ts index 3e43093c6d09..9c8cca9900c9 100644 --- a/x-pack/test_serverless/api_integration/test_suites/search/serverless_search/api_key.ts +++ b/x-pack/test_serverless/api_integration/test_suites/search/serverless_search/api_key.ts @@ -17,22 +17,20 @@ export default function ({ getService }: FtrProviderContext) { const roleScopedSupertest = getService('roleScopedSupertest'); const es = getService('es'); const log = getService('log'); - let supertestDeveloperWithApiKey: SupertestWithRoleScopeType; + let supertestDeveloperWithCookieCredentials: SupertestWithRoleScopeType; describe('API Key routes', function () { describe('GET api_keys', function () { before(async () => { - supertestDeveloperWithApiKey = await roleScopedSupertest.getSupertestWithRoleScope( - 'developer', - { + supertestDeveloperWithCookieCredentials = + await roleScopedSupertest.getSupertestWithRoleScope('developer', { useCookieHeader: true, withInternalHeaders: true, - } - ); + }); }); it('return apiKeys', async () => { - const { body } = await supertestDeveloperWithApiKey + const { body } = await supertestDeveloperWithCookieCredentials .get(`${API_BASE_PATH}/api_keys`) .expect(200); diff --git a/x-pack/test_serverless/api_integration/test_suites/search/serverless_search/connectors.ts b/x-pack/test_serverless/api_integration/test_suites/search/serverless_search/connectors.ts index fbf5810cec55..819500aadf71 100644 --- a/x-pack/test_serverless/api_integration/test_suites/search/serverless_search/connectors.ts +++ b/x-pack/test_serverless/api_integration/test_suites/search/serverless_search/connectors.ts @@ -6,30 +6,30 @@ */ import expect from 'expect'; -import { RoleCredentials } from '../../../../shared/services'; +import { SupertestWithRoleScope } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services/role_scoped_supertest'; import { FtrProviderContext } from '../../../ftr_provider_context'; const API_BASE_PATH = '/internal/serverless_search'; export default function ({ getService }: FtrProviderContext) { - const svlCommonApi = getService('svlCommonApi'); - const svlUserManager = getService('svlUserManager'); - const supertestWithoutAuth = getService('supertestWithoutAuth'); - let roleAuthc: RoleCredentials; + const roleScopedSupertest = getService('roleScopedSupertest'); + let supertestViewerWithCookieCredentials: SupertestWithRoleScope; describe('Connectors routes', function () { describe('GET connectors', function () { before(async () => { - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('viewer'); - }); - after(async () => { - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); + supertestViewerWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope( + 'viewer', + { + useCookieHeader: true, + withInternalHeaders: true, + } + ); }); + it('returns list of connectors', async () => { - const { body } = await supertestWithoutAuth + const { body } = await supertestViewerWithCookieCredentials .get(`${API_BASE_PATH}/connectors`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .expect(200); expect(body.connectors).toBeDefined(); diff --git a/x-pack/test_serverless/api_integration/test_suites/search/serverless_search/indices.ts b/x-pack/test_serverless/api_integration/test_suites/search/serverless_search/indices.ts index b5138e70a8c3..35c61f354892 100644 --- a/x-pack/test_serverless/api_integration/test_suites/search/serverless_search/indices.ts +++ b/x-pack/test_serverless/api_integration/test_suites/search/serverless_search/indices.ts @@ -6,47 +6,43 @@ */ import expect from 'expect'; -import { RoleCredentials } from '../../../../shared/services'; +import { SupertestWithRoleScope } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services/role_scoped_supertest'; import { FtrProviderContext } from '../../../ftr_provider_context'; const API_BASE_PATH = '/internal/serverless_search'; export default function ({ getService }: FtrProviderContext) { - const svlCommonApi = getService('svlCommonApi'); - const supertestWithoutAuth = getService('supertestWithoutAuth'); - const svlUserManager = getService('svlUserManager'); - let roleAuthc: RoleCredentials; + const roleScopedSupertest = getService('roleScopedSupertest'); + let supertestViewerWithCookieCredentials: SupertestWithRoleScope; describe('Indices routes', function () { describe('GET indices', function () { before(async () => { - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('viewer'); - }); - after(async () => { - await svlUserManager.invalidateM2mApiKeyWithRoleScope(roleAuthc); + supertestViewerWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope( + 'viewer', + { + useCookieHeader: true, + withInternalHeaders: true, + } + ); }); + it('has route', async () => { - const { body } = await supertestWithoutAuth + const { body } = await supertestViewerWithCookieCredentials .get(`${API_BASE_PATH}/indices`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .expect(200); expect(body).toBeDefined(); }); it('accepts search_query', async () => { - await supertestWithoutAuth + await supertestViewerWithCookieCredentials .get(`${API_BASE_PATH}/indices`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .query({ search_query: 'foo' }) .expect(200); }); it('accepts from & size', async () => { - await supertestWithoutAuth + await supertestViewerWithCookieCredentials .get(`${API_BASE_PATH}/indices`) - .set(svlCommonApi.getInternalRequestHeader()) - .set(roleAuthc.apiKeyHeader) .query({ from: 0, size: 10 }) .expect(200); }); diff --git a/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/telemetry.ts b/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/telemetry.ts index 837a9a7e6ba9..62cf85b47d99 100644 --- a/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/telemetry.ts +++ b/x-pack/test_serverless/api_integration/test_suites/security/cloud_security_posture/telemetry.ts @@ -6,13 +6,13 @@ */ import expect from '@kbn/expect'; -import type { Agent as SuperTestAgent } from 'supertest'; import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; import { data as telemetryMockData, MockTelemetryFindings, } from '@kbn/test-suites-xpack/cloud_security_posture_api/telemetry/data'; import { createPackagePolicy } from '@kbn/test-suites-xpack/api_integration/apis/cloud_security_posture/helper'; +import { SupertestWithRoleScopeType } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services'; import type { FtrProviderContext } from '../../../ftr_provider_context'; import { RoleCredentials } from '../../../../shared/services'; @@ -27,32 +27,12 @@ export default function ({ getService }: FtrProviderContext) { const supertestWithoutAuth = getService('supertestWithoutAuth'); const svlCommonApi = getService('svlCommonApi'); const svlUserManager = getService('svlUserManager'); + const roleScopedSupertest = getService('roleScopedSupertest'); + let supertestAdminWithCookieCredentials: SupertestWithRoleScopeType; let roleAuthc: RoleCredentials; let internalRequestHeader: { 'x-elastic-internal-origin': string; 'kbn-xsrf': string }; - /** - * required before indexing findings - */ - const waitForPluginInitialized = ( - supertestWithoutAuthParam: SuperTestAgent, - internalRequestHeaderParam: { 'x-elastic-internal-origin': string; 'kbn-xsrf': string }, - roleAuthcParam: RoleCredentials - ): Promise => - retry.try(async () => { - log.debug('Check CSP plugin is initialized'); - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin'); - internalRequestHeader = svlCommonApi.getInternalRequestHeader(); - const response = await supertestWithoutAuthParam - .get('/internal/cloud_security_posture/status?check=init') - .set(ELASTIC_HTTP_VERSION_HEADER, '1') - .set(internalRequestHeaderParam) - .set(roleAuthcParam.apiKeyHeader) - .expect(200); - expect(response.body).to.eql({ isPluginInitialized: true }); - log.debug('CSP plugin is initialized'); - }); - const index = { remove: () => es.deleteByQuery({ @@ -79,6 +59,14 @@ export default function ({ getService }: FtrProviderContext) { let agentPolicyId: string; before(async () => { + supertestAdminWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope( + 'admin', + { + useCookieHeader: true, + withInternalHeaders: true, + withCustomHeaders: { [ELASTIC_HTTP_VERSION_HEADER]: '2' }, + } + ); roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('admin'); internalRequestHeader = svlCommonApi.getInternalRequestHeader(); await kibanaServer.savedObjects.cleanStandardList(); @@ -106,7 +94,23 @@ export default function ({ getService }: FtrProviderContext) { roleAuthc, internalRequestHeader ); - await waitForPluginInitialized(supertestWithoutAuth, internalRequestHeader, roleAuthc); + + log.debug('Check CSP plugin is initialized'); + await retry.try(async () => { + const supertestAdminWithHttpHeaderV1 = await roleScopedSupertest.getSupertestWithRoleScope( + 'admin', + { + useCookieHeader: true, + withInternalHeaders: true, + withCustomHeaders: { [ELASTIC_HTTP_VERSION_HEADER]: '1' }, + } + ); + const response = await supertestAdminWithHttpHeaderV1 + .get('/internal/cloud_security_posture/status?check=init') + .expect(200); + expect(response.body).to.eql({ isPluginInitialized: true }); + log.debug('CSP plugin is initialized'); + }); }); after(async () => { @@ -124,11 +128,8 @@ export default function ({ getService }: FtrProviderContext) { const { body: [{ stats: apiResponse }], - } = await supertestWithoutAuth + } = await supertestAdminWithCookieCredentials .post(`/internal/telemetry/clusters/_stats`) - .set(ELASTIC_HTTP_VERSION_HEADER, '2') - .set(internalRequestHeader) - .set(roleAuthc.apiKeyHeader) .send({ unencrypted: true, refreshCache: true, @@ -178,11 +179,8 @@ export default function ({ getService }: FtrProviderContext) { const { body: [{ stats: apiResponse }], - } = await supertestWithoutAuth + } = await supertestAdminWithCookieCredentials .post(`/internal/telemetry/clusters/_stats`) - .set(ELASTIC_HTTP_VERSION_HEADER, '2') - .set(internalRequestHeader) - .set(roleAuthc.apiKeyHeader) .send({ unencrypted: true, refreshCache: true, @@ -225,11 +223,8 @@ export default function ({ getService }: FtrProviderContext) { const { body: [{ stats: apiResponse }], - } = await supertestWithoutAuth + } = await supertestAdminWithCookieCredentials .post(`/internal/telemetry/clusters/_stats`) - .set(ELASTIC_HTTP_VERSION_HEADER, '2') - .set(internalRequestHeader) - .set(roleAuthc.apiKeyHeader) .send({ unencrypted: true, refreshCache: true, @@ -303,11 +298,8 @@ export default function ({ getService }: FtrProviderContext) { const { body: [{ stats: apiResponse }], - } = await supertestWithoutAuth + } = await supertestAdminWithCookieCredentials .post(`/internal/telemetry/clusters/_stats`) - .set(ELASTIC_HTTP_VERSION_HEADER, '2') - .set(internalRequestHeader) - .set(roleAuthc.apiKeyHeader) .send({ unencrypted: true, refreshCache: true, @@ -359,11 +351,8 @@ export default function ({ getService }: FtrProviderContext) { const { body: [{ stats: apiResponse }], - } = await supertestWithoutAuth + } = await supertestAdminWithCookieCredentials .post(`/internal/telemetry/clusters/_stats`) - .set(ELASTIC_HTTP_VERSION_HEADER, '2') - .set(internalRequestHeader) - .set(roleAuthc.apiKeyHeader) .send({ unencrypted: true, refreshCache: true, From e7d6c9f763031c4672cb2c34e96ca58b2e52bd40 Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Mon, 16 Sep 2024 10:41:49 +0200 Subject: [PATCH 12/18] update docs --- .../deployment_agnostic/README.md | 14 +++++ x-pack/test_serverless/README.md | 54 +++++++++++++++---- 2 files changed, 57 insertions(+), 11 deletions(-) diff --git a/x-pack/test/api_integration/deployment_agnostic/README.md b/x-pack/test/api_integration/deployment_agnostic/README.md index 8cb1c4f7c334..d855b0d403f5 100644 --- a/x-pack/test/api_integration/deployment_agnostic/README.md +++ b/x-pack/test/api_integration/deployment_agnostic/README.md @@ -97,6 +97,20 @@ export type DeploymentAgnosticFtrProviderContext = GenericFtrProviderContext)` authenticate requests with API key by default +- pass `withCookieHeader: true` to use Cookie header for requests authentication +- don't forget to invalidate API key using `destroy()` on supertest scoped instance in `after` hook + Add test files to `x-pack/test//deployment_agnostic/apis/`: test example diff --git a/x-pack/test_serverless/README.md b/x-pack/test_serverless/README.md index d7bb3d62d552..2ed34ff66d37 100644 --- a/x-pack/test_serverless/README.md +++ b/x-pack/test_serverless/README.md @@ -143,28 +143,60 @@ describe("my test suite", async function() { #### API integration test example +API Authentication in Kibana: Public vs. Internal APIs + +Kibana provides both public and internal APIs, each requiring authentication with the correct privileges. However, the method of testing these APIs varies, depending on how they are untilized by end users. + +- Public APIs: When testing HTTP requests to public APIs, API key-based authentication should be used. It reflect how end user call these APIs. Due to existing restrictions, we utilize `Admin` user credentials to generate API keys for various roles. While the API key permissions are correctly scoped according to the assigned role, the user will internally be recognized as `Admin` during authentication. + +- Internal APIs: Direct HTTP requests to internal APIs are generally not expected. However, for testing purposes, authentication should be performed using the Cookie header. This approach simulates client-side behavior during browser interactions, mirroring how internal APIs are indirectly invoked. + Recommendations: -- in each test file top level `describe` suite should start with `createM2mApiKeyWithRoleScope` call in `before` hook -- don't forget to invalidate api key using `invalidateApiKeyWithRoleScope` in `after` hook -- make api calls using `supertestWithoutAuth` with generated api key header +- use `roleScopedSupertest` service to create supertest instance scoped to specific role and pre-defined request headers +- `roleScopedSupertest.getSupertestWithRoleScope()` authenticate requests with API key by default +- pass `withCookieHeader: true` to use Cookie header for requests authentication +- don't forget to invalidate API key using `destroy()` on supertest scoped instance in `after` hook ``` -describe("my test suite", async function() { +describe("my public APIs test suite", async function() { before(async () => { - roleAuthc = await svlUserManager.createM2mApiKeyWithRoleScope('viewer'); - commonRequestHeader = svlCommonApi.getCommonRequestHeader(); - internalRequestHeader = svlCommonApi.getInternalRequestHeader(); + supertestViewerWithApiKey = + await roleScopedSupertest.getSupertestWithRoleScope('viewer', { + withInternalHeaders: true, + }); }); after(async () => { - await svlUserManager.invalidateApiKeyWithRoleScope(roleAuthc); + await supertestViewerWithApiKey.destroy(); }); it(''test step', async () => { - const { body, status } = await supertestWithoutAuth + const { body, status } = await supertestViewerWithApiKey .delete('/api/spaces/space/default') - .set(commonRequestHeader) - .set(roleAuthc.apiKeyHeader); + ... + }); +}); +``` + +``` +describe("my internal APIs test suite", async function() { + before(async () => { + supertestViewerWithCookieCredentials = + await roleScopedSupertest.getSupertestWithRoleScope('admin', { + withCookieHeader: true, // to avoid generating API key and use Cookie header instead + withInternalHeaders: true, + }); + }); + + after(async () => { + // no need to call '.destroy' since we didn't create API key and Cookie persist for the role within FTR run + }); + + it(''test step', async () => { + await supertestAdminWithCookieCredentials + .post(`/internal/kibana/settings`) + .send({ changes: { [TEST_SETTING]: 500 } }) + .expect(200); ... }); }); From 51b7339e8aeb27fabfdff1b654fb94705f11fa5a Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Mon, 16 Sep 2024 12:36:48 +0200 Subject: [PATCH 13/18] fix role typo --- .../test_suites/search/search_indices/indices.ts | 2 +- .../api_integration/test_suites/search/search_indices/status.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/test_serverless/api_integration/test_suites/search/search_indices/indices.ts b/x-pack/test_serverless/api_integration/test_suites/search/search_indices/indices.ts index 9dae19886f3c..ba75d1334f4f 100644 --- a/x-pack/test_serverless/api_integration/test_suites/search/search_indices/indices.ts +++ b/x-pack/test_serverless/api_integration/test_suites/search/search_indices/indices.ts @@ -62,7 +62,7 @@ export default function ({ getService }: FtrProviderContext) { describe('viewer', function () { before(async () => { supertestViewerWithCookieCredentials = - await roleScopedSupertest.getSupertestWithRoleScope('viwer', { + await roleScopedSupertest.getSupertestWithRoleScope('viewer', { useCookieHeader: true, withInternalHeaders: true, }); diff --git a/x-pack/test_serverless/api_integration/test_suites/search/search_indices/status.ts b/x-pack/test_serverless/api_integration/test_suites/search/search_indices/status.ts index 0bdf328dbc2a..33a2a438016b 100644 --- a/x-pack/test_serverless/api_integration/test_suites/search/search_indices/status.ts +++ b/x-pack/test_serverless/api_integration/test_suites/search/search_indices/status.ts @@ -51,7 +51,7 @@ export default function ({ getService }: FtrProviderContext) { describe('viewer', function () { before(async () => { supertestViewerWithCookieCredentials = - await roleScopedSupertest.getSupertestWithRoleScope('viwer', { + await roleScopedSupertest.getSupertestWithRoleScope('viewer', { useCookieHeader: true, withInternalHeaders: true, }); From e592be974d8ab876d0d2c98e8a308eea25c2640c Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Wed, 18 Sep 2024 12:02:06 +0200 Subject: [PATCH 14/18] Update x-pack/test_serverless/README.md Co-authored-by: Jeramy Soucy --- x-pack/test_serverless/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/test_serverless/README.md b/x-pack/test_serverless/README.md index 2ed34ff66d37..c2e25fe5496d 100644 --- a/x-pack/test_serverless/README.md +++ b/x-pack/test_serverless/README.md @@ -147,7 +147,7 @@ API Authentication in Kibana: Public vs. Internal APIs Kibana provides both public and internal APIs, each requiring authentication with the correct privileges. However, the method of testing these APIs varies, depending on how they are untilized by end users. -- Public APIs: When testing HTTP requests to public APIs, API key-based authentication should be used. It reflect how end user call these APIs. Due to existing restrictions, we utilize `Admin` user credentials to generate API keys for various roles. While the API key permissions are correctly scoped according to the assigned role, the user will internally be recognized as `Admin` during authentication. +- Public APIs: When testing HTTP requests to public APIs, API key-based authentication should be used. It reflects how an end user calls these APIs. Due to existing restrictions, we utilize `Admin` user credentials to generate API keys for various roles. While the API key permissions are correctly scoped according to the assigned role, the user will internally be recognized as `Admin` during authentication. - Internal APIs: Direct HTTP requests to internal APIs are generally not expected. However, for testing purposes, authentication should be performed using the Cookie header. This approach simulates client-side behavior during browser interactions, mirroring how internal APIs are indirectly invoked. From f6d935e63ddfefb7ebd5ea396eefcf71d181354a Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Wed, 18 Sep 2024 12:14:17 +0200 Subject: [PATCH 15/18] rename function to getM2MApiCookieCredentialsWithRoleScope --- .../services/saml_auth/saml_auth_provider.ts | 6 +++--- .../deployment_agnostic/services/role_scoped_supertest.ts | 2 +- .../test_suites/common/platform_security/api_keys.ts | 2 +- .../observability/platform_security/authorization.ts | 2 +- .../observability/synthetics/synthetics_enablement.ts | 4 ++-- .../test_suites/search/platform_security/authorization.ts | 2 +- .../test_suites/security/platform_security/authorization.ts | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/kbn-ftr-common-functional-services/services/saml_auth/saml_auth_provider.ts b/packages/kbn-ftr-common-functional-services/services/saml_auth/saml_auth_provider.ts index 51a0ed992b9e..67d77583af71 100644 --- a/packages/kbn-ftr-common-functional-services/services/saml_auth/saml_auth_provider.ts +++ b/packages/kbn-ftr-common-functional-services/services/saml_auth/saml_auth_provider.ts @@ -66,7 +66,7 @@ export function SamlAuthProvider({ getService }: FtrProviderContext) { async getInteractiveUserSessionCookieWithRoleScope(role: string) { return sessionManager.getInteractiveUserSessionCookieWithRoleScope(role); }, - async getM2MApiCredentialsWithRoleScope(role: string): Promise { + async getM2MApiCookieCredentialsWithRoleScope(role: string): Promise { return sessionManager.getApiCredentialsForRole(role); }, async getEmail(role: string) { @@ -82,7 +82,7 @@ export function SamlAuthProvider({ getService }: FtrProviderContext) { }, async createM2mApiKeyWithRoleScope(role: string): Promise { // Get admin credentials in order to create the API key - const adminCookieHeader = await this.getM2MApiCredentialsWithRoleScope('admin'); + const adminCookieHeader = await this.getM2MApiCookieCredentialsWithRoleScope('admin'); // Get the role descrtiptor for the role let roleDescriptors = {}; @@ -120,7 +120,7 @@ export function SamlAuthProvider({ getService }: FtrProviderContext) { }, async invalidateM2mApiKeyWithRoleScope(roleCredentials: RoleCredentials) { // Get admin credentials in order to invalidate the API key - const adminCookieHeader = await this.getM2MApiCredentialsWithRoleScope('admin'); + const adminCookieHeader = await this.getM2MApiCookieCredentialsWithRoleScope('admin'); const requestBody = { apiKeys: [ diff --git a/x-pack/test/api_integration/deployment_agnostic/services/role_scoped_supertest.ts b/x-pack/test/api_integration/deployment_agnostic/services/role_scoped_supertest.ts index 8f6ee6d53f07..41853cadbe86 100644 --- a/x-pack/test/api_integration/deployment_agnostic/services/role_scoped_supertest.ts +++ b/x-pack/test/api_integration/deployment_agnostic/services/role_scoped_supertest.ts @@ -135,7 +135,7 @@ export function RoleScopedSupertestProvider({ getService }: DeploymentAgnosticFt ) { // if 'useCookieHeader' set to 'true', HTTP requests will be called with cookie Header (like in browser) if (options.useCookieHeader) { - const cookieHeader = await samlAuth.getM2MApiCredentialsWithRoleScope(role); + const cookieHeader = await samlAuth.getM2MApiCookieCredentialsWithRoleScope(role); return new SupertestWithRoleScope(cookieHeader, supertestWithoutAuth, samlAuth, options); } 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 728c7c08ebab..38b9f809d285 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 @@ -17,7 +17,7 @@ export default function ({ getService }: FtrProviderContext) { describe('security/api_keys', function () { before(async () => { - cookieHeader = await samlAuth.getM2MApiCredentialsWithRoleScope('admin'); + cookieHeader = await samlAuth.getM2MApiCookieCredentialsWithRoleScope('admin'); }); describe('route access', () => { diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/platform_security/authorization.ts b/x-pack/test_serverless/api_integration/test_suites/observability/platform_security/authorization.ts index 2e41125e8265..ecf6ddd2c76f 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/platform_security/authorization.ts +++ b/x-pack/test_serverless/api_integration/test_suites/observability/platform_security/authorization.ts @@ -18,7 +18,7 @@ export default function ({ getService }: FtrProviderContext) { before(async () => { // get auth header for Viewer role - adminCredentials = await svlUserManager.getM2MApiCredentialsWithRoleScope('admin'); + adminCredentials = await svlUserManager.getM2MApiCookieCredentialsWithRoleScope('admin'); }); it('composite features', async () => { diff --git a/x-pack/test_serverless/api_integration/test_suites/observability/synthetics/synthetics_enablement.ts b/x-pack/test_serverless/api_integration/test_suites/observability/synthetics/synthetics_enablement.ts index f33e8195c4d9..7e8fcc343db7 100644 --- a/x-pack/test_serverless/api_integration/test_suites/observability/synthetics/synthetics_enablement.ts +++ b/x-pack/test_serverless/api_integration/test_suites/observability/synthetics/synthetics_enablement.ts @@ -69,7 +69,7 @@ export default function ({ getService }: FtrProviderContext) { return supertestWithoutAuth .put(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT) .set(internalRequestHeader as unknown as Record) - .set(await svlUserManager.getM2MApiCredentialsWithRoleScope(role)) + .set(await svlUserManager.getM2MApiCookieCredentialsWithRoleScope(role)) .expect(expectedStatus); } @@ -77,7 +77,7 @@ export default function ({ getService }: FtrProviderContext) { return supertestWithoutAuth .delete(SYNTHETICS_API_URLS.SYNTHETICS_ENABLEMENT) .set(internalRequestHeader as unknown as Record) - .set(await svlUserManager.getM2MApiCredentialsWithRoleScope(role)) + .set(await svlUserManager.getM2MApiCookieCredentialsWithRoleScope(role)) .expect(expectedStatus); } diff --git a/x-pack/test_serverless/api_integration/test_suites/search/platform_security/authorization.ts b/x-pack/test_serverless/api_integration/test_suites/search/platform_security/authorization.ts index 472647f92382..a30b8aca571e 100644 --- a/x-pack/test_serverless/api_integration/test_suites/search/platform_security/authorization.ts +++ b/x-pack/test_serverless/api_integration/test_suites/search/platform_security/authorization.ts @@ -18,7 +18,7 @@ export default function ({ getService }: FtrProviderContext) { before(async () => { // get auth header for Viewer role - adminCredentials = await svlUserManager.getM2MApiCredentialsWithRoleScope('admin'); + adminCredentials = await svlUserManager.getM2MApiCookieCredentialsWithRoleScope('admin'); }); it('composite features', async () => { diff --git a/x-pack/test_serverless/api_integration/test_suites/security/platform_security/authorization.ts b/x-pack/test_serverless/api_integration/test_suites/security/platform_security/authorization.ts index 5cf491188ba9..8852f274aeea 100644 --- a/x-pack/test_serverless/api_integration/test_suites/security/platform_security/authorization.ts +++ b/x-pack/test_serverless/api_integration/test_suites/security/platform_security/authorization.ts @@ -18,7 +18,7 @@ export default function ({ getService }: FtrProviderContext) { before(async () => { // get auth header for Viewer role - adminCredentials = await svlUserManager.getM2MApiCredentialsWithRoleScope('admin'); + adminCredentials = await svlUserManager.getM2MApiCookieCredentialsWithRoleScope('admin'); }); it('composite features', async () => { From 192fea2066ce9271b1a2abd4dbe3430e1d48e55d Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Wed, 18 Sep 2024 12:16:18 +0200 Subject: [PATCH 16/18] Update x-pack/test_serverless/README.md Co-authored-by: Jeramy Soucy --- x-pack/test_serverless/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/test_serverless/README.md b/x-pack/test_serverless/README.md index c2e25fe5496d..661633e9678e 100644 --- a/x-pack/test_serverless/README.md +++ b/x-pack/test_serverless/README.md @@ -152,10 +152,10 @@ Kibana provides both public and internal APIs, each requiring authentication wit - Internal APIs: Direct HTTP requests to internal APIs are generally not expected. However, for testing purposes, authentication should be performed using the Cookie header. This approach simulates client-side behavior during browser interactions, mirroring how internal APIs are indirectly invoked. Recommendations: -- use `roleScopedSupertest` service to create supertest instance scoped to specific role and pre-defined request headers -- `roleScopedSupertest.getSupertestWithRoleScope()` authenticate requests with API key by default -- pass `withCookieHeader: true` to use Cookie header for requests authentication -- don't forget to invalidate API key using `destroy()` on supertest scoped instance in `after` hook +- use `roleScopedSupertest` service to create a supertest instance scoped to a specific role and predefined request headers +- `roleScopedSupertest.getSupertestWithRoleScope()` authenticates requests with an API key by default +- pass `withCookieHeader: true` to use Cookie header for request authentication +- don't forget to invalidate API keys by using `destroy()` on the supertest scoped instance in the `after` hook ``` describe("my public APIs test suite", async function() { From e031d9c974efbe492923c1321aa85860537f20bf Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Wed, 18 Sep 2024 14:02:05 +0200 Subject: [PATCH 17/18] update tests --- .../management/multiple_spaces_enabled.ts | 1 + .../common/platform_security/api_keys.ts | 46 ++++++++----------- .../common/platform_security/views.ts | 33 ++++++------- 3 files changed, 38 insertions(+), 42 deletions(-) diff --git a/x-pack/test_serverless/api_integration/test_suites/common/management/multiple_spaces_enabled.ts b/x-pack/test_serverless/api_integration/test_suites/common/management/multiple_spaces_enabled.ts index 1fed5a62b9db..e5c4053b97e7 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/management/multiple_spaces_enabled.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/management/multiple_spaces_enabled.ts @@ -26,6 +26,7 @@ import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { const svlCommonApi = getService('svlCommonApi'); const roleScopedSupertest = getService('roleScopedSupertest'); + // CRUD operations to become public APIs: https://github.com/elastic/kibana/issues/192153 let supertestAdminWithApiKey: SupertestWithRoleScopeType; let supertestAdminWithCookieCredentials: SupertestWithRoleScopeType; 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 38b9f809d285..d0082d0e85da 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 @@ -6,26 +6,30 @@ */ import expect from 'expect'; -import { CookieCredentials } from '@kbn/ftr-common-functional-services'; import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { let roleMapping: { id: string; name: string; api_key: string; encoded: string }; const samlAuth = getService('samlAuth'); const supertestWithoutAuth = getService('supertestWithoutAuth'); - let cookieHeader: CookieCredentials; + const roleScopedSupertest = getService('roleScopedSupertest'); + let supertestAdminWithCookieCredentials: SupertestWithRoleScopeType; describe('security/api_keys', function () { before(async () => { - cookieHeader = await samlAuth.getM2MApiCookieCredentialsWithRoleScope('admin'); + supertestAdminWithCookieCredentials = await roleScopedSupertest.getSupertestWithRoleScope( + 'admin', + { + useCookieHeader: true, + } + ); }); describe('route access', () => { describe('internal', () => { before(async () => { - const { body, status } = await supertestWithoutAuth + const { body, status } = await supertestAdminWithCookieCredentials .post('/internal/security/api_key') - .set(cookieHeader) .set(samlAuth.getInternalRequestHeader()) .send({ name: 'test', @@ -37,15 +41,13 @@ export default function ({ getService }: FtrProviderContext) { }); after(async function invalidateAll() { - const { body, status } = await supertestWithoutAuth + const { body, status } = await supertestAdminWithCookieCredentials .get('/internal/security/api_key?isAdmin=true') - .set(cookieHeader) .set(samlAuth.getInternalRequestHeader()); if (status === 200) { - await supertestWithoutAuth + await supertestAdminWithCookieCredentials .post('/internal/security/api_key/invalidate') - .set(cookieHeader) .set(samlAuth.getInternalRequestHeader()) .send({ apiKeys: body?.apiKeys, @@ -75,10 +77,9 @@ export default function ({ getService }: FtrProviderContext) { }); expect(status).toBe(401); - ({ body, status } = await supertestWithoutAuth + ({ body, status } = await supertestAdminWithCookieCredentials .post('/internal/security/api_key') .set(samlAuth.getInternalRequestHeader()) - .set(cookieHeader) .send(requestBody)); // expect success because we're using the internal header expect(body).toEqual(expect.objectContaining({ name: 'create_test' })); @@ -94,10 +95,9 @@ export default function ({ getService }: FtrProviderContext) { role_descriptors: {}, }; - ({ body, status } = await supertestWithoutAuth + ({ body, status } = await supertestAdminWithCookieCredentials .put('/internal/security/api_key') .set(samlAuth.getCommonRequestHeader()) - .set(cookieHeader) .send(requestBody)); // expect a rejection because we're not using the internal header expect(body).toEqual({ @@ -109,10 +109,9 @@ export default function ({ getService }: FtrProviderContext) { }); expect(status).toBe(400); - ({ body, status } = await supertestWithoutAuth + ({ body, status } = await supertestAdminWithCookieCredentials .put('/internal/security/api_key') .set(samlAuth.getInternalRequestHeader()) - .set(cookieHeader) .send(requestBody)); // expect success because we're using the internal header expect(body).toEqual(expect.objectContaining({ updated: true })); @@ -123,10 +122,9 @@ export default function ({ getService }: FtrProviderContext) { let body: unknown; let status: number; - ({ body, status } = await supertestWithoutAuth + ({ body, status } = await supertestAdminWithCookieCredentials .get('/internal/security/api_key/_enabled') - .set(samlAuth.getCommonRequestHeader()) - .set(cookieHeader)); + .set(samlAuth.getCommonRequestHeader())); // expect a rejection because we're not using the internal header expect(body).toEqual({ statusCode: 400, @@ -137,9 +135,8 @@ export default function ({ getService }: FtrProviderContext) { }); expect(status).toBe(400); - ({ body, status } = await supertestWithoutAuth + ({ body, status } = await supertestAdminWithCookieCredentials .get('/internal/security/api_key/_enabled') - .set(cookieHeader) .set(samlAuth.getInternalRequestHeader())); // expect success because we're using the internal header expect(body).toEqual({ apiKeysEnabled: true }); @@ -159,10 +156,9 @@ export default function ({ getService }: FtrProviderContext) { isAdmin: true, }; - ({ body, status } = await supertestWithoutAuth + ({ body, status } = await supertestAdminWithCookieCredentials .post('/internal/security/api_key/invalidate') .set(samlAuth.getCommonRequestHeader()) - .set(cookieHeader) .send(requestBody)); // expect a rejection because we're not using the internal header expect(body).toEqual({ @@ -174,10 +170,9 @@ export default function ({ getService }: FtrProviderContext) { }); expect(status).toBe(400); - ({ body, status } = await supertestWithoutAuth + ({ body, status } = await supertestAdminWithCookieCredentials .post('/internal/security/api_key/invalidate') .set(samlAuth.getInternalRequestHeader()) - .set(cookieHeader) .send(requestBody)); // expect success because we're using the internal header expect(body).toEqual({ @@ -202,10 +197,9 @@ export default function ({ getService }: FtrProviderContext) { size: 1, }; - const { body } = await supertestWithoutAuth + const { body } = await supertestAdminWithCookieCredentials .post('/internal/security/api_key/_query') .set(samlAuth.getInternalRequestHeader()) - .set(cookieHeader) .send(requestBody) .expect(200); 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 5b35e46803b2..4d9acd0a688e 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 @@ -24,18 +24,13 @@ export default function ({ getService }: FtrProviderContext) { withInternalHeaders: true, } ); - supertestAdminWithApiKey = await roleScopedSupertest.getSupertestWithRoleScope('admin', { - withInternalHeaders: true, - }); - }); - after(async () => { - await supertestAdminWithApiKey.destroy(); }); + describe('route access', () => { describe('disabled', () => { // ToDo: unskip these when we disable login routes xit('login', async () => { - const { body, status } = await supertestAdminWithApiKey.get('/login'); + const { body, status } = await supertestAdminWithCookieCredentials.get('/login'); svlCommonApi.assertApiNotFound(body, status); }); @@ -48,7 +43,9 @@ export default function ({ getService }: FtrProviderContext) { }); it('access agreement', async () => { - const { body, status } = await supertestAdminWithApiKey.get('/security/access_agreement'); + const { body, status } = await supertestAdminWithCookieCredentials.get( + '/security/access_agreement' + ); svlCommonApi.assertApiNotFound(body, status); }); @@ -62,7 +59,7 @@ export default function ({ getService }: FtrProviderContext) { describe('public', () => { it('login', async () => { - const { status } = await supertestAdminWithApiKey.get('/login'); + const { status } = await supertestAdminWithCookieCredentials.get('/login'); expect(status).toBe(302); }); @@ -81,32 +78,36 @@ export default function ({ getService }: FtrProviderContext) { }); it('space selector', async () => { - const { status } = await supertestAdminWithApiKey.get('/spaces/space_selector'); + const { status } = await supertestAdminWithCookieCredentials.get( + '/spaces/space_selector' + ); expect(status).toBe(200); }); it('enter space', async () => { - const { status } = await supertestAdminWithApiKey.get('/spaces/enter'); + const { status } = await supertestAdminWithCookieCredentials.get('/spaces/enter'); expect(status).toBe(302); }); it('account', async () => { - const { status } = await supertestAdminWithApiKey.get('/security/account'); + const { status } = await supertestAdminWithCookieCredentials.get('/security/account'); expect(status).toBe(200); }); it('logged out', async () => { - const { status } = await supertestAdminWithApiKey.get('/security/logged_out'); - expect(status).toBe(200); + const { status } = await supertestAdminWithCookieCredentials.get('/security/logged_out'); + expect(status).toBe(302); }); it('logout', async () => { - const { status } = await supertestAdminWithApiKey.get('/logout'); + const { status } = await supertestAdminWithCookieCredentials.get('/logout'); expect(status).toBe(200); }); it('overwritten session', async () => { - const { status } = await supertestAdminWithApiKey.get('/security/overwritten_session'); + const { status } = await supertestAdminWithCookieCredentials.get( + '/security/overwritten_session' + ); expect(status).toBe(200); }); }); From 8c25dc1697f8dd10bd9fdbfe7de549a038ab6e7e Mon Sep 17 00:00:00 2001 From: Dzmitry Lemechko Date: Wed, 18 Sep 2024 16:10:33 +0200 Subject: [PATCH 18/18] fix type check failure --- .../test_suites/common/platform_security/api_keys.ts | 1 + .../test_suites/common/platform_security/views.ts | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) 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 d0082d0e85da..6646e34ae849 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 @@ -6,6 +6,7 @@ */ import expect from 'expect'; +import { SupertestWithRoleScopeType } from '@kbn/test-suites-xpack/api_integration/deployment_agnostic/services'; import { FtrProviderContext } from '../../../ftr_provider_context'; export default function ({ getService }: FtrProviderContext) { 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 4d9acd0a688e..8234fa61113d 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 @@ -13,7 +13,6 @@ export default function ({ getService }: FtrProviderContext) { const svlCommonApi = getService('svlCommonApi'); const roleScopedSupertest = getService('roleScopedSupertest'); let supertestAdminWithCookieCredentials: SupertestWithRoleScopeType; - let supertestAdminWithApiKey: SupertestWithRoleScopeType; describe('security/views', function () { before(async () => {