From 305d466c18474fa23ff30940d8dc25373501ab23 Mon Sep 17 00:00:00 2001 From: Brad White Date: Wed, 15 Nov 2023 12:20:16 -0700 Subject: [PATCH] Revert "Add mock identity provider for serverless (#170852)" This reverts commit 1fb0313a5262caf2881af3d81992f914461cdfb2. --- .github/CODEOWNERS | 1 - package.json | 1 - .../kbn-es/src/cli_commands/serverless.ts | 3 +- packages/kbn-es/src/paths.ts | 3 - packages/kbn-es/src/utils/docker.test.ts | 106 +------- packages/kbn-es/src/utils/docker.ts | 148 +++-------- packages/kbn-es/tsconfig.json | 11 +- .../kbn-mock-idp-plugin/common/constants.ts | 24 -- packages/kbn-mock-idp-plugin/common/index.ts | 27 -- packages/kbn-mock-idp-plugin/common/utils.ts | 231 ------------------ packages/kbn-mock-idp-plugin/kibana.jsonc | 11 - packages/kbn-mock-idp-plugin/package.json | 6 - packages/kbn-mock-idp-plugin/server/index.ts | 9 - packages/kbn-mock-idp-plugin/server/plugin.ts | 120 --------- packages/kbn-mock-idp-plugin/tsconfig.json | 18 -- scripts/es.js | 1 - src/cli/serve/serve.js | 24 +- src/cli/tsconfig.json | 1 - tsconfig.base.json | 2 - yarn.lock | 4 - 20 files changed, 41 insertions(+), 710 deletions(-) delete mode 100644 packages/kbn-mock-idp-plugin/common/constants.ts delete mode 100644 packages/kbn-mock-idp-plugin/common/index.ts delete mode 100644 packages/kbn-mock-idp-plugin/common/utils.ts delete mode 100644 packages/kbn-mock-idp-plugin/kibana.jsonc delete mode 100644 packages/kbn-mock-idp-plugin/package.json delete mode 100644 packages/kbn-mock-idp-plugin/server/index.ts delete mode 100644 packages/kbn-mock-idp-plugin/server/plugin.ts delete mode 100644 packages/kbn-mock-idp-plugin/tsconfig.json diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index d5c7d162278f29e..d0f6c72f29a818e 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -534,7 +534,6 @@ x-pack/packages/ml/runtime_field_utils @elastic/ml-ui x-pack/packages/ml/string_hash @elastic/ml-ui x-pack/packages/ml/trained_models_utils @elastic/ml-ui x-pack/packages/ml/url_state @elastic/ml-ui -packages/kbn-mock-idp-plugin @elastic/kibana-security packages/kbn-monaco @elastic/appex-sharedux x-pack/plugins/monitoring_collection @elastic/obs-ux-infra_services-team x-pack/plugins/monitoring @elastic/obs-ux-infra_services-team diff --git a/package.json b/package.json index 779ee0751d8a687..843a2eca9a5b03b 100644 --- a/package.json +++ b/package.json @@ -1233,7 +1233,6 @@ "@kbn/managed-vscode-config": "link:packages/kbn-managed-vscode-config", "@kbn/managed-vscode-config-cli": "link:packages/kbn-managed-vscode-config-cli", "@kbn/management-storybook-config": "link:packages/kbn-management/storybook/config", - "@kbn/mock-idp-plugin": "link:packages/kbn-mock-idp-plugin", "@kbn/openapi-generator": "link:packages/kbn-openapi-generator", "@kbn/optimizer": "link:packages/kbn-optimizer", "@kbn/optimizer-webpack-helpers": "link:packages/kbn-optimizer-webpack-helpers", diff --git a/packages/kbn-es/src/cli_commands/serverless.ts b/packages/kbn-es/src/cli_commands/serverless.ts index 0743cf2e7b5b690..87a573a8810dd7d 100644 --- a/packages/kbn-es/src/cli_commands/serverless.ts +++ b/packages/kbn-es/src/cli_commands/serverless.ts @@ -38,7 +38,6 @@ export const serverless: Command = { --host Publish ES docker container on additional host IP --port The port to bind to on 127.0.0.1 [default: ${DEFAULT_PORT}] --ssl Enable HTTP SSL on the ES cluster - --kibanaUrl Fully qualified URL where Kibana is hosted (including base path). [default: https://localhost:5601/] --skipTeardown If this process exits, leave the ES cluster running in the background --waitForReady Wait for the ES cluster to be ready to serve requests --resources Overrides resources under ES 'config/' directory, which are by default @@ -74,7 +73,7 @@ export const serverless: Command = { files: 'F', }, - string: ['tag', 'image', 'basePath', 'resources', 'host', 'kibanaUrl'], + string: ['tag', 'image', 'basePath', 'resources', 'host'], boolean: ['clean', 'ssl', 'kill', 'background', 'skipTeardown', 'waitForReady'], default: defaults, diff --git a/packages/kbn-es/src/paths.ts b/packages/kbn-es/src/paths.ts index 4da4448573384b5..d9b4be41aa15be0 100644 --- a/packages/kbn-es/src/paths.ts +++ b/packages/kbn-es/src/paths.ts @@ -8,7 +8,6 @@ import Os from 'os'; import { resolve } from 'path'; -import { REPO_ROOT } from '@kbn/repo-info'; function maybeUseBat(bin: string) { return Os.platform().startsWith('win') ? `${bin}.bat` : bin; @@ -52,8 +51,6 @@ export const SERVERLESS_SECRETS_SSL_PATH = resolve( export const SERVERLESS_JWKS_PATH = resolve(__dirname, './serverless_resources/jwks.json'); -export const SERVERLESS_IDP_METADATA_PATH = resolve(REPO_ROOT, '.es', 'idp_metadata.xml'); - export const SERVERLESS_RESOURCES_PATHS = [ SERVERLESS_OPERATOR_USERS_PATH, SERVERLESS_ROLE_MAPPING_PATH, diff --git a/packages/kbn-es/src/utils/docker.test.ts b/packages/kbn-es/src/utils/docker.test.ts index b574447a20508ba..2d71a4e628e1183 100644 --- a/packages/kbn-es/src/utils/docker.test.ts +++ b/packages/kbn-es/src/utils/docker.test.ts @@ -32,17 +32,15 @@ import { ServerlessOptions, } from './docker'; import { ToolingLog, ToolingLogCollectingWriter } from '@kbn/tooling-log'; -import { CA_CERT_PATH, ES_P12_PATH } from '@kbn/dev-utils'; +import { ES_P12_PATH } from '@kbn/dev-utils'; import { SERVERLESS_CONFIG_PATH, SERVERLESS_RESOURCES_PATHS, SERVERLESS_SECRETS_PATH, SERVERLESS_JWKS_PATH, - SERVERLESS_IDP_METADATA_PATH, } from '../paths'; import * as waitClusterUtil from './wait_until_cluster_ready'; import * as waitForSecurityIndexUtil from './wait_for_security_index'; -import * as mockIdpPluginUtil from '@kbn/mock-idp-plugin/common'; jest.mock('execa'); const execa = jest.requireMock('execa'); @@ -60,8 +58,6 @@ jest.mock('./wait_for_security_index', () => ({ waitForSecurityIndex: jest.fn(), })); -jest.mock('@kbn/mock-idp-plugin/common'); - const log = new ToolingLog(); const logWriter = new ToolingLogCollectingWriter(); log.setWriters([logWriter]); @@ -73,8 +69,6 @@ const serverlessObjectStorePath = `${baseEsPath}/${serverlessDir}`; const waitUntilClusterReadyMock = jest.spyOn(waitClusterUtil, 'waitUntilClusterReady'); const waitForSecurityIndexMock = jest.spyOn(waitForSecurityIndexUtil, 'waitForSecurityIndex'); -const ensureSAMLRoleMappingMock = jest.spyOn(mockIdpPluginUtil, 'ensureSAMLRoleMapping'); -const createMockIdpMetadataMock = jest.spyOn(mockIdpPluginUtil, 'createMockIdpMetadata'); beforeEach(() => { jest.resetAllMocks(); @@ -429,66 +423,6 @@ describe('resolveEsArgs()', () => { ] `); }); - - test('should add SAML realm args when kibanaUrl and SSL are passed', () => { - const esArgs = resolveEsArgs([], { - ssl: true, - kibanaUrl: 'https://localhost:5601/', - }); - - expect(esArgs).toHaveLength(26); - expect(esArgs).toMatchInlineSnapshot(` - Array [ - "--env", - "xpack.security.http.ssl.enabled=true", - "--env", - "xpack.security.http.ssl.keystore.path=/usr/share/elasticsearch/config/certs/elasticsearch.p12", - "--env", - "xpack.security.http.ssl.verification_mode=certificate", - "--env", - "xpack.security.authc.realms.saml.mock-idp.order=0", - "--env", - "xpack.security.authc.realms.saml.mock-idp.idp.metadata.path=/usr/share/elasticsearch/config/secrets/idp_metadata.xml", - "--env", - "xpack.security.authc.realms.saml.mock-idp.idp.entity_id=urn:mock-idp", - "--env", - "xpack.security.authc.realms.saml.mock-idp.sp.entity_id=https://localhost:5601", - "--env", - "xpack.security.authc.realms.saml.mock-idp.sp.acs=https://localhost:5601/api/security/saml/callback", - "--env", - "xpack.security.authc.realms.saml.mock-idp.sp.logout=https://localhost:5601/logout", - "--env", - "xpack.security.authc.realms.saml.mock-idp.attributes.principal=http://saml.elastic-cloud.com/attributes/principal", - "--env", - "xpack.security.authc.realms.saml.mock-idp.attributes.groups=http://saml.elastic-cloud.com/attributes/roles", - "--env", - "xpack.security.authc.realms.saml.mock-idp.attributes.name=http://saml.elastic-cloud.com/attributes/email", - "--env", - "xpack.security.authc.realms.saml.mock-idp.attributes.mail=http://saml.elastic-cloud.com/attributes/name", - ] - `); - }); - - test('should not add SAML realm args when security is disabled', () => { - const esArgs = resolveEsArgs([['xpack.security.enabled', 'false']], { - ssl: true, - kibanaUrl: 'https://localhost:5601/', - }); - - expect(esArgs).toHaveLength(8); - expect(esArgs).toMatchInlineSnapshot(` - Array [ - "--env", - "xpack.security.enabled=false", - "--env", - "xpack.security.http.ssl.enabled=true", - "--env", - "xpack.security.http.ssl.keystore.path=/usr/share/elasticsearch/config/certs/elasticsearch.p12", - "--env", - "xpack.security.http.ssl.verification_mode=certificate", - ] - `); - }); }); describe('setupServerlessVolumes()', () => { @@ -529,29 +463,21 @@ describe('setupServerlessVolumes()', () => { expect(existsSync(`${serverlessObjectStorePath}/cluster_state/lease`)).toBe(false); }); - test('should add SSL and IDP metadata volumes when ssl and kibanaUrl are passed', async () => { + test('should add SSL volumes when ssl is passed', async () => { mockFs(existingObjectStore); - createMockIdpMetadataMock.mockResolvedValue(''); - const volumeCmd = await setupServerlessVolumes(log, { - basePath: baseEsPath, - ssl: true, - kibanaUrl: 'https://localhost:5603/', - }); - - expect(createMockIdpMetadataMock).toHaveBeenCalledTimes(1); - expect(createMockIdpMetadataMock).toHaveBeenCalledWith('https://localhost:5603/'); + const volumeCmd = await setupServerlessVolumes(log, { basePath: baseEsPath, ssl: true }); const requiredPaths = [ `${baseEsPath}:/objectstore:z`, - SERVERLESS_IDP_METADATA_PATH, ES_P12_PATH, ...SERVERLESS_RESOURCES_PATHS, ]; const pathsNotIncludedInCmd = requiredPaths.filter( (path) => !volumeCmd.some((cmd) => cmd.includes(path)) ); - expect(volumeCmd).toHaveLength(22); + + expect(volumeCmd).toHaveLength(20); expect(pathsNotIncludedInCmd).toEqual([]); }); @@ -617,7 +543,6 @@ describe('runServerlessEsNode()', () => { describe('runServerlessCluster()', () => { test('should start 3 serverless nodes', async () => { - waitUntilClusterReadyMock.mockResolvedValue(); mockFs({ [baseEsPath]: {}, }); @@ -642,27 +567,7 @@ describe('runServerlessCluster()', () => { expect(waitUntilClusterReadyMock.mock.calls[0][0].readyTimeout).toEqual(undefined); }); - test(`should create SAML role mapping when ssl and kibanaUrl are passed`, async () => { - waitUntilClusterReadyMock.mockResolvedValue(); - mockFs({ - [CA_CERT_PATH]: '', - [baseEsPath]: {}, - }); - execa.mockImplementation(() => Promise.resolve({ stdout: '' })); - createMockIdpMetadataMock.mockResolvedValue(''); - - await runServerlessCluster(log, { - basePath: baseEsPath, - waitForReady: true, - ssl: true, - kibanaUrl: 'https://localhost:5601/', - }); - - expect(ensureSAMLRoleMappingMock).toHaveBeenCalledTimes(1); - }); - test(`should wait for the security index`, async () => { - waitUntilClusterReadyMock.mockResolvedValue(); waitForSecurityIndexMock.mockResolvedValue(); mockFs({ [baseEsPath]: {}, @@ -675,7 +580,6 @@ describe('runServerlessCluster()', () => { }); test(`should not wait for the security index when security is disabled`, async () => { - waitUntilClusterReadyMock.mockResolvedValue(); mockFs({ [baseEsPath]: {}, }); diff --git a/packages/kbn-es/src/utils/docker.ts b/packages/kbn-es/src/utils/docker.ts index 73e5e1fc7728840..1c89339e1a56703 100644 --- a/packages/kbn-es/src/utils/docker.ts +++ b/packages/kbn-es/src/utils/docker.ts @@ -14,17 +14,12 @@ import { Client, ClientOptions, HttpConnection } from '@elastic/elasticsearch'; import { ToolingLog } from '@kbn/tooling-log'; import { kibanaPackageJson as pkg, REPO_ROOT } from '@kbn/repo-info'; -import { CA_CERT_PATH, ES_P12_PASSWORD, ES_P12_PATH } from '@kbn/dev-utils'; import { - MOCK_IDP_REALM_NAME, - MOCK_IDP_ENTITY_ID, - MOCK_IDP_ATTRIBUTE_PRINCIPAL, - MOCK_IDP_ATTRIBUTE_ROLES, - MOCK_IDP_ATTRIBUTE_EMAIL, - MOCK_IDP_ATTRIBUTE_NAME, - ensureSAMLRoleMapping, - createMockIdpMetadata, -} from '@kbn/mock-idp-plugin/common'; + CA_CERT_PATH, + ES_P12_PASSWORD, + ES_P12_PATH, + kibanaDevServiceAccount, +} from '@kbn/dev-utils'; import { waitForSecurityIndex } from './wait_for_security_index'; import { createCliError } from '../errors'; @@ -33,7 +28,6 @@ import { SERVERLESS_RESOURCES_PATHS, SERVERLESS_SECRETS_PATH, SERVERLESS_JWKS_PATH, - SERVERLESS_IDP_METADATA_PATH, SERVERLESS_CONFIG_PATH, SERVERLESS_FILES_PATH, SERVERLESS_SECRETS_SSL_PATH, @@ -75,8 +69,6 @@ export interface ServerlessOptions extends EsClusterExecOptions, BaseOptions { background?: boolean; /** Wait for the ES cluster to be ready to serve requests */ waitForReady?: boolean; - /** Fully qualified URL where Kibana is hosted (including base path) */ - kibanaUrl?: string; /** * Resource file(s) to overwrite * (see list of files that can be overwritten under `packages/kbn-es/src/serverless_resources/users`) @@ -468,54 +460,6 @@ export function resolveEsArgs( esArgs.set('ELASTIC_PASSWORD', password); } - // Configure mock identify provider (ES only supports SAML when running in SSL mode) - if ( - ssl && - 'kibanaUrl' in options && - options.kibanaUrl && - esArgs.get('xpack.security.enabled') !== 'false' - ) { - const trimTrailingSlash = (url: string) => (url.endsWith('/') ? url.slice(0, -1) : url); - - esArgs.set(`xpack.security.authc.realms.saml.${MOCK_IDP_REALM_NAME}.order`, '0'); - esArgs.set( - `xpack.security.authc.realms.saml.${MOCK_IDP_REALM_NAME}.idp.metadata.path`, - `${SERVERLESS_CONFIG_PATH}secrets/idp_metadata.xml` - ); - esArgs.set( - `xpack.security.authc.realms.saml.${MOCK_IDP_REALM_NAME}.idp.entity_id`, - MOCK_IDP_ENTITY_ID - ); - esArgs.set( - `xpack.security.authc.realms.saml.${MOCK_IDP_REALM_NAME}.sp.entity_id`, - trimTrailingSlash(options.kibanaUrl) - ); - esArgs.set( - `xpack.security.authc.realms.saml.${MOCK_IDP_REALM_NAME}.sp.acs`, - `${trimTrailingSlash(options.kibanaUrl)}/api/security/saml/callback` - ); - esArgs.set( - `xpack.security.authc.realms.saml.${MOCK_IDP_REALM_NAME}.sp.logout`, - `${trimTrailingSlash(options.kibanaUrl)}/logout` - ); - esArgs.set( - `xpack.security.authc.realms.saml.${MOCK_IDP_REALM_NAME}.attributes.principal`, - MOCK_IDP_ATTRIBUTE_PRINCIPAL - ); - esArgs.set( - `xpack.security.authc.realms.saml.${MOCK_IDP_REALM_NAME}.attributes.groups`, - MOCK_IDP_ATTRIBUTE_ROLES - ); - esArgs.set( - `xpack.security.authc.realms.saml.${MOCK_IDP_REALM_NAME}.attributes.name`, - MOCK_IDP_ATTRIBUTE_EMAIL - ); - esArgs.set( - `xpack.security.authc.realms.saml.${MOCK_IDP_REALM_NAME}.attributes.mail`, - MOCK_IDP_ATTRIBUTE_NAME - ); - } - return Array.from(esArgs).flatMap((e) => ['--env', e.join('=')]); } @@ -536,7 +480,7 @@ export function getDockerFileMountPath(hostPath: string) { * Setup local volumes for Serverless ES */ export async function setupServerlessVolumes(log: ToolingLog, options: ServerlessOptions) { - const { basePath, clean, ssl, kibanaUrl, files, resources } = options; + const { basePath, clean, ssl, files, resources } = options; const objectStorePath = resolve(basePath, 'stateless'); log.info(chalk.bold(`Checking for local serverless ES object store at ${objectStorePath}`)); @@ -607,16 +551,6 @@ export async function setupServerlessVolumes(log: ToolingLog, options: Serverles ); } - // Create and add meta data for mock identity provider - if (ssl && kibanaUrl) { - const metadata = await createMockIdpMetadata(kibanaUrl); - await Fsp.writeFile(SERVERLESS_IDP_METADATA_PATH, metadata); - volumeCmds.push( - '--volume', - `${SERVERLESS_IDP_METADATA_PATH}:${SERVERLESS_CONFIG_PATH}secrets/idp_metadata.xml:z` - ); - } - volumeCmds.push( ...getESp12Volume(), ...serverlessResources, @@ -625,6 +559,7 @@ export async function setupServerlessVolumes(log: ToolingLog, options: Serverles `${ ssl ? SERVERLESS_SECRETS_SSL_PATH : SERVERLESS_SECRETS_PATH }:${SERVERLESS_CONFIG_PATH}secrets/secrets.json:z`, + '--volume', `${SERVERLESS_JWKS_PATH}:${SERVERLESS_CONFIG_PATH}secrets/jwks.json:z` ); @@ -726,52 +661,33 @@ export async function runServerlessCluster(log: ToolingLog, options: ServerlessO process.on('SIGINT', () => teardownServerlessClusterSync(log, options)); } - const esNodeUrl = `${options.ssl ? 'https' : 'http'}://${portCmd[1].substring( - 0, - portCmd[1].lastIndexOf(':') - )}`; - - const client = getESClient({ - node: esNodeUrl, - auth: { - username: ELASTIC_SERVERLESS_SUPERUSER, - password: ELASTIC_SERVERLESS_SUPERUSER_PASSWORD, - }, - ...(options.ssl - ? { - tls: { - ca: [fs.readFileSync(CA_CERT_PATH)], - // NOTE: Even though we've added ca into the tls options, we are using 127.0.0.1 instead of localhost - // for the ip which is not validated. As such we are getting the error - // Hostname/IP does not match certificate's altnames: IP: 127.0.0.1 is not in the cert's list: - // To work around that we are overriding the function checkServerIdentity too - checkServerIdentity: () => { - return undefined; - }, - }, - } - : {}), - }); - - const readyPromise = waitUntilClusterReady({ client, expectedStatus: 'green', log }).then( - async () => { - if (!options.ssl || !options.kibanaUrl) { - return; - } - - await ensureSAMLRoleMapping(client); - - log.success( - `Created role mapping for mock identity provider. You can now login using ${chalk.bold.cyan( - MOCK_IDP_REALM_NAME - )} realm` - ); - } - ); - if (options.waitForReady) { log.info('Waiting until ES is ready to serve requests...'); - await readyPromise; + + const esNodeUrl = `${options.ssl ? 'https' : 'http'}://${portCmd[1].substring( + 0, + portCmd[1].lastIndexOf(':') + )}`; + + const client = getESClient({ + node: esNodeUrl, + auth: { bearer: kibanaDevServiceAccount.token }, + ...(options.ssl + ? { + tls: { + ca: [fs.readFileSync(CA_CERT_PATH)], + // NOTE: Even though we've added ca into the tls options, we are using 127.0.0.1 instead of localhost + // for the ip which is not validated. As such we are getting the error + // Hostname/IP does not match certificate's altnames: IP: 127.0.0.1 is not in the cert's list: + // To work around that we are overriding the function checkServerIdentity too + checkServerIdentity: () => { + return undefined; + }, + }, + } + : {}), + }); + await waitUntilClusterReady({ client, expectedStatus: 'green', log }); if (!options.esArgs || !options.esArgs.includes('xpack.security.enabled=false')) { // If security is not disabled, make sure the security index exists before running the test to avoid flakiness await waitForSecurityIndex({ client, log }); diff --git a/packages/kbn-es/tsconfig.json b/packages/kbn-es/tsconfig.json index b40ca33825562d6..75059c2ef69cd72 100644 --- a/packages/kbn-es/tsconfig.json +++ b/packages/kbn-es/tsconfig.json @@ -3,20 +3,13 @@ "compilerOptions": { "outDir": "target/types" }, - "include": [ - "**/*.ts", - "**/*.js", - "**/*.json" - ], - "exclude": [ - "target/**/*" - ], + "include": ["**/*.ts", "**/*.js", "**/*.json"], + "exclude": ["target/**/*"], "kbn_references": [ "@kbn/tooling-log", "@kbn/dev-utils", "@kbn/dev-proc-runner", "@kbn/ci-stats-reporter", - "@kbn/mock-idp-plugin", "@kbn/jest-serializers", "@kbn/repo-info" ] diff --git a/packages/kbn-mock-idp-plugin/common/constants.ts b/packages/kbn-mock-idp-plugin/common/constants.ts deleted file mode 100644 index 6fb54755875746a..000000000000000 --- a/packages/kbn-mock-idp-plugin/common/constants.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * 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 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 or the Server - * Side Public License, v 1. - */ - -import { resolve } from 'path'; - -export const MOCK_IDP_PLUGIN_PATH = resolve(__dirname, '..'); -export const MOCK_IDP_METADATA_PATH = resolve(MOCK_IDP_PLUGIN_PATH, 'metadata.xml'); - -export const MOCK_IDP_LOGIN_PATH = '/mock_idp/login'; -export const MOCK_IDP_LOGOUT_PATH = '/mock_idp/logout'; - -export const MOCK_IDP_REALM_NAME = 'mock-idp'; -export const MOCK_IDP_ENTITY_ID = 'urn:mock-idp'; // Must match `entityID` in `metadata.xml` -export const MOCK_IDP_ROLE_MAPPING_NAME = 'mock-idp-mapping'; - -export const MOCK_IDP_ATTRIBUTE_PRINCIPAL = 'http://saml.elastic-cloud.com/attributes/principal'; -export const MOCK_IDP_ATTRIBUTE_ROLES = 'http://saml.elastic-cloud.com/attributes/roles'; -export const MOCK_IDP_ATTRIBUTE_EMAIL = 'http://saml.elastic-cloud.com/attributes/email'; -export const MOCK_IDP_ATTRIBUTE_NAME = 'http://saml.elastic-cloud.com/attributes/name'; diff --git a/packages/kbn-mock-idp-plugin/common/index.ts b/packages/kbn-mock-idp-plugin/common/index.ts deleted file mode 100644 index aaaffc15f10f8ab..000000000000000 --- a/packages/kbn-mock-idp-plugin/common/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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 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 or the Server - * Side Public License, v 1. - */ - -export { - MOCK_IDP_PLUGIN_PATH, - MOCK_IDP_METADATA_PATH, - MOCK_IDP_LOGIN_PATH, - MOCK_IDP_LOGOUT_PATH, - MOCK_IDP_REALM_NAME, - MOCK_IDP_ENTITY_ID, - MOCK_IDP_ROLE_MAPPING_NAME, - MOCK_IDP_ATTRIBUTE_PRINCIPAL, - MOCK_IDP_ATTRIBUTE_ROLES, - MOCK_IDP_ATTRIBUTE_EMAIL, - MOCK_IDP_ATTRIBUTE_NAME, -} from './constants'; -export { - createMockIdpMetadata, - createSAMLResponse, - ensureSAMLRoleMapping, - parseSAMLAuthnRequest, -} from './utils'; diff --git a/packages/kbn-mock-idp-plugin/common/utils.ts b/packages/kbn-mock-idp-plugin/common/utils.ts deleted file mode 100644 index 5d55fbc56568574..000000000000000 --- a/packages/kbn-mock-idp-plugin/common/utils.ts +++ /dev/null @@ -1,231 +0,0 @@ -/* - * 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 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 or the Server - * Side Public License, v 1. - */ - -import { Client } from '@elastic/elasticsearch'; -import { SignedXml } from 'xml-crypto'; -import { KBN_KEY_PATH, KBN_CERT_PATH } from '@kbn/dev-utils'; -import { readFile } from 'fs/promises'; -import zlib from 'zlib'; -import { promisify } from 'util'; -import { parseString } from 'xml2js'; -import { X509Certificate } from 'crypto'; - -import { - MOCK_IDP_REALM_NAME, - MOCK_IDP_ENTITY_ID, - MOCK_IDP_ROLE_MAPPING_NAME, - MOCK_IDP_ATTRIBUTE_PRINCIPAL, - MOCK_IDP_ATTRIBUTE_ROLES, - MOCK_IDP_ATTRIBUTE_EMAIL, - MOCK_IDP_ATTRIBUTE_NAME, - MOCK_IDP_LOGIN_PATH, - MOCK_IDP_LOGOUT_PATH, -} from './constants'; - -const inflateRawAsync = promisify(zlib.inflateRaw); -const parseStringAsync = promisify(parseString); - -/** - * Creates XML metadata for our mock identity provider. - * - * This can be saved to file and used to configure Elasticsearch SAML realm. - * - * @param kibanaUrl Fully qualified URL where Kibana is hosted (including base path) - */ -export async function createMockIdpMetadata(kibanaUrl: string) { - const signingKey = await readFile(KBN_CERT_PATH); - const cert = new X509Certificate(signingKey); - const trimTrailingSlash = (url: string) => (url.endsWith('/') ? url.slice(0, -1) : url); - - return ` - - - - - - ${cert.raw.toString('base64')} - - - - - - - - - - `; -} - -/** - * Creates a SAML response that can be passed directly to the Kibana ACS endpoint to authenticate a user. - * - * @example Create a SAML response. - * - * ```ts - * const samlResponse = await createSAMLResponse({ - * username: '1234567890', - * email: 'mail@elastic.co', - * fullname: 'Test User', - * roles: ['t1_analyst', 'editor'], - * }) - * ``` - * - * @example Authenticate user with SAML response. - * - * ```ts - * fetch('/api/security/saml/callback', { - * method: 'POST', - * body: JSON.stringify({ SAMLResponse: samlResponse }), - * redirect: 'manual' - * }) - * ``` - */ -export async function createSAMLResponse(options: { - /** Fully qualified URL where Kibana is hosted (including base path) */ - kibanaUrl: string; - /** ID from SAML authentication request */ - authnRequestId?: string; - username: string; - fullname?: string; - email?: string; - roles: string[]; -}) { - const issueInstant = new Date().toISOString(); - const notOnOrAfter = new Date(Date.now() + 3600 * 1000).toISOString(); - - const samlAssertionTemplateXML = ` - - ${MOCK_IDP_ENTITY_ID} - - _643ec1b3f5673583b9f9a1e9e73a36daa2a3748f - - - - - - - urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified - - - - - ${options.username} - - - ${options.roles - .map( - (role) => `${role}` - ) - .join('')} - - ${ - options.email - ? ` - ${options.email} - ` - : '' - } - ${ - options.fullname - ? ` - ${options.fullname} - ` - : '' - } - - - `; - - const signature = new SignedXml(); - signature.signatureAlgorithm = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'; - signature.signingKey = await readFile(KBN_KEY_PATH); - - // Adds a reference to a `Assertion` xml element and an array of transform algorithms to be used during signing. - signature.addReference( - `//*[local-name(.)='Assertion']`, - [ - 'http://www.w3.org/2000/09/xmldsig#enveloped-signature', - 'http://www.w3.org/2001/10/xml-exc-c14n#', - ], - 'http://www.w3.org/2001/04/xmlenc#sha256' - ); - - signature.computeSignature(samlAssertionTemplateXML, { - location: { reference: `//*[local-name(.)='Issuer']`, action: 'after' }, - }); - - const value = await Buffer.from( - ` - - ${MOCK_IDP_ENTITY_ID} - - - ${signature.getSignedXml()} - - ` - ).toString('base64'); - - return value; -} - -/** - * Creates the role mapping required for developers to authenticate using SAML. - */ -export async function ensureSAMLRoleMapping(client: Client) { - return client.transport.request({ - method: 'PUT', - path: `/_security/role_mapping/${MOCK_IDP_ROLE_MAPPING_NAME}`, - body: { - enabled: true, - role_templates: [ - { - template: '{"source":"{{#tojson}}groups{{/tojson}}"}', - format: 'json', - }, - ], - rules: { - all: [ - { - field: { - 'realm.name': MOCK_IDP_REALM_NAME, - }, - }, - ], - }, - }, - }); -} - -interface SAMLAuthnRequest { - 'saml2p:AuthnRequest': { - $: { - AssertionConsumerServiceURL: string; - Destination: string; - ID: string; - IssueInstant: string; - }; - }; -} - -export async function parseSAMLAuthnRequest(samlRequest: string) { - const inflatedSAMLRequest = (await inflateRawAsync(Buffer.from(samlRequest, 'base64'))) as Buffer; - const parsedSAMLRequest = (await parseStringAsync( - inflatedSAMLRequest.toString() - )) as SAMLAuthnRequest; - return parsedSAMLRequest['saml2p:AuthnRequest'].$; -} diff --git a/packages/kbn-mock-idp-plugin/kibana.jsonc b/packages/kbn-mock-idp-plugin/kibana.jsonc deleted file mode 100644 index 929d7b9b990db36..000000000000000 --- a/packages/kbn-mock-idp-plugin/kibana.jsonc +++ /dev/null @@ -1,11 +0,0 @@ -{ - "type": "plugin", - "id": "@kbn/mock-idp-plugin", - "owner": "@elastic/kibana-security", - "devOnly": true, - "plugin": { - "id": "mockIdpPlugin", - "server": true, - "browser": false - } -} \ No newline at end of file diff --git a/packages/kbn-mock-idp-plugin/package.json b/packages/kbn-mock-idp-plugin/package.json deleted file mode 100644 index 456a2cfa5ce322d..000000000000000 --- a/packages/kbn-mock-idp-plugin/package.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "@kbn/mock-idp-plugin", - "private": true, - "version": "1.0.0", - "license": "SSPL-1.0 OR Elastic License 2.0" -} \ No newline at end of file diff --git a/packages/kbn-mock-idp-plugin/server/index.ts b/packages/kbn-mock-idp-plugin/server/index.ts deleted file mode 100644 index db807851d45642e..000000000000000 --- a/packages/kbn-mock-idp-plugin/server/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* - * 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 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 or the Server - * Side Public License, v 1. - */ - -export { plugin } from './plugin'; diff --git a/packages/kbn-mock-idp-plugin/server/plugin.ts b/packages/kbn-mock-idp-plugin/server/plugin.ts deleted file mode 100644 index 20c115d80cf2c9a..000000000000000 --- a/packages/kbn-mock-idp-plugin/server/plugin.ts +++ /dev/null @@ -1,120 +0,0 @@ -/* - * 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 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 or the Server - * Side Public License, v 1. - */ - -import type { PluginInitializer, Plugin } from '@kbn/core-plugins-server'; -import { schema } from '@kbn/config-schema'; - -import { - MOCK_IDP_LOGIN_PATH, - MOCK_IDP_LOGOUT_PATH, - createSAMLResponse, - parseSAMLAuthnRequest, -} from '../common'; - -export const plugin: PluginInitializer = async (): Promise => ({ - setup(core) { - core.http.resources.register( - { - path: MOCK_IDP_LOGIN_PATH, - validate: { - query: schema.object({ - SAMLRequest: schema.string(), - }), - }, - options: { authRequired: false }, - }, - async (context, request, response) => { - let samlRequest: Awaited>; - try { - samlRequest = await parseSAMLAuthnRequest(request.query.SAMLRequest); - } catch (error) { - return response.badRequest({ - body: '[request query.SAMLRequest]: value is not valid SAMLRequest.', - }); - } - - const userRoles: Array<[string, string]> = [ - ['system_indices_superuser', 'system_indices_superuser'], - ['t1_analyst', 't1_analyst'], - ['t2_analyst', 't2_analyst'], - ['t3_analyst', 't3_analyst'], - ['threat_intelligence_analyst', 'threat_intelligence_analyst'], - ['rule_author', 'rule_author'], - ['soc_manager', 'soc_manager'], - ['detections_admin', 'detections_admin'], - ['platform_engineer', 'platform_engineer'], - ['endpoint_operations_analyst', 'endpoint_operations_analyst'], - ['endpoint_policy_manager', 'endpoint_policy_manager'], - ]; - - const samlResponses = await Promise.all( - userRoles.map(([username, role]) => - createSAMLResponse({ - authnRequestId: samlRequest.ID, - kibanaUrl: samlRequest.AssertionConsumerServiceURL, - username, - roles: [role], - }) - ) - ); - - return response.renderHtml({ - body: ` - - Mock Identity Provider - - -

Mock Identity Provider

-
-

Pick a role:

-
    - ${userRoles - .map( - ([username], i) => - ` -
  • - -
  • - ` - ) - .join('')} -
- - - `, - }); - } - ); - - core.http.resources.register( - { - path: `${MOCK_IDP_LOGIN_PATH}/submit.js`, - validate: false, - options: { authRequired: false }, - }, - (context, request, response) => { - return response.renderJs({ body: 'document.getElementById("loginForm").submit();' }); - } - ); - - core.http.resources.register( - { - path: MOCK_IDP_LOGOUT_PATH, - validate: false, - options: { authRequired: false }, - }, - async (context, request, response) => { - return response.redirected({ headers: { location: '/' } }); - } - ); - }, - start() {}, - stop() {}, -}); diff --git a/packages/kbn-mock-idp-plugin/tsconfig.json b/packages/kbn-mock-idp-plugin/tsconfig.json deleted file mode 100644 index 1420a34208f138a..000000000000000 --- a/packages/kbn-mock-idp-plugin/tsconfig.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "outDir": "target/types" - }, - "include": [ - "**/*.ts", - "**/*.tsx" - ], - "exclude": [ - "target/**/*" - ], - "kbn_references": [ - "@kbn/core-plugins-server", - "@kbn/config-schema", - "@kbn/dev-utils" - ] -} diff --git a/scripts/es.js b/scripts/es.js index 1cee27b7685b51f..1fcd221c97904aa 100644 --- a/scripts/es.js +++ b/scripts/es.js @@ -20,7 +20,6 @@ kbnEs 'source-path': resolve(__dirname, '../../elasticsearch'), 'base-path': resolve(__dirname, '../.es'), ssl: false, - kibanaUrl: 'https://localhost:5601/', }) .catch(function (e) { console.error(e); diff --git a/src/cli/serve/serve.js b/src/cli/serve/serve.js index adb951def861a69..911eecd45a9fbdf 100644 --- a/src/cli/serve/serve.js +++ b/src/cli/serve/serve.js @@ -15,7 +15,6 @@ import { isKibanaDistributable } from '@kbn/repo-info'; import { readKeystore } from '../keystore/read_keystore'; import { compileConfigStack } from './compile_config_stack'; import { getConfigFromFiles } from '@kbn/config'; -import { MOCK_IDP_PLUGIN_PATH, MOCK_IDP_REALM_NAME } from '@kbn/mock-idp-plugin/common'; const DEV_MODE_PATH = '@kbn/cli-dev-mode'; const DEV_MODE_SUPPORTED = canRequire(DEV_MODE_PATH); @@ -110,25 +109,6 @@ export function applyConfigOverrides(rawConfig, opts, extraCliOptions) { if (opts.dev) { if (opts.serverless) { setServerlessKibanaDevServiceAccountIfPossible(get, set, opts); - - // Load mock identity provider plugin and configure realm if supported (ES only supports SAML when run with SSL) - if (opts.ssl) { - set('plugins.paths', _.compact([].concat(get('plugins.paths'), MOCK_IDP_PLUGIN_PATH))); - set(`xpack.security.authc.providers.saml.${MOCK_IDP_REALM_NAME}`, { - order: Number.MAX_SAFE_INTEGER, - realm: MOCK_IDP_REALM_NAME, - icon: 'user', - description: 'Continue as Test User', - hint: 'Allows testing serverless user roles', - }); - // Add basic realm since defaults won't be applied when a provider has been configured - if (!has('xpack.security.authc.providers.basic')) { - set('xpack.security.authc.providers.basic.basic', { - order: 0, - enabled: true, - }); - } - } } if (!has('elasticsearch.serviceAccountToken') && opts.devCredentials !== false) { @@ -294,9 +274,7 @@ export default function (program) { // We can tell users they only have to run with `yarn start --run-examples` to get those // local links to work. Similar to what we do for "View in Console" links in our // elastic.co links. - // We also want to run without base path when running in serverless mode so that Elasticsearch can - // connect to Kibana's mock identity provider. - basePath: opts.runExamples || isServerlessMode ? false : !!opts.basePath, + basePath: opts.runExamples ? false : !!opts.basePath, optimize: !!opts.optimize, disableOptimizer: !opts.optimizer, oss: !!opts.oss, diff --git a/src/cli/tsconfig.json b/src/cli/tsconfig.json index 3b3c0854975d37f..ebbbc19f75c7922 100644 --- a/src/cli/tsconfig.json +++ b/src/cli/tsconfig.json @@ -17,7 +17,6 @@ "@kbn/config", "@kbn/dev-utils", "@kbn/apm-config-loader", - "@kbn/mock-idp-plugin", ], "exclude": [ "target/**/*", diff --git a/tsconfig.base.json b/tsconfig.base.json index 18ae153c7fa12e9..a92c90b6aeb3849 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1062,8 +1062,6 @@ "@kbn/ml-trained-models-utils/*": ["x-pack/packages/ml/trained_models_utils/*"], "@kbn/ml-url-state": ["x-pack/packages/ml/url_state"], "@kbn/ml-url-state/*": ["x-pack/packages/ml/url_state/*"], - "@kbn/mock-idp-plugin": ["packages/kbn-mock-idp-plugin"], - "@kbn/mock-idp-plugin/*": ["packages/kbn-mock-idp-plugin/*"], "@kbn/monaco": ["packages/kbn-monaco"], "@kbn/monaco/*": ["packages/kbn-monaco/*"], "@kbn/monitoring-collection-plugin": ["x-pack/plugins/monitoring_collection"], diff --git a/yarn.lock b/yarn.lock index 67b95f803c7ae27..0d004ee99d7d464 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5028,10 +5028,6 @@ version "0.0.0" uid "" -"@kbn/mock-idp-plugin@link:packages/kbn-mock-idp-plugin": - version "0.0.0" - uid "" - "@kbn/monaco@link:packages/kbn-monaco": version "0.0.0" uid ""