Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add mock identity provider for serverless #170852

Merged
merged 31 commits into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
13a3831
Add mock identity provider for serverless
thomheymann Nov 8, 2023
5358334
Merge branch 'main' of https://github.com/elastic/kibana into serverl…
thomheymann Nov 8, 2023
bc21dd2
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Nov 8, 2023
b48a2c8
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Nov 8, 2023
12cf10e
[CI] Auto-commit changed files from 'node scripts/generate codeowners'
kibanamachine Nov 8, 2023
0fec2e0
Fix errors
thomheymann Nov 8, 2023
22b9e23
Merge branch 'serverless-role-selector' of https://github.com/thomhey…
thomheymann Nov 8, 2023
478cd79
Explicit exports
thomheymann Nov 8, 2023
e4f17ac
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Nov 8, 2023
4f99a74
Fix logout flow and login selector validation
thomheymann Nov 8, 2023
19af2ef
Merge branch 'serverless-role-selector' of https://github.com/thomhey…
thomheymann Nov 8, 2023
0e60429
Add user roles
thomheymann Nov 8, 2023
f863db3
Fix cyclic project reference
thomheymann Nov 8, 2023
4882634
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Nov 8, 2023
022f61b
Fix unit tests
thomheymann Nov 9, 2023
f7ce3a1
Merge branch 'serverless-role-selector' of https://github.com/thomhey…
thomheymann Nov 9, 2023
b635222
Merge branch 'main' of https://github.com/elastic/kibana into serverl…
thomheymann Nov 9, 2023
a993ab5
Merge branch 'main' into serverless-role-selector
thomheymann Nov 9, 2023
ebbf87d
Add unit tests
thomheymann Nov 10, 2023
d8fd42e
Merge branch 'serverless-role-selector' of https://github.com/thomhey…
thomheymann Nov 10, 2023
936d0fc
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Nov 10, 2023
3bf667b
Merge branch 'main' into serverless-role-selector
thomheymann Nov 10, 2023
e1958ae
Update packages/kbn-es/src/utils/docker.ts
thomheymann Nov 14, 2023
e55955d
Merge branch 'main' of https://github.com/elastic/kibana into serverl…
thomheymann Nov 14, 2023
6324b49
Fix unit test
thomheymann Nov 14, 2023
52bb13c
Merge branch 'main' into serverless-role-selector
thomheymann Nov 14, 2023
59a49fb
Merge branch 'main' into serverless-role-selector
thomheymann Nov 14, 2023
11eb3c9
Merge branch 'main' into serverless-role-selector
thomheymann Nov 14, 2023
d8b0b01
Merge branch 'main' into serverless-role-selector
thomheymann Nov 14, 2023
9449096
Merge branch 'main' into serverless-role-selector
thomheymann Nov 14, 2023
cf5aac0
Merge branch 'main' into serverless-role-selector
dmlemeshko Nov 15, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,7 @@ 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
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1221,6 +1221,7 @@
"@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",
Expand Down
3 changes: 2 additions & 1 deletion packages/kbn-es/src/cli_commands/serverless.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ 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
Expand Down Expand Up @@ -73,7 +74,7 @@ export const serverless: Command = {
files: 'F',
},

string: ['tag', 'image', 'basePath', 'resources', 'host'],
string: ['tag', 'image', 'basePath', 'resources', 'host', 'kibanaUrl'],
boolean: ['clean', 'ssl', 'kill', 'background', 'skipTeardown', 'waitForReady'],

default: defaults,
Expand Down
3 changes: 3 additions & 0 deletions packages/kbn-es/src/paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

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;
Expand Down Expand Up @@ -51,6 +52,8 @@ 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,
Expand Down
108 changes: 103 additions & 5 deletions packages/kbn-es/src/utils/docker.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,17 @@ import {
ServerlessOptions,
} from './docker';
import { ToolingLog, ToolingLogCollectingWriter } from '@kbn/tooling-log';
import { ES_P12_PATH } from '@kbn/dev-utils';
import { CA_CERT_PATH, 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');
Expand All @@ -58,6 +60,8 @@ 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]);
Expand All @@ -69,6 +73,8 @@ 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();
Expand Down Expand Up @@ -423,6 +429,68 @@ 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(28);
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.token.enabled=true",
"--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()', () => {
Expand Down Expand Up @@ -463,21 +531,29 @@ describe('setupServerlessVolumes()', () => {
expect(existsSync(`${serverlessObjectStorePath}/cluster_state/lease`)).toBe(false);
});

test('should add SSL volumes when ssl is passed', async () => {
test('should add SSL and IDP metadata volumes when ssl and kibanaUrl are passed', async () => {
mockFs(existingObjectStore);
createMockIdpMetadataMock.mockResolvedValue('<xml/>');

const volumeCmd = await setupServerlessVolumes(log, {
basePath: baseEsPath,
ssl: true,
kibanaUrl: 'https://localhost:5603/',
});

const volumeCmd = await setupServerlessVolumes(log, { basePath: baseEsPath, ssl: true });
expect(createMockIdpMetadataMock).toHaveBeenCalledTimes(1);
expect(createMockIdpMetadataMock).toHaveBeenCalledWith('https://localhost:5603/');

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(20);
expect(volumeCmd).toHaveLength(22);
expect(pathsNotIncludedInCmd).toEqual([]);
});

Expand Down Expand Up @@ -543,6 +619,7 @@ describe('runServerlessEsNode()', () => {

describe('runServerlessCluster()', () => {
test('should start 3 serverless nodes', async () => {
waitUntilClusterReadyMock.mockResolvedValue();
mockFs({
[baseEsPath]: {},
});
Expand All @@ -567,7 +644,27 @@ 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('<xml/>');

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]: {},
Expand All @@ -580,6 +677,7 @@ describe('runServerlessCluster()', () => {
});

test(`should not wait for the security index when security is disabled`, async () => {
waitUntilClusterReadyMock.mockResolvedValue();
mockFs({
[baseEsPath]: {},
});
Expand Down
Loading