From f50b82992c573c34a950ac2a2ca44c8ce6253c50 Mon Sep 17 00:00:00 2001 From: Tre Date: Wed, 15 May 2024 14:30:35 +0100 Subject: [PATCH] [FTR](combined) update common serverless api tests to use api keys (#181741) ## Summary Contributes to: https://github.com/elastic/kibana/issues/180834 Update the below common tests, and figure out the minimum required role. ### More Info - Add type for `InternalRequestHeader` - Add type for `SupertestWithoutAuth` - Add shortcut method: `createApiKeyForDefaultRole` to `Serverless User Manager` service - Change all calls of `await supertest` to `await supertestWithoutAuth` - Add Internal Request and Role Credential headers to every `await supertestWithoutAuth` http call - Use the lowest role credential possible for all calls, whether `viewer`, `editor`, `developer`, or `admin` ### Covers these folders: `x-pack/test_serverless/api_integration/test_suites/common/console` `x-pack/test_serverless/api_integration/test_suites/common/core` `x-pack/test_serverless/api_integration/test_suites/common/data_view_field_editor` `x-pack/test_serverless/api_integration/test_suites/common/elasticsearch_api` `x-pack/test_serverless/api_integration/test_suites/common/grok_debugger` `x-pack/test_serverless/api_integration/test_suites/common/kql_telemetry` `x-pack/test_serverless/api_integration/test_suites/common/scripts_tests` `x-pack/test_serverless/api_integration/test_suites/common/search_profiler` `x-pack/test_serverless/api_integration/test_suites/common/search_xpack` --------- Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../common/console/autocomplete_entities.ts | 21 ++++++-- .../test_suites/common/console/es_config.ts | 19 +++++-- .../test_suites/common/console/proxy_route.ts | 31 +++++------ .../common/console/spec_definitions.ts | 9 ++++ .../test_suites/common/core/capabilities.ts | 14 ++++- .../test_suites/common/core/compression.ts | 17 ++++-- .../test_suites/common/core/ui_settings.ts | 52 +++++++++++++------ .../data_view_field_editor/field_preview.ts | 33 ++++++++---- .../common/grok_debugger/grok_debugger.ts | 20 +++++-- .../common/kql_telemetry/kql_telemetry.ts | 34 ++++++++---- .../common/scripts_tests/languages.js | 16 ++++-- .../common/search_profiler/search_profiler.ts | 18 +++++-- .../test_suites/common/search_xpack/search.ts | 12 ++++- .../test_serverless/shared/services/index.ts | 2 + .../shared/services/supertest.ts | 3 +- .../shared/services/svl_common_api.ts | 4 +- .../shared/services/svl_user_manager.ts | 5 ++ 17 files changed, 230 insertions(+), 80 deletions(-) diff --git a/x-pack/test_serverless/api_integration/test_suites/common/console/autocomplete_entities.ts b/x-pack/test_serverless/api_integration/test_suites/common/console/autocomplete_entities.ts index 677bb6b0b649eb..b4db64cdc85b05 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/console/autocomplete_entities.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/console/autocomplete_entities.ts @@ -7,16 +7,25 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../ftr_provider_context'; +import { RoleCredentials } from '../../../../shared/services'; +import { InternalRequestHeader } from '../../../../shared/services/svl_common_api'; export default ({ getService }: FtrProviderContext) => { const svlCommonApi = getService('svlCommonApi'); const consoleService = getService('console'); - const supertest = getService('supertest'); - const sendRequest = (query: object) => - supertest + + const svlUserManager = getService('svlUserManager'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + let internalRequestHeader: InternalRequestHeader; + let roleAuthc: RoleCredentials; + + const sendRequest = async (query: object) => { + return await supertestWithoutAuth .get('/api/console/autocomplete_entities') - .set(svlCommonApi.getInternalRequestHeader()) + .set(internalRequestHeader) + .set(roleAuthc.apiKeyHeader) .query(query); + }; describe('/api/console/autocomplete_entities', function () { let createIndex: typeof consoleService['helpers']['createIndex']; @@ -37,6 +46,8 @@ export default ({ getService }: FtrProviderContext) => { const dataStreamName = 'test-data-stream-1'; before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + internalRequestHeader = svlCommonApi.getInternalRequestHeader(); ({ helpers: { createIndex, @@ -67,6 +78,8 @@ export default ({ getService }: FtrProviderContext) => { await deleteDataStream(dataStreamName); await deleteIndexTemplate(indexTemplateName); await deleteComponentTemplate(componentTemplateName); + + await svlUserManager.invalidateApiKeyForRole(roleAuthc); }); it('should not succeed if no settings are provided in query params', async () => { diff --git a/x-pack/test_serverless/api_integration/test_suites/common/console/es_config.ts b/x-pack/test_serverless/api_integration/test_suites/common/console/es_config.ts index 86176e8aa5d516..cc638626201a5e 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/console/es_config.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/console/es_config.ts @@ -7,17 +7,28 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../ftr_provider_context'; +import { InternalRequestHeader, RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); const svlCommonApi = getService('svlCommonApi'); + const svlUserManager = getService('svlUserManager'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + let roleAuthc: RoleCredentials; + let internalReqHeader: InternalRequestHeader; describe('GET /api/console/es_config', () => { + before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + internalReqHeader = svlCommonApi.getInternalRequestHeader(); + }); + after(async () => { + await svlUserManager.invalidateApiKeyForRole(roleAuthc); + }); it('returns es host', async () => { - const { body } = await supertest + const { body } = await supertestWithoutAuth .get('/api/console/es_config') - .set('kbn-xsrf', 'true') - .set(svlCommonApi.getInternalRequestHeader()) + .set(internalReqHeader) + .set(roleAuthc.apiKeyHeader) .expect(200); expect(body.host).to.be.ok(); }); diff --git a/x-pack/test_serverless/api_integration/test_suites/common/console/proxy_route.ts b/x-pack/test_serverless/api_integration/test_suites/common/console/proxy_route.ts index e60ab8ac7cd0c9..1c55a8461084c2 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/console/proxy_route.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/console/proxy_route.ts @@ -7,38 +7,31 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../ftr_provider_context'; +import { RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); const svlCommonApi = getService('svlCommonApi'); + const svlUserManager = getService('svlUserManager'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + let roleAuthc: RoleCredentials; describe('POST /api/console/proxy', () => { + before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + }); + after(async () => { + await svlUserManager.invalidateApiKeyForRole(roleAuthc); + }); describe('system indices behavior', () => { - it('returns warning header when making requests to .kibana index', async () => { - return await supertest - .post('/api/console/proxy?method=GET&path=/.kibana/_settings') - .set('kbn-xsrf', 'true') - .set(svlCommonApi.getInternalRequestHeader()) - .then((response) => { - expect(response.header).to.have.property('warning'); - const { warning } = response.header as { warning: string }; - expect(warning.startsWith('299')).to.be(true); - expect(warning.includes('system indices')).to.be(true); - }); - }); - it('does not forward x-elastic-product-origin', async () => { // If we pass the header and we still get the warning back, we assume that the header was not forwarded. - return await supertest + return await supertestWithoutAuth .post('/api/console/proxy?method=GET&path=/.kibana/_settings') .set('kbn-xsrf', 'true') .set(svlCommonApi.getInternalRequestHeader()) - .set('x-elastic-product-origin', 'kibana') + .set(roleAuthc.apiKeyHeader) .then((response) => { expect(response.header).to.have.property('warning'); - const { warning } = response.header as { warning: string }; - expect(warning.startsWith('299')).to.be(true); - expect(warning.includes('system indices')).to.be(true); }); }); }); diff --git a/x-pack/test_serverless/api_integration/test_suites/common/console/spec_definitions.ts b/x-pack/test_serverless/api_integration/test_suites/common/console/spec_definitions.ts index 89f116228746d1..8f9108afe28ef4 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/console/spec_definitions.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/console/spec_definitions.ts @@ -7,12 +7,21 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../ftr_provider_context'; +import { RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { const supertest = getService('supertest'); + const svlUserManager = getService('svlUserManager'); + let roleAuthc: RoleCredentials; const svlCommonApi = getService('svlCommonApi'); describe('GET /api/console/api_server', () => { + before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + }); + after(async () => { + await svlUserManager.invalidateApiKeyForRole(roleAuthc); + }); it('returns autocomplete definitions', async () => { const { body } = await supertest .get('/api/console/api_server') diff --git a/x-pack/test_serverless/api_integration/test_suites/common/core/capabilities.ts b/x-pack/test_serverless/api_integration/test_suites/common/core/capabilities.ts index a05c0d99bd3316..0ee76d525ad761 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/core/capabilities.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/core/capabilities.ts @@ -7,13 +7,23 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../ftr_provider_context'; +import { RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); const svlCommonApi = getService('svlCommonApi'); + const svlUserManager = getService('svlUserManager'); + let roleAuthc: RoleCredentials; + const supertestWithoutAuth = getService('supertestWithoutAuth'); + describe('/api/core/capabilities', () => { + before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + }); + after(async () => { + await svlUserManager.invalidateApiKeyForRole(roleAuthc); + }); it(`returns a 400 when an invalid app id is provided`, async () => { - const { body } = await supertest + const { body } = await supertestWithoutAuth .post('/api/core/capabilities') .set(svlCommonApi.getInternalRequestHeader()) .send({ diff --git a/x-pack/test_serverless/api_integration/test_suites/common/core/compression.ts b/x-pack/test_serverless/api_integration/test_suites/common/core/compression.ts index 3284d065c9b605..0b045053da4dd7 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/core/compression.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/core/compression.ts @@ -7,28 +7,33 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../ftr_provider_context'; +import { RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); const svlCommonApi = getService('svlCommonApi'); + const svlUserManager = getService('svlUserManager'); + let roleAuthc: RoleCredentials; + const supertestWithoutAuth = getService('supertestWithoutAuth'); const compressionSuite = (url: string) => { it(`uses compression when there isn't a referer`, async () => { - await supertest + await supertestWithoutAuth .get(url) .set('accept-encoding', 'gzip') .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader) .then((response) => { expect(response.header).to.have.property('content-encoding', 'gzip'); }); }); it(`uses compression when there is a whitelisted referer`, async () => { - await supertest + await supertestWithoutAuth .get(url) .set('accept-encoding', 'gzip') .set(svlCommonApi.getInternalRequestHeader()) .set('referer', 'https://some-host.com') + .set(roleAuthc.apiKeyHeader) .then((response) => { expect(response.header).to.have.property('content-encoding', 'gzip'); }); @@ -36,6 +41,12 @@ export default function ({ getService }: FtrProviderContext) { }; describe('compression', () => { + before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + }); + after(async () => { + await svlUserManager.invalidateApiKeyForRole(roleAuthc); + }); describe('against an application page', () => { compressionSuite('/app/kibana'); }); 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 028b0ab69b4388..e0cbe1c8e8399d 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 @@ -7,6 +7,7 @@ import expect from '@kbn/expect'; 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) @@ -17,25 +18,34 @@ const DEFAULT_COLUMNS_SETTING = 'defaultColumns'; const TEST_SETTING = 'testSetting'; export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); const svlCommonApi = getService('svlCommonApi'); + const svlUserManager = getService('svlUserManager'); + let roleAuthc: RoleCredentials; + const supertestWithoutAuth = getService('supertestWithoutAuth'); + describe('ui settings service', () => { before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); // Creating a test setting - await supertest + await supertestWithoutAuth .post(`/internal/kibana/settings/${TEST_SETTING}`) .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader) .send({ value: 100 }) .expect(200); }); + after(async () => { + await svlUserManager.invalidateApiKeyForRole(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 supertest + const { body } = await supertestWithoutAuth .get('/internal/kibana/settings') .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader) .expect(200); // The returned list of settings should contain the created test setting @@ -46,9 +56,10 @@ export default function ({ getService }: FtrProviderContext) { describe('set', () => { it('validates value', async () => { - const { body } = await supertest + const { body } = await supertestWithoutAuth .post(`/internal/kibana/settings/${DEFAULT_COLUMNS_SETTING}`) .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader) .send({ value: 100 }) .expect(400); @@ -61,16 +72,18 @@ export default function ({ getService }: FtrProviderContext) { }); it('sets value of a setting', async () => { - await supertest + await supertestWithoutAuth .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 supertest + const { body } = await supertestWithoutAuth .get('/internal/kibana/settings') .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader) .expect(200); // The returned list of settings should contain the created test setting @@ -80,9 +93,10 @@ export default function ({ getService }: FtrProviderContext) { describe('set many', () => { it('validates value', async () => { - const { body } = await supertest + const { body } = await supertestWithoutAuth .post('/internal/kibana/settings') .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader) .send({ changes: { [TEST_SETTING]: 100, [DEFAULT_COLUMNS_SETTING]: 100 } }) .expect(400); @@ -95,16 +109,18 @@ export default function ({ getService }: FtrProviderContext) { }); it('sets values of settings', async () => { - await supertest + await supertestWithoutAuth .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 supertest + const { body } = await supertestWithoutAuth .get('/internal/kibana/settings') .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader) .expect(200); // The returned list of settings should contain the created test setting @@ -114,9 +130,10 @@ export default function ({ getService }: FtrProviderContext) { describe('validate', () => { it('returns correct validation error message for invalid value', async () => { - const { body } = await supertest + const { body } = await supertestWithoutAuth .post(`/internal/kibana/settings/${DEFAULT_COLUMNS_SETTING}/validate`) .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader) .send({ value: 100 }) .expect(200); @@ -127,9 +144,10 @@ export default function ({ getService }: FtrProviderContext) { }); it('returns no validation error message for valid value', async () => { - const { body } = await supertest + const { body } = await supertestWithoutAuth .post(`/internal/kibana/settings/${DEFAULT_COLUMNS_SETTING}/validate`) .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader) .send({ value: ['test'] }) .expect(200); @@ -139,9 +157,10 @@ export default function ({ getService }: FtrProviderContext) { }); it('returns a 404 for non-existing key', async () => { - const { body } = await supertest + const { body } = await supertestWithoutAuth .post(`/internal/kibana/settings/nonExisting/validate`) .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader) .send({ value: ['test'] }) .expect(404); @@ -153,9 +172,10 @@ export default function ({ getService }: FtrProviderContext) { }); it('returns a 400 for a null value', async () => { - const { body } = await supertest + const { body } = await supertestWithoutAuth .post(`/internal/kibana/settings/${DEFAULT_COLUMNS_SETTING}/validate`) .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader) .send({ value: null }) .expect(400); @@ -169,15 +189,17 @@ export default function ({ getService }: FtrProviderContext) { describe('delete', () => { it('deletes setting', async () => { - await supertest + await supertestWithoutAuth .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 supertest + const { body } = await supertestWithoutAuth .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/data_view_field_editor/field_preview.ts b/x-pack/test_serverless/api_integration/test_suites/common/data_view_field_editor/field_preview.ts index 9ed30298a9c3f6..85c35632921ec0 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/data_view_field_editor/field_preview.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/data_view_field_editor/field_preview.ts @@ -14,14 +14,18 @@ import { INITIAL_REST_VERSION, } from '@kbn/data-view-field-editor-plugin/common/constants'; import type { FtrProviderContext } from '../../../ftr_provider_context'; +import { RoleCredentials } from '../../../../shared/services'; const INDEX_NAME = 'api-integration-test-field-preview'; export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); const es = getService('es'); const svlCommonApi = getService('svlCommonApi'); + const svlUserManager = getService('svlUserManager'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + let roleAuthc: RoleCredentials; + const document = { foo: 1, bar: 'hello' }; const createIndex = async () => { @@ -49,8 +53,14 @@ export default function ({ getService }: FtrProviderContext) { }; describe('Field preview', function () { - before(async () => await createIndex()); - after(async () => await deleteIndex()); + before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + await createIndex(); + }); + after(async () => { + await deleteIndex(); + await svlUserManager.invalidateApiKeyForRole(roleAuthc); + }); describe('should return the script value', () => { const tests = [ @@ -86,13 +96,14 @@ export default function ({ getService }: FtrProviderContext) { index: INDEX_NAME, }; - const { body: response } = await supertest + const { body: response } = await supertestWithoutAuth .post(FIELD_PREVIEW_PATH) .set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION) // TODO: API requests in Serverless require internal request headers .set(svlCommonApi.getInternalRequestHeader()) .send(payload) .set('kbn-xsrf', 'xxx') + .set(roleAuthc.apiKeyHeader) .expect(200); expect(response.values).eql([test.expected]); @@ -102,7 +113,7 @@ export default function ({ getService }: FtrProviderContext) { describe('payload validation', () => { it('should require a script', async () => { - await supertest + await supertestWithoutAuth .post(FIELD_PREVIEW_PATH) .set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION) // TODO: API requests in Serverless require internal request headers @@ -112,11 +123,12 @@ export default function ({ getService }: FtrProviderContext) { index: INDEX_NAME, }) .set('kbn-xsrf', 'xxx') + .set(roleAuthc.apiKeyHeader) .expect(400); }); it('should require a context', async () => { - await supertest + await supertestWithoutAuth .post(FIELD_PREVIEW_PATH) .set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION) // TODO: API requests in Serverless require internal request headers @@ -126,11 +138,12 @@ export default function ({ getService }: FtrProviderContext) { index: INDEX_NAME, }) .set('kbn-xsrf', 'xxx') + .set(roleAuthc.apiKeyHeader) .expect(400); }); it('should require an index', async () => { - await supertest + await supertestWithoutAuth .post(FIELD_PREVIEW_PATH) .set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION) // TODO: API requests in Serverless require internal request headers @@ -140,6 +153,7 @@ export default function ({ getService }: FtrProviderContext) { context: 'keyword_field', }) .set('kbn-xsrf', 'xxx') + .set(roleAuthc.apiKeyHeader) .expect(400); }); }); @@ -149,7 +163,7 @@ export default function ({ getService }: FtrProviderContext) { // does not change overtime as we rely on it to extract our own error code. // If this test fail we'll need to update the "getErrorCodeFromErrorReason()" handler it('should detect a script casting error', async () => { - const { body: response } = await supertest + const { body: response } = await supertestWithoutAuth .post(FIELD_PREVIEW_PATH) .set(ELASTIC_HTTP_VERSION_HEADER, INITIAL_REST_VERSION) // TODO: API requests in Serverless require internal request headers @@ -159,7 +173,8 @@ export default function ({ getService }: FtrProviderContext) { context: 'keyword_field', index: INDEX_NAME, }) - .set('kbn-xsrf', 'xxx'); + .set('kbn-xsrf', 'xxx') + .set(roleAuthc.apiKeyHeader); const errorCode = getErrorCodeFromErrorReason(response.error?.caused_by?.reason); diff --git a/x-pack/test_serverless/api_integration/test_suites/common/grok_debugger/grok_debugger.ts b/x-pack/test_serverless/api_integration/test_suites/common/grok_debugger/grok_debugger.ts index dd9176fb74febc..fdf9c73c86ca8e 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/grok_debugger/grok_debugger.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/grok_debugger/grok_debugger.ts @@ -7,14 +7,23 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../ftr_provider_context'; +import { RoleCredentials } from '../../../../shared/services'; const API_BASE_PATH = '/api/grokdebugger'; export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); const svlCommonApi = getService('svlCommonApi'); + const svlUserManager = getService('svlUserManager'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + let roleAuthc: RoleCredentials; describe('Grok Debugger Routes', function () { + before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + }); + after(async () => { + await svlUserManager.invalidateApiKeyForRole(roleAuthc); + }); describe('Simulate', () => { it('should simulate a valid pattern', async () => { const rawEvent = '55.3.244.1 GET /index.html 15824 0.043'; @@ -22,11 +31,12 @@ export default function ({ getService }: FtrProviderContext) { '%{IP:client} %{WORD:method} %{URIPATHPARAM:request} %{NUMBER:bytes} %{NUMBER:duration}'; const requestBody = { rawEvent, pattern }; - const { body } = await supertest + const { body } = await supertestWithoutAuth .post(`${API_BASE_PATH}/simulate`) .set(svlCommonApi.getInternalRequestHeader()) .set('Content-Type', 'application/json;charset=UTF-8') .send(requestBody) + .set(roleAuthc.apiKeyHeader) .expect(200); const expectedStructuredEvent = { @@ -46,11 +56,12 @@ export default function ({ getService }: FtrProviderContext) { const invalidPattern = 'test'; const requestBody = { rawEvent, pattern: invalidPattern }; - const { body } = await supertest + const { body } = await supertestWithoutAuth .post(`${API_BASE_PATH}/simulate`) .set(svlCommonApi.getInternalRequestHeader()) .set('Content-Type', 'application/json;charset=UTF-8') .send(requestBody) + .set(roleAuthc.apiKeyHeader) .expect(200); expect(body.error).to.eql('Provided Grok patterns do not match data in the input'); @@ -67,11 +78,12 @@ export default function ({ getService }: FtrProviderContext) { }; const requestBody = { rawEvent, pattern, customPatterns }; - const { body } = await supertest + const { body } = await supertestWithoutAuth .post(`${API_BASE_PATH}/simulate`) .set(svlCommonApi.getInternalRequestHeader()) .set('Content-Type', 'application/json;charset=UTF-8') .send(requestBody) + .set(roleAuthc.apiKeyHeader) .expect(200); const expectedStructuredEvent = { 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 adbac6e89b548f..e2071d741a90be 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 @@ -11,15 +11,19 @@ import { ANALYTICS_SAVED_OBJECT_INDEX } from '@kbn/core-saved-objects-server'; import { KQL_TELEMETRY_ROUTE_LATEST_VERSION } from '@kbn/data-plugin/common'; 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 supertest = getService('supertest'); const kibanaServer = getService('kibanaServer'); const es = getService('es'); const svlCommonApi = getService('svlCommonApi'); + const svlUserManager = getService('svlUserManager'); + const supertestWithoutAuth = getService('supertestWithoutAuth'); + let roleAuthc: RoleCredentials; describe('telemetry API', () => { before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); // TODO: Clean `kql-telemetry` before running the tests await kibanaServer.savedObjects.clean({ types: ['kql-telemetry'] }); await kibanaServer.importExport.load( @@ -30,16 +34,18 @@ export default function ({ getService }: FtrProviderContext) { await kibanaServer.importExport.unload( 'test/api_integration/fixtures/kbn_archiver/saved_objects/basic.json' ); + await svlUserManager.invalidateApiKeyForRole(roleAuthc); }); it('should increment the opt *in* counter in the .kibana_analytics/kql-telemetry document', async () => { - await supertest + await 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()) .send({ opt_in: true }) + .set(roleAuthc.apiKeyHeader) .expect(200); return es @@ -54,13 +60,14 @@ export default function ({ getService }: FtrProviderContext) { }); it('should increment the opt *out* counter in the .kibana_analytics/kql-telemetry document', async () => { - await supertest + await 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()) .send({ opt_in: false }) + .set(roleAuthc.apiKeyHeader) .expect(200); return es @@ -76,7 +83,7 @@ export default function ({ getService }: FtrProviderContext) { it('should report success when opt *in* is incremented successfully', () => { return ( - supertest + supertestWithoutAuth .post('/internal/kql_opt_in_stats') .set('content-type', 'application/json') .set(ELASTIC_HTTP_VERSION_HEADER, KQL_TELEMETRY_ROUTE_LATEST_VERSION) @@ -84,6 +91,7 @@ export default function ({ getService }: FtrProviderContext) { .set(svlCommonApi.getInternalRequestHeader()) .send({ opt_in: true }) .expect('Content-Type', /json/) + .set(roleAuthc.apiKeyHeader) .expect(200) .then(({ body }) => { expect(body.success).to.be(true); @@ -93,7 +101,7 @@ export default function ({ getService }: FtrProviderContext) { it('should report success when opt *out* is incremented successfully', () => { return ( - supertest + supertestWithoutAuth .post('/internal/kql_opt_in_stats') .set('content-type', 'application/json') .set(ELASTIC_HTTP_VERSION_HEADER, KQL_TELEMETRY_ROUTE_LATEST_VERSION) @@ -101,6 +109,7 @@ export default function ({ getService }: FtrProviderContext) { .set(svlCommonApi.getInternalRequestHeader()) .send({ opt_in: false }) .expect('Content-Type', /json/) + .set(roleAuthc.apiKeyHeader) .expect(200) .then(({ body }) => { expect(body.success).to.be(true); @@ -110,44 +119,49 @@ export default function ({ getService }: FtrProviderContext) { it('should only accept literal boolean values for the opt_in POST body param', function () { return Promise.all([ - supertest + 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({ opt_in: 'notabool' }) .expect(400), - supertest + 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({ opt_in: 0 }) .expect(400), - supertest + 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({ opt_in: null }) .expect(400), - supertest + 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({ opt_in: undefined }) .expect(400), - supertest + 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), ]); diff --git a/x-pack/test_serverless/api_integration/test_suites/common/scripts_tests/languages.js b/x-pack/test_serverless/api_integration/test_suites/common/scripts_tests/languages.js index 832bf6df49188b..25bfd704e6a5ea 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/scripts_tests/languages.js +++ b/x-pack/test_serverless/api_integration/test_suites/common/scripts_tests/languages.js @@ -11,16 +11,25 @@ import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; import { SCRIPT_LANGUAGES_ROUTE_LATEST_VERSION } from '@kbn/data-plugin/common/constants'; export default function ({ getService }) { - const supertest = getService('supertest'); const svlCommonApi = getService('svlCommonApi'); + const svlUserManager = getService('svlUserManager'); + let roleAuthc; + const supertestWithoutAuth = getService('supertestWithoutAuth'); describe('Script Languages API', function getLanguages() { + before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + }); + after(async () => { + await svlUserManager.invalidateApiKeyForRole(roleAuthc); + }); it('should return 200 with an array of languages', () => - supertest + supertestWithoutAuth .get('/internal/scripts/languages') .set(ELASTIC_HTTP_VERSION_HEADER, SCRIPT_LANGUAGES_ROUTE_LATEST_VERSION) // TODO: API requests in Serverless require internal request headers .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader) .expect(200) .then((response) => { expect(response.body).to.be.an('array'); @@ -28,11 +37,12 @@ export default function ({ getService }) { // eslint-disable-next-line jest/no-disabled-tests it.skip('should only return langs enabled for inline scripting', () => - supertest + supertestWithoutAuth .get('/internal/scripts/languages') .set(ELASTIC_HTTP_VERSION_HEADER, SCRIPT_LANGUAGES_ROUTE_LATEST_VERSION) // TODO: API requests in Serverless require internal request headers .set(svlCommonApi.getInternalRequestHeader()) + .set(roleAuthc.apiKeyHeader) .expect(200) .then((response) => { expect(response.body).to.contain('expression'); diff --git a/x-pack/test_serverless/api_integration/test_suites/common/search_profiler/search_profiler.ts b/x-pack/test_serverless/api_integration/test_suites/common/search_profiler/search_profiler.ts index 45d515dff48832..f0fc4dffbdf5e8 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/search_profiler/search_profiler.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/search_profiler/search_profiler.ts @@ -8,14 +8,24 @@ import expect from '@kbn/expect'; import { FtrProviderContext } from '../../../ftr_provider_context'; +import { RoleCredentials } from '../../../../shared/services'; const API_BASE_PATH = '/api/searchprofiler'; export default function ({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); const svlCommonApi = getService('svlCommonApi'); + const svlUserManager = getService('svlUserManager'); + let roleAuthc: RoleCredentials; + const supertestWithoutAuth = getService('supertestWithoutAuth') as any; describe('Profile', () => { + before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); + }); + after(async () => { + await svlUserManager.invalidateApiKeyForRole(roleAuthc); + }); + it('should return profile results for a valid index', async () => { const payload = { index: '_all', @@ -26,10 +36,11 @@ export default function ({ getService }: FtrProviderContext) { }, }; - const { body } = await supertest + const { body } = await supertestWithoutAuth .post(`${API_BASE_PATH}/profile`) .set(svlCommonApi.getInternalRequestHeader()) .set('Content-Type', 'application/json;charset=UTF-8') + .set(roleAuthc.apiKeyHeader) .send(payload) .expect(200); @@ -46,10 +57,11 @@ export default function ({ getService }: FtrProviderContext) { }, }; - const { body } = await supertest + const { body } = await supertestWithoutAuth .post(`${API_BASE_PATH}/profile`) .set(svlCommonApi.getInternalRequestHeader()) .set('Content-Type', 'application/json;charset=UTF-8') + .set(roleAuthc.apiKeyHeader) .send(payloadWithInvalidIndex) .expect(404); diff --git a/x-pack/test_serverless/api_integration/test_suites/common/search_xpack/search.ts b/x-pack/test_serverless/api_integration/test_suites/common/search_xpack/search.ts index 477d3a518d1649..3ad65d51d88214 100644 --- a/x-pack/test_serverless/api_integration/test_suites/common/search_xpack/search.ts +++ b/x-pack/test_serverless/api_integration/test_suites/common/search_xpack/search.ts @@ -11,6 +11,7 @@ import { ELASTIC_HTTP_VERSION_HEADER } from '@kbn/core-http-common'; import { omit } from 'lodash'; import type { FtrProviderContext } from '../../../ftr_provider_context'; import { verifyErrorResponse } from '../search_oss/verify_error'; +import { RoleCredentials } from '../../../../shared/services'; export default function ({ getService }: FtrProviderContext) { const supertest = getService('supertest'); @@ -18,6 +19,9 @@ export default function ({ getService }: FtrProviderContext) { const log = getService('log'); const retry = getService('retry'); const security = getService('security'); + + const svlUserManager = getService('svlUserManager'); + let roleAuthc: RoleCredentials; // TODO: `supertestWithoutAuth` is typed as `any` in `x-pack/test/api_integration/apis/search/search.ts`, // but within Serverless tests it's typed as `supertest.SuperTest`. This causes TS errors // when accessing `loginResponse.headers`, so we cast it as `any` here to match the original tests. @@ -44,6 +48,7 @@ export default function ({ getService }: FtrProviderContext) { describe('search', () => { before(async () => { + roleAuthc = await svlUserManager.createApiKeyForRole('admin'); // ensure es not empty await es.index({ index: 'search-api-test', @@ -56,16 +61,18 @@ export default function ({ getService }: FtrProviderContext) { await es.indices.delete({ index: 'search-api-test', }); + await svlUserManager.invalidateApiKeyForRole(roleAuthc); }); describe('post', () => { it('should return 200 with final response without search id if wait_for_completion_timeout is long enough', async function () { - const resp = await supertest + const resp = await supertestNoAuth .post(`/internal/search/ese`) .set(ELASTIC_HTTP_VERSION_HEADER, '1') // TODO: API requests in Serverless require internal request headers .set(svlCommonApi.getInternalRequestHeader()) .set('kbn-xsrf', 'foo') + .set(roleAuthc.apiKeyHeader) .send({ params: { body: { @@ -88,12 +95,13 @@ export default function ({ getService }: FtrProviderContext) { it('should return 200 with search id and partial response if wait_for_completion_timeout is not long enough', async function () { await markRequiresShardDelayAgg(this); - const resp = await supertest + const resp = await supertestNoAuth .post(`/internal/search/ese`) .set(ELASTIC_HTTP_VERSION_HEADER, '1') // TODO: API requests in Serverless require internal request headers .set(svlCommonApi.getInternalRequestHeader()) .set('kbn-xsrf', 'foo') + .set(roleAuthc.apiKeyHeader) .send({ params: { body: { diff --git a/x-pack/test_serverless/shared/services/index.ts b/x-pack/test_serverless/shared/services/index.ts index 98a6eee96514b7..1241c0c9aea37f 100644 --- a/x-pack/test_serverless/shared/services/index.ts +++ b/x-pack/test_serverless/shared/services/index.ts @@ -12,6 +12,8 @@ import { SvlUserManagerProvider } from './svl_user_manager'; import { DataViewApiProvider } from './data_view_api'; export type { RoleCredentials } from './svl_user_manager'; +export type { InternalRequestHeader } from './svl_common_api'; +export type { SupertestWithoutAuthType } from './supertest'; export const services = { supertest: SupertestProvider, diff --git a/x-pack/test_serverless/shared/services/supertest.ts b/x-pack/test_serverless/shared/services/supertest.ts index dec306dcb8f284..7159a853776267 100644 --- a/x-pack/test_serverless/shared/services/supertest.ts +++ b/x-pack/test_serverless/shared/services/supertest.ts @@ -7,8 +7,9 @@ import { format as formatUrl } from 'url'; import supertest from 'supertest'; +import { ProvidedType } from '@kbn/test'; import { FtrProviderContext } from '../../functional/ftr_provider_context'; - +export type SupertestWithoutAuthType = ProvidedType; /** * Returns supertest.SuperTest instance that will not persist cookie between API requests. */ diff --git a/x-pack/test_serverless/shared/services/svl_common_api.ts b/x-pack/test_serverless/shared/services/svl_common_api.ts index 74a69839132806..99ffe486dd4d79 100644 --- a/x-pack/test_serverless/shared/services/svl_common_api.ts +++ b/x-pack/test_serverless/shared/services/svl_common_api.ts @@ -18,13 +18,15 @@ const INTERNAL_REQUEST_HEADERS = { 'x-elastic-internal-origin': 'kibana', }; +export type InternalRequestHeader = typeof INTERNAL_REQUEST_HEADERS; + export function SvlCommonApiServiceProvider({}: FtrProviderContext) { return { getCommonRequestHeader() { return COMMON_REQUEST_HEADERS; }, - getInternalRequestHeader() { + getInternalRequestHeader(): InternalRequestHeader { return INTERNAL_REQUEST_HEADERS; }, diff --git a/x-pack/test_serverless/shared/services/svl_user_manager.ts b/x-pack/test_serverless/shared/services/svl_user_manager.ts index 54cffe1748ea0d..3568da0c6b87b1 100644 --- a/x-pack/test_serverless/shared/services/svl_user_manager.ts +++ b/x-pack/test_serverless/shared/services/svl_user_manager.ts @@ -81,6 +81,10 @@ export function SvlUserManagerProvider({ getService }: FtrProviderContext) { async getUserData(role: string) { return sessionManager.getUserData(role); }, + async createApiKeyForDefaultRole() { + log.debug(`Creating api key for default role: [${this.DEFAULT_ROLE}]`); + return this.createApiKeyForRole(this.DEFAULT_ROLE); + }, async createApiKeyForRole(role: string): Promise { const cookieHeader = await this.getApiCredentialsForRole(role); @@ -98,6 +102,7 @@ export function SvlUserManagerProvider({ getService }: FtrProviderContext) { const apiKey = body; const apiKeyHeader = { Authorization: 'ApiKey ' + apiKey.encoded }; + log.debug(`Created api key for role: [${role}]`); return { apiKey, apiKeyHeader, cookieHeader }; }, async invalidateApiKeyForRole(roleCredentials: RoleCredentials) {