diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 0fdced2d6e44d..18f22b1e103a9 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1024,6 +1024,7 @@ src/platform/packages/shared/kbn-test @elastic/kibana-operations @elastic/appex- src/platform/packages/private/kbn-test-eui-helpers @elastic/kibana-visualizations x-pack/platform/test/licensing_plugin/plugins/test_feature_usage @elastic/kibana-security src/platform/packages/shared/kbn-test-jest-helpers @elastic/kibana-operations @elastic/appex-qa +src/platform/packages/shared/kbn-test-saml-auth @elastic/appex-qa src/platform/packages/shared/kbn-test-subj-selector @elastic/kibana-operations @elastic/appex-qa x-pack/solutions/security/test/security_solution_api_integration @elastic/secutity-detection-engine src/platform/test diff --git a/package.json b/package.json index 762902d24db6e..bb89b84ce04da 100644 --- a/package.json +++ b/package.json @@ -1588,6 +1588,7 @@ "@kbn/test": "link:src/platform/packages/shared/kbn-test", "@kbn/test-eui-helpers": "link:src/platform/packages/private/kbn-test-eui-helpers", "@kbn/test-jest-helpers": "link:src/platform/packages/shared/kbn-test-jest-helpers", + "@kbn/test-saml-auth": "link:src/platform/packages/shared/kbn-test-saml-auth", "@kbn/test-subj-selector": "link:src/platform/packages/shared/kbn-test-subj-selector", "@kbn/test-suites-security-solution-apis": "link:x-pack/solutions/security/test/security_solution_api_integration", "@kbn/test-suites-src": "link:src/platform/test", diff --git a/packages/kbn-repo-source-classifier/src/repo_source_classifier.ts b/packages/kbn-repo-source-classifier/src/repo_source_classifier.ts index bfa8375919889..9df336c955fd3 100644 --- a/packages/kbn-repo-source-classifier/src/repo_source_classifier.ts +++ b/packages/kbn-repo-source-classifier/src/repo_source_classifier.ts @@ -166,7 +166,12 @@ export class RepoSourceClassifier { const { pkgId, rel } = pkgInfo; - if (pkgId === '@kbn/test' || pkgId === '@kbn/test-subj-selector') { + if ( + pkgId === '@kbn/test' || + pkgId === '@kbn/test-es-server' || + pkgId === '@kbn/test-saml-auth' || + pkgId === '@kbn/test-subj-selector' + ) { return 'common package'; } diff --git a/src/platform/packages/shared/kbn-ftr-common-functional-services/moon.yml b/src/platform/packages/shared/kbn-ftr-common-functional-services/moon.yml index 2b0c69bbb5cf4..20bd0d3b6b9e2 100644 --- a/src/platform/packages/shared/kbn-ftr-common-functional-services/moon.yml +++ b/src/platform/packages/shared/kbn-ftr-common-functional-services/moon.yml @@ -21,6 +21,7 @@ dependsOn: - '@kbn/tooling-log' - '@kbn/es-archiver' - '@kbn/test' + - '@kbn/test-saml-auth' - '@kbn/expect' - '@kbn/search-types' - '@kbn/core-http-common' diff --git a/src/platform/packages/shared/kbn-ftr-common-functional-services/services/saml_auth/serverless/auth_provider.ts b/src/platform/packages/shared/kbn-ftr-common-functional-services/services/saml_auth/serverless/auth_provider.ts index da364c33bdc09..4e0e2f2b6d77e 100644 --- a/src/platform/packages/shared/kbn-ftr-common-functional-services/services/saml_auth/serverless/auth_provider.ts +++ b/src/platform/packages/shared/kbn-ftr-common-functional-services/services/saml_auth/serverless/auth_provider.ts @@ -12,7 +12,7 @@ import { ServerlessProjectType, SERVERLESS_ROLES_ROOT_PATH } from '@kbn/es'; import { type Config } from '@kbn/test'; import { isServerlessProjectType, readRolesDescriptorsFromResource } from '@kbn/es/src/utils'; import { resolve } from 'path'; -import { Role } from '@kbn/test/src/auth/types'; +import type { Role } from '@kbn/test-saml-auth'; import { getServerlessInternalRequestHeaders, COMMON_REQUEST_HEADERS, diff --git a/src/platform/packages/shared/kbn-ftr-common-functional-services/tsconfig.json b/src/platform/packages/shared/kbn-ftr-common-functional-services/tsconfig.json index 41309b8260833..1b8edd1d69209 100644 --- a/src/platform/packages/shared/kbn-ftr-common-functional-services/tsconfig.json +++ b/src/platform/packages/shared/kbn-ftr-common-functional-services/tsconfig.json @@ -16,6 +16,7 @@ "@kbn/tooling-log", "@kbn/es-archiver", "@kbn/test", + "@kbn/test-saml-auth", "@kbn/expect", "@kbn/search-types", "@kbn/core-http-common", diff --git a/src/platform/packages/shared/kbn-scout/moon.yml b/src/platform/packages/shared/kbn-scout/moon.yml index b64c2d0a7c749..127086acd9f8c 100644 --- a/src/platform/packages/shared/kbn-scout/moon.yml +++ b/src/platform/packages/shared/kbn-scout/moon.yml @@ -27,6 +27,7 @@ dependsOn: - '@kbn/dev-proc-runner' - '@kbn/kbn-client' - '@kbn/test' + - '@kbn/test-saml-auth' - '@kbn/es-archiver' - '@kbn/dev-utils' - '@kbn/mock-idp-utils' diff --git a/src/platform/packages/shared/kbn-scout/src/common/constants.ts b/src/platform/packages/shared/kbn-scout/src/common/constants.ts index bf5c6fb181cd7..bf9085888a53b 100644 --- a/src/platform/packages/shared/kbn-scout/src/common/constants.ts +++ b/src/platform/packages/shared/kbn-scout/src/common/constants.ts @@ -7,7 +7,7 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import { Role } from '@kbn/test/src/auth/types'; +import type { Role } from '@kbn/test-saml-auth'; export const PROJECT_DEFAULT_ROLES = new Map([ ['es', 'developer'], diff --git a/src/platform/packages/shared/kbn-scout/src/common/services/index.ts b/src/platform/packages/shared/kbn-scout/src/common/services/index.ts index f46743eb17d1d..5cf8c409a1f4f 100644 --- a/src/platform/packages/shared/kbn-scout/src/common/services/index.ts +++ b/src/platform/packages/shared/kbn-scout/src/common/services/index.ts @@ -14,7 +14,7 @@ export { createKbnUrl } from './kibana_url'; export { createSamlSessionManager } from './saml_auth'; export type { KibanaUrl } from './kibana_url'; -export type { SamlSessionManager } from '@kbn/test'; +export type { SamlSessionManager } from '@kbn/test-saml-auth'; export { ScoutLogger } from './logger'; export type { KbnClient } from '@kbn/kbn-client'; export type { Client as EsClient } from '@elastic/elasticsearch'; diff --git a/src/platform/packages/shared/kbn-scout/src/common/services/roles.ts b/src/platform/packages/shared/kbn-scout/src/common/services/roles.ts index 2aba012b7d315..1eb32c2c199ad 100644 --- a/src/platform/packages/shared/kbn-scout/src/common/services/roles.ts +++ b/src/platform/packages/shared/kbn-scout/src/common/services/roles.ts @@ -8,7 +8,7 @@ */ import type { ServerlessProjectType } from '@kbn/es'; -import type { Role } from '@kbn/test/src/auth/types'; +import type { Role } from '@kbn/test-saml-auth'; import { PROJECT_DEFAULT_ROLES } from '../constants'; /** diff --git a/src/platform/packages/shared/kbn-scout/src/common/services/saml_auth.ts b/src/platform/packages/shared/kbn-scout/src/common/services/saml_auth.ts index 447b021b4020f..3cc2ad8343787 100644 --- a/src/platform/packages/shared/kbn-scout/src/common/services/saml_auth.ts +++ b/src/platform/packages/shared/kbn-scout/src/common/services/saml_auth.ts @@ -15,10 +15,11 @@ import { readRolesDescriptorsFromResource, } from '@kbn/es'; import { REPO_ROOT } from '@kbn/repo-info'; -import { HostOptions, SamlSessionManager } from '@kbn/test'; -import { ScoutTestConfig } from '../../types'; -import { Protocol } from '../../playwright/types'; -import { ScoutLogger } from './logger'; +import type { HostOptions } from '@kbn/test-saml-auth'; +import { SamlSessionManager } from '@kbn/test-saml-auth'; +import type { ScoutTestConfig } from '../../types'; +import type { Protocol } from '../../playwright/types'; +import type { ScoutLogger } from './logger'; const getResourceDirPath = (config: ScoutTestConfig) => { return config.serverless diff --git a/src/platform/packages/shared/kbn-scout/src/playwright/fixtures/scope/worker/core_fixtures.ts b/src/platform/packages/shared/kbn-scout/src/playwright/fixtures/scope/worker/core_fixtures.ts index 79a03d304bcf8..40a59549bf8e9 100644 --- a/src/platform/packages/shared/kbn-scout/src/playwright/fixtures/scope/worker/core_fixtures.ts +++ b/src/platform/packages/shared/kbn-scout/src/playwright/fixtures/scope/worker/core_fixtures.ts @@ -8,9 +8,9 @@ */ import { test as base } from '@playwright/test'; -import { SamlSessionManager } from '@kbn/test'; -import { KbnClient } from '@kbn/kbn-client'; -import { Client } from '@elastic/elasticsearch'; +import type { KbnClient } from '@kbn/kbn-client'; +import type { SamlSessionManager } from '@kbn/test-saml-auth'; +import type { Client } from '@elastic/elasticsearch'; import { createKbnUrl, getEsClient, @@ -30,7 +30,7 @@ import type { ScoutTestConfig } from '.'; // re-export to import types from '@kbn-scout' export type { KbnClient } from '@kbn/kbn-client'; -export type { SamlSessionManager } from '@kbn/test'; +export type { SamlSessionManager } from '@kbn/test-saml-auth'; export type { Client as EsClient } from '@elastic/elasticsearch'; export type { KibanaUrl } from '../../../../common/services/kibana_url'; export type { ScoutTestConfig } from '../../../../types'; diff --git a/src/platform/packages/shared/kbn-scout/tsconfig.json b/src/platform/packages/shared/kbn-scout/tsconfig.json index 149f86aa2804a..94d77ae79d98b 100644 --- a/src/platform/packages/shared/kbn-scout/tsconfig.json +++ b/src/platform/packages/shared/kbn-scout/tsconfig.json @@ -24,6 +24,7 @@ "@kbn/dev-proc-runner", "@kbn/kbn-client", "@kbn/test", + "@kbn/test-saml-auth", "@kbn/es-archiver", "@kbn/dev-utils", "@kbn/mock-idp-utils", diff --git a/src/platform/packages/shared/kbn-test/src/auth/index.ts b/src/platform/packages/shared/kbn-test-saml-auth/index.ts similarity index 88% rename from src/platform/packages/shared/kbn-test/src/auth/index.ts rename to src/platform/packages/shared/kbn-test-saml-auth/index.ts index b16ddc6951944..8bc70f74c2112 100644 --- a/src/platform/packages/shared/kbn-test/src/auth/index.ts +++ b/src/platform/packages/shared/kbn-test-saml-auth/index.ts @@ -12,4 +12,6 @@ export { type GetCookieOptions, type HostOptions, type SamlSessionManagerOptions, -} from './session_manager'; +} from './src/session_manager'; + +export type { Role } from './src/types'; diff --git a/src/platform/packages/shared/kbn-test-saml-auth/jest.config.js b/src/platform/packages/shared/kbn-test-saml-auth/jest.config.js new file mode 100644 index 0000000000000..62c5c0d313021 --- /dev/null +++ b/src/platform/packages/shared/kbn-test-saml-auth/jest.config.js @@ -0,0 +1,14 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +module.exports = { + preset: '@kbn/test', + rootDir: '../../../../..', + roots: ['/src/platform/packages/shared/kbn-test-saml-auth'], +}; diff --git a/src/platform/packages/shared/kbn-test-saml-auth/kibana.jsonc b/src/platform/packages/shared/kbn-test-saml-auth/kibana.jsonc new file mode 100644 index 0000000000000..cf6ce2183be95 --- /dev/null +++ b/src/platform/packages/shared/kbn-test-saml-auth/kibana.jsonc @@ -0,0 +1,10 @@ +{ + "type": "shared-common", + "id": "@kbn/test-saml-auth", + "owner": [ + "@elastic/appex-qa" + ], + "group": "platform", + "visibility": "shared", + "devOnly": true +} diff --git a/src/platform/packages/shared/kbn-test-saml-auth/moon.yml b/src/platform/packages/shared/kbn-test-saml-auth/moon.yml new file mode 100644 index 0000000000000..355bea3dae7a5 --- /dev/null +++ b/src/platform/packages/shared/kbn-test-saml-auth/moon.yml @@ -0,0 +1,58 @@ +# This file is generated by the @kbn/moon package. Any manual edits will be erased! +# To extend this, write your extensions/overrides to 'moon.extend.yml' +# then regenerate this file with: 'node scripts/regenerate_moon_projects.js --update --filter @kbn/test-saml-auth' + +$schema: https://moonrepo.dev/schemas/project.json +id: '@kbn/test-saml-auth' +layer: unknown +owners: + defaultOwner: '@elastic/appex-qa' +toolchains: + default: node +language: typescript +project: + title: '@kbn/test-saml-auth' + description: Moon project for @kbn/test-saml-auth + channel: '' + owner: '@elastic/appex-qa' + sourceRoot: src/platform/packages/shared/kbn-test-saml-auth +dependsOn: + - '@kbn/es' + - '@kbn/mock-idp-utils' + - '@kbn/tooling-log' + - '@kbn/repo-info' +tags: + - shared-common + - package + - dev + - group-platform + - shared + - jest-unit-tests +fileGroups: + src: + - '**/*.ts' + - '**/*.js' + - '!target/**/*' +tasks: + jest: + command: node + args: + - '--no-experimental-require-module' + - $workspaceRoot/scripts/jest + - '--config' + - $projectRoot/jest.config.js + options: + runFromWorkspaceRoot: true + inputs: + - '@group(src)' + jestCI: + command: node + args: + - '--no-experimental-require-module' + - $workspaceRoot/scripts/jest + - '--config' + - $projectRoot/jest.config.js + options: + runFromWorkspaceRoot: true + inputs: + - '@group(src)' diff --git a/src/platform/packages/shared/kbn-test-saml-auth/package.json b/src/platform/packages/shared/kbn-test-saml-auth/package.json new file mode 100644 index 0000000000000..15e1ed1b827f1 --- /dev/null +++ b/src/platform/packages/shared/kbn-test-saml-auth/package.json @@ -0,0 +1,7 @@ +{ + "name": "@kbn/test-saml-auth", + "author": "Operations", + "version": "1.0.0", + "private": true, + "license": "Elastic License 2.0 OR AGPL-3.0-only OR SSPL-1.0" +} diff --git a/src/platform/packages/shared/kbn-test-saml-auth/src/fetch_kibana_version.test.ts b/src/platform/packages/shared/kbn-test-saml-auth/src/fetch_kibana_version.test.ts new file mode 100644 index 0000000000000..8a6775d9a72bf --- /dev/null +++ b/src/platform/packages/shared/kbn-test-saml-auth/src/fetch_kibana_version.test.ts @@ -0,0 +1,71 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import axios from 'axios'; +import { ToolingLog } from '@kbn/tooling-log'; +import { fetchKibanaVersionHeaderString } from './fetch_kibana_version'; + +jest.mock('axios'); +const mockedAxios = axios as jest.Mocked; + +describe('fetchKibanaVersionHeaderString', () => { + const log = new ToolingLog(); + + beforeEach(() => { + jest.resetAllMocks(); + }); + + test('returns version.number and appends -SNAPSHOT when build_snapshot is true', async () => { + mockedAxios.request.mockResolvedValue({ + data: { + version: { number: '9.0.0', build_snapshot: true }, + }, + }); + + const v = await fetchKibanaVersionHeaderString( + 'https://localhost:5601', + 'elastic', + 'changeme', + log + ); + + expect(v).toBe('9.0.0-SNAPSHOT'); + expect(mockedAxios.request).toHaveBeenCalledTimes(1); + expect(mockedAxios.request).toHaveBeenCalledWith( + expect.objectContaining({ + method: 'GET', + auth: { username: 'elastic', password: 'changeme' }, + validateStatus: expect.any(Function), + }) + ); + const callUrl = mockedAxios.request.mock.calls[0][0].url as string; + expect(callUrl).toContain('/api/status'); + expect(callUrl).toContain('v8format=true'); + }); + + test('throws when version is missing from response body', async () => { + mockedAxios.request.mockResolvedValue({ data: {} }); + + await expect( + fetchKibanaVersionHeaderString('http://localhost:5601', 'u', 'p', log) + ).rejects.toThrow(/Unable to get version from Kibana/); + + expect(mockedAxios.request).toHaveBeenCalledTimes(1); + }); + + test('propagates axios errors after a single attempt', async () => { + mockedAxios.request.mockRejectedValue(new Error('network down')); + + await expect( + fetchKibanaVersionHeaderString('http://localhost:5601', 'u', 'p', log) + ).rejects.toThrow('network down'); + + expect(mockedAxios.request).toHaveBeenCalledTimes(1); + }); +}); diff --git a/src/platform/packages/shared/kbn-test-saml-auth/src/fetch_kibana_version.ts b/src/platform/packages/shared/kbn-test-saml-auth/src/fetch_kibana_version.ts new file mode 100644 index 0000000000000..8898826da419a --- /dev/null +++ b/src/platform/packages/shared/kbn-test-saml-auth/src/fetch_kibana_version.ts @@ -0,0 +1,64 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +import https from 'https'; +import axios from 'axios'; +import type { ToolingLog } from '@kbn/tooling-log'; + +interface KibanaStatusResponse { + version?: { + number: string; + build_snapshot: boolean; + }; +} + +/** + * Fetches Kibana version string in the same shape as @kbn/kbn-client KbnClientVersion.get() + * (for use as the `kbn-version` header on SAML requests). Single GET to `/api/status`; no retries. + */ +export async function fetchKibanaVersionHeaderString( + kbnBaseUrl: string, + username: string, + password: string, + log: ToolingLog +): Promise { + const base = kbnBaseUrl.endsWith('/') ? kbnBaseUrl : `${kbnBaseUrl}/`; + const url = new URL('api/status', base); + url.searchParams.set('v8format', 'true'); + + const isHttps = url.protocol === 'https:'; + const httpsAgent = isHttps + ? new https.Agent({ + rejectUnauthorized: false, + }) + : undefined; + + log.debug(`Fetching Kibana version from ${url.origin}/api/status`); + + const response = await axios.request({ + method: 'GET', + url: url.toString(), + auth: { username, password }, + headers: { + 'kbn-xsrf': 'kbn-client', + 'x-elastic-internal-origin': 'kbn-client', + }, + httpsAgent, + validateStatus: (status: number) => status === 200 || status === 503, + }); + + const data = response.data; + if (!data?.version) { + throw new Error( + `Unable to get version from Kibana, invalid response from server: ${JSON.stringify(data)}` + ); + } + + return data.version.number + (data.version.build_snapshot ? '-SNAPSHOT' : ''); +} diff --git a/src/platform/packages/shared/kbn-test/src/auth/helper.ts b/src/platform/packages/shared/kbn-test-saml-auth/src/helper.ts similarity index 100% rename from src/platform/packages/shared/kbn-test/src/auth/helper.ts rename to src/platform/packages/shared/kbn-test-saml-auth/src/helper.ts diff --git a/src/platform/packages/shared/kbn-test/src/auth/saml_auth.test.ts b/src/platform/packages/shared/kbn-test-saml-auth/src/saml_auth.test.ts similarity index 100% rename from src/platform/packages/shared/kbn-test/src/auth/saml_auth.test.ts rename to src/platform/packages/shared/kbn-test-saml-auth/src/saml_auth.test.ts diff --git a/src/platform/packages/shared/kbn-test/src/auth/saml_auth.ts b/src/platform/packages/shared/kbn-test-saml-auth/src/saml_auth.ts similarity index 100% rename from src/platform/packages/shared/kbn-test/src/auth/saml_auth.ts rename to src/platform/packages/shared/kbn-test-saml-auth/src/saml_auth.ts diff --git a/src/platform/packages/shared/kbn-test/src/auth/session_manager.test.ts b/src/platform/packages/shared/kbn-test-saml-auth/src/session_manager.test.ts similarity index 96% rename from src/platform/packages/shared/kbn-test/src/auth/session_manager.test.ts rename to src/platform/packages/shared/kbn-test-saml-auth/src/session_manager.test.ts index 8c7d0945388f7..889464f7ed609 100644 --- a/src/platform/packages/shared/kbn-test/src/auth/session_manager.test.ts +++ b/src/platform/packages/shared/kbn-test-saml-auth/src/session_manager.test.ts @@ -10,8 +10,18 @@ import { ToolingLog } from '@kbn/tooling-log'; import crypto from 'crypto'; import { Cookie } from 'tough-cookie'; +import { fetchKibanaVersionHeaderString } from './fetch_kibana_version'; import { Session } from './saml_auth'; -import { SamlSessionManager, SupportedRoles } from './session_manager'; +import type { SupportedRoles } from './session_manager'; +import { SamlSessionManager } from './session_manager'; + +jest.mock('./fetch_kibana_version', () => ({ + fetchKibanaVersionHeaderString: jest.fn(), +})); + +const mockedFetchKibanaVersionHeaderString = fetchKibanaVersionHeaderString as jest.MockedFunction< + typeof fetchKibanaVersionHeaderString +>; import * as samlAuth from './saml_auth'; import * as helper from './helper'; import { Role, User, UserProfile } from './types'; @@ -35,13 +45,6 @@ const readCloudUsersFromFileMock = jest.spyOn(helper, 'readCloudUsersFromFile'); const getTestToken = () => 'kbn_cookie_' + crypto.randomBytes(16).toString('hex'); -jest.mock('@kbn/kbn-client', () => { - return { - KbnClient: jest.fn(), - }; -}); -const get = jest.fn(); - describe('SamlSessionManager', () => { let createCloudSAMLSessionMock: jest.SpyInstance; beforeEach(() => { @@ -51,10 +54,6 @@ describe('SamlSessionManager', () => { describe('for local session', () => { beforeEach(() => { jest.resetAllMocks(); - jest - .requireMock('@kbn/kbn-client') - .KbnClient.mockImplementation(() => ({ version: { get } })); - get.mockImplementation(() => Promise.resolve('8.12.0')); createLocalSAMLSessionMock.mockResolvedValue(new Session(cookieInstance, testEmail)); }); @@ -235,10 +234,6 @@ describe('SamlSessionManager', () => { describe('handles errors', () => { beforeEach(() => { jest.resetAllMocks(); - jest - .requireMock('@kbn/kbn-client') - .KbnClient.mockImplementation(() => ({ version: { get } })); - get.mockImplementationOnce(() => Promise.resolve('8.12.0')); readCloudUsersFromFileMock.mockReturnValue(cloudUsers); delete process.env.TEST_CLOUD_HOST_NAME; // Ensure variable is unset @@ -261,11 +256,8 @@ describe('SamlSessionManager', () => { beforeEach(() => { jest.resetAllMocks(); - jest - .requireMock('@kbn/kbn-client') - .KbnClient.mockImplementation(() => ({ version: { get } })); - get.mockImplementationOnce(() => Promise.resolve('8.12.0')); + mockedFetchKibanaVersionHeaderString.mockResolvedValue('8.12.0'); createCloudSAMLSessionMock.mockResolvedValue(new Session(cloudCookieInstance, cloudEmail)); readCloudUsersFromFileMock.mockReturnValue(cloudUsers); delete process.env.TEST_CLOUD_HOST_NAME; diff --git a/src/platform/packages/shared/kbn-test/src/auth/session_manager.ts b/src/platform/packages/shared/kbn-test-saml-auth/src/session_manager.ts similarity index 91% rename from src/platform/packages/shared/kbn-test/src/auth/session_manager.ts rename to src/platform/packages/shared/kbn-test-saml-auth/src/session_manager.ts index c11ce9b29f400..6692e04cc70bf 100644 --- a/src/platform/packages/shared/kbn-test/src/auth/session_manager.ts +++ b/src/platform/packages/shared/kbn-test-saml-auth/src/session_manager.ts @@ -9,7 +9,7 @@ import { ToolingLog } from '@kbn/tooling-log'; import Url from 'url'; -import { KbnClient } from '@kbn/kbn-client'; +import { fetchKibanaVersionHeaderString } from './fetch_kibana_version'; import { isValidHostname, readCloudUsersFromFile } from './helper'; import { createCloudSAMLSession, @@ -52,7 +52,9 @@ export interface GetCookieOptions { export class SamlSessionManager { private readonly isCloud: boolean; private readonly kbnHost: string; - private readonly kbnClient: KbnClient; + private readonly kbnUsername: string; + private readonly kbnPassword: string; + private kbnVersionResolved?: string; private readonly log: ToolingLog; private readonly roleToUserMap: Map; private readonly sessionCache: Map; @@ -68,18 +70,13 @@ export class SamlSessionManager { port: options.hostOptions.port, }; this.kbnHost = Url.format(hostOptionsWithoutAuth); + this.kbnUsername = options.hostOptions.username; + this.kbnPassword = options.hostOptions.password; this.isCloud = options.isCloud; this.cloudHostName = options.cloudHostName || process.env.TEST_CLOUD_HOST_NAME; if (this.isCloud) { this.validateCloudHostName(); } - this.kbnClient = new KbnClient({ - log: this.log, - url: Url.format({ - ...hostOptionsWithoutAuth, - auth: `${options.hostOptions.username}:${options.hostOptions.password}`, - }), - }); this.cloudUsersFilePath = options.cloudUsersFilePath; this.sessionCache = new Map(); this.roleToUserMap = new Map(); @@ -87,6 +84,20 @@ export class SamlSessionManager { this.validateCloudSetting(); } + private async getKibanaVersionForCloudSaml(): Promise { + if (this.kbnVersionResolved !== undefined) { + return this.kbnVersionResolved; + } + const version = await fetchKibanaVersionHeaderString( + this.kbnHost, + this.kbnUsername, + this.kbnPassword, + this.log + ); + this.kbnVersionResolved = version; + return version; + } + private validateCloudHostName() { if (!this.cloudHostName) { throw new Error( @@ -166,7 +177,7 @@ Set env variable 'TEST_CLOUD=1' to run FTR against your Cloud deployment` if (this.isCloud) { this.log.debug(`Creating new cloud SAML session for role '${role}'`); - const kbnVersion = await this.kbnClient.version.get(); + const kbnVersion = await this.getKibanaVersionForCloudSaml(); const { email, password } = this.getCloudUserByRole(role); session = await createCloudSAMLSession({ hostname: this.cloudHostName!, diff --git a/src/platform/packages/shared/kbn-test/src/auth/types.ts b/src/platform/packages/shared/kbn-test-saml-auth/src/types.ts similarity index 100% rename from src/platform/packages/shared/kbn-test/src/auth/types.ts rename to src/platform/packages/shared/kbn-test-saml-auth/src/types.ts diff --git a/src/platform/packages/shared/kbn-test-saml-auth/tsconfig.json b/src/platform/packages/shared/kbn-test-saml-auth/tsconfig.json new file mode 100644 index 0000000000000..d1bf1171fbff2 --- /dev/null +++ b/src/platform/packages/shared/kbn-test-saml-auth/tsconfig.json @@ -0,0 +1,16 @@ +{ + "extends": "@kbn/tsconfig-base/tsconfig.json", + "compilerOptions": { + "outDir": "target/types", + "stripInternal": true, + "types": ["jest", "node"] + }, + "include": ["**/*.ts", "**/*.js"], + "exclude": ["target/**/*"], + "kbn_references": [ + "@kbn/es", + "@kbn/mock-idp-utils", + "@kbn/tooling-log", + "@kbn/repo-info" + ] +} diff --git a/src/platform/packages/shared/kbn-test/index.ts b/src/platform/packages/shared/kbn-test/index.ts index e16f6d0e997e2..3043536b777f6 100644 --- a/src/platform/packages/shared/kbn-test/index.ts +++ b/src/platform/packages/shared/kbn-test/index.ts @@ -30,7 +30,8 @@ export { type SamlSessionManagerOptions, type HostOptions, type GetCookieOptions, -} from './src/auth'; + type Role, +} from '@kbn/test-saml-auth'; export type { CreateTestEsClusterOptions, diff --git a/src/platform/packages/shared/kbn-test/moon.yml b/src/platform/packages/shared/kbn-test/moon.yml index 699fdef1d03b6..fdf00a15a872e 100644 --- a/src/platform/packages/shared/kbn-test/moon.yml +++ b/src/platform/packages/shared/kbn-test/moon.yml @@ -33,7 +33,7 @@ dependsOn: - '@kbn/stdio-dev-helpers' - '@kbn/babel-register' - '@kbn/repo-packages' - - '@kbn/mock-idp-utils' + - '@kbn/test-saml-auth' - '@kbn/code-owners' - '@kbn/scout-reporting' - '@kbn/scout-info' diff --git a/src/platform/packages/shared/kbn-test/tsconfig.json b/src/platform/packages/shared/kbn-test/tsconfig.json index 654991682d09d..9437814d38ab1 100644 --- a/src/platform/packages/shared/kbn-test/tsconfig.json +++ b/src/platform/packages/shared/kbn-test/tsconfig.json @@ -35,7 +35,7 @@ "@kbn/stdio-dev-helpers", "@kbn/babel-register", "@kbn/repo-packages", - "@kbn/mock-idp-utils", + "@kbn/test-saml-auth", "@kbn/code-owners", "@kbn/scout-reporting", "@kbn/scout-info", diff --git a/tsconfig.base.json b/tsconfig.base.json index 47183c48f5fba..aa4acfd8c2bc3 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -2042,6 +2042,8 @@ "@kbn/test-feature-usage-plugin/*": ["x-pack/platform/test/licensing_plugin/plugins/test_feature_usage/*"], "@kbn/test-jest-helpers": ["src/platform/packages/shared/kbn-test-jest-helpers"], "@kbn/test-jest-helpers/*": ["src/platform/packages/shared/kbn-test-jest-helpers/*"], + "@kbn/test-saml-auth": ["src/platform/packages/shared/kbn-test-saml-auth"], + "@kbn/test-saml-auth/*": ["src/platform/packages/shared/kbn-test-saml-auth/*"], "@kbn/test-subj-selector": ["src/platform/packages/shared/kbn-test-subj-selector"], "@kbn/test-subj-selector/*": ["src/platform/packages/shared/kbn-test-subj-selector/*"], "@kbn/test-suites-security-solution-apis": ["x-pack/solutions/security/test/security_solution_api_integration"], diff --git a/x-pack/solutions/security/test/security_solution_cypress/cypress/support/saml_auth.ts b/x-pack/solutions/security/test/security_solution_cypress/cypress/support/saml_auth.ts index 7cf0d036c1e87..ce04103eb9e9d 100644 --- a/x-pack/solutions/security/test/security_solution_cypress/cypress/support/saml_auth.ts +++ b/x-pack/solutions/security/test/security_solution_cypress/cypress/support/saml_auth.ts @@ -9,8 +9,9 @@ import type { Role } from '@kbn/security-plugin-types-common'; import { ToolingLog } from '@kbn/tooling-log'; -import { SecurityRoleName } from '@kbn/security-solution-plugin/common/test'; -import { HostOptions, SamlSessionManager } from '@kbn/test'; +import type { SecurityRoleName } from '@kbn/security-solution-plugin/common/test'; +import type { HostOptions } from '@kbn/test-saml-auth'; +import { SamlSessionManager } from '@kbn/test-saml-auth'; import { REPO_ROOT } from '@kbn/repo-info'; import { resolve } from 'path'; import axios from 'axios'; diff --git a/x-pack/solutions/security/test/security_solution_cypress/cypress/tsconfig.json b/x-pack/solutions/security/test/security_solution_cypress/cypress/tsconfig.json index 9e8e0fd768428..d371cbb43ae09 100644 --- a/x-pack/solutions/security/test/security_solution_cypress/cypress/tsconfig.json +++ b/x-pack/solutions/security/test/security_solution_cypress/cypress/tsconfig.json @@ -39,6 +39,7 @@ "@kbn/elastic-assistant-common", "@kbn/cloud-security-posture-common", "@kbn/security-plugin-types-common", - "@kbn/securitysolution-utils" + "@kbn/securitysolution-utils", + "@kbn/test-saml-auth" ] } diff --git a/yarn.lock b/yarn.lock index d1359ba426bd5..d7b3b7d639bc3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7987,6 +7987,10 @@ version "0.0.0" uid "" +"@kbn/test-saml-auth@link:src/platform/packages/shared/kbn-test-saml-auth": + version "0.0.0" + uid "" + "@kbn/test-subj-selector@link:src/platform/packages/shared/kbn-test-subj-selector": version "0.0.0" uid ""