mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 09:19:04 -04:00
[Cloud/Security] Fix the server-side import of the contract CloudStart
(#149203)
Co-authored-by: Aleh Zasypkin <aleh.zasypkin@elastic.co> Resolves https://github.com/elastic/kibana/issues/149204
This commit is contained in:
parent
ebb61a5089
commit
f0b5db6f70
8 changed files with 187 additions and 18 deletions
|
@ -262,6 +262,7 @@ enabled:
|
|||
- x-pack/test/security_api_integration/oidc.config.ts
|
||||
- x-pack/test/security_api_integration/pki.config.ts
|
||||
- x-pack/test/security_api_integration/saml.config.ts
|
||||
- x-pack/test/security_api_integration/saml_cloud.config.ts
|
||||
- x-pack/test/security_api_integration/session_idle.config.ts
|
||||
- x-pack/test/security_api_integration/session_invalidate.config.ts
|
||||
- x-pack/test/security_api_integration/session_lifespan.config.ts
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import { PluginInitializerContext } from '@kbn/core/server';
|
||||
import { CloudPlugin } from './plugin';
|
||||
|
||||
export type { CloudSetup } from './plugin';
|
||||
export type { CloudSetup, CloudStart } from './plugin';
|
||||
export { config } from './config';
|
||||
export const plugin = (initializerContext: PluginInitializerContext) => {
|
||||
return new CloudPlugin(initializerContext);
|
||||
|
|
|
@ -16,22 +16,23 @@ const baseConfig = {
|
|||
};
|
||||
|
||||
describe('Cloud Plugin', () => {
|
||||
const setupPlugin = () => {
|
||||
const initContext = coreMock.createPluginInitializerContext({
|
||||
...baseConfig,
|
||||
id: 'cloudId',
|
||||
cname: 'cloud.elastic.co',
|
||||
});
|
||||
const plugin = new CloudPlugin(initContext);
|
||||
|
||||
const coreSetup = coreMock.createSetup();
|
||||
const setup = plugin.setup(coreSetup, {});
|
||||
const start = plugin.start();
|
||||
|
||||
return { setup, start };
|
||||
};
|
||||
|
||||
describe('#setup', () => {
|
||||
describe('interface', () => {
|
||||
const setupPlugin = () => {
|
||||
const initContext = coreMock.createPluginInitializerContext({
|
||||
...baseConfig,
|
||||
id: 'cloudId',
|
||||
cname: 'cloud.elastic.co',
|
||||
});
|
||||
const plugin = new CloudPlugin(initContext);
|
||||
|
||||
const coreSetup = coreMock.createSetup();
|
||||
const setup = plugin.setup(coreSetup, {});
|
||||
|
||||
return { setup };
|
||||
};
|
||||
|
||||
it('exposes isCloudEnabled', () => {
|
||||
const { setup } = setupPlugin();
|
||||
expect(setup.isCloudEnabled).toBe(true);
|
||||
|
@ -58,4 +59,13 @@ describe('Cloud Plugin', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('#start', () => {
|
||||
describe('interface', () => {
|
||||
it('exposes isCloudEnabled', () => {
|
||||
const { start } = setupPlugin();
|
||||
expect(start.isCloudEnabled).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -55,7 +55,17 @@ export interface CloudSetup {
|
|||
};
|
||||
}
|
||||
|
||||
export class CloudPlugin implements Plugin<CloudSetup> {
|
||||
/**
|
||||
* Start contract
|
||||
*/
|
||||
export interface CloudStart {
|
||||
/**
|
||||
* `true` when running on Elastic Cloud.
|
||||
*/
|
||||
isCloudEnabled: boolean;
|
||||
}
|
||||
|
||||
export class CloudPlugin implements Plugin<CloudSetup, CloudStart> {
|
||||
private readonly config: CloudConfigType;
|
||||
|
||||
constructor(private readonly context: PluginInitializerContext) {
|
||||
|
@ -85,5 +95,9 @@ export class CloudPlugin implements Plugin<CloudSetup> {
|
|||
};
|
||||
}
|
||||
|
||||
public start() {}
|
||||
public start() {
|
||||
return {
|
||||
isCloudEnabled: getIsCloudEnabled(this.config.id),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import type { Subscription } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
import type { CloudStart } from '@kbn/cloud-plugin/public';
|
||||
import type { CloudStart } from '@kbn/cloud-plugin/server';
|
||||
import type { TypeOf } from '@kbn/config-schema';
|
||||
import type {
|
||||
CoreSetup,
|
||||
|
|
55
x-pack/test/security_api_integration/saml_cloud.config.ts
Normal file
55
x-pack/test/security_api_integration/saml_cloud.config.ts
Normal file
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { resolve } from 'path';
|
||||
import { FtrConfigProviderContext } from '@kbn/test';
|
||||
import { services } from './services';
|
||||
|
||||
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
||||
const xPackAPITestsConfig = await readConfigFile(require.resolve('../api_integration/config.ts'));
|
||||
|
||||
const kibanaPort = xPackAPITestsConfig.get('servers.kibana.port');
|
||||
const idpPath = resolve(__dirname, './fixtures/saml/idp_metadata.xml');
|
||||
|
||||
return {
|
||||
testFiles: [require.resolve('./tests/saml_cloud')],
|
||||
servers: xPackAPITestsConfig.get('servers'),
|
||||
security: { disableTestUser: true },
|
||||
services,
|
||||
junit: {
|
||||
reportName: 'X-Pack Security API Integration Tests (Cloud SAML)',
|
||||
},
|
||||
|
||||
esTestCluster: {
|
||||
...xPackAPITestsConfig.get('esTestCluster'),
|
||||
serverArgs: [
|
||||
...xPackAPITestsConfig.get('esTestCluster.serverArgs'),
|
||||
'xpack.security.authc.token.enabled=true',
|
||||
'xpack.security.authc.token.timeout=15s',
|
||||
'xpack.security.authc.realms.saml.cloud-saml-kibana.order=0',
|
||||
`xpack.security.authc.realms.saml.cloud-saml-kibana.idp.metadata.path=${idpPath}`,
|
||||
'xpack.security.authc.realms.saml.cloud-saml-kibana.idp.entity_id=http://www.elastic.co/saml1',
|
||||
`xpack.security.authc.realms.saml.cloud-saml-kibana.sp.entity_id=http://localhost:${kibanaPort}`,
|
||||
`xpack.security.authc.realms.saml.cloud-saml-kibana.sp.logout=http://localhost:${kibanaPort}/logout`,
|
||||
`xpack.security.authc.realms.saml.cloud-saml-kibana.sp.acs=http://localhost:${kibanaPort}/api/security/saml/callback`,
|
||||
'xpack.security.authc.realms.saml.cloud-saml-kibana.attributes.principal=urn:oid:0.0.7',
|
||||
],
|
||||
},
|
||||
|
||||
kbnTestServer: {
|
||||
...xPackAPITestsConfig.get('kbnTestServer'),
|
||||
serverArgs: [
|
||||
...xPackAPITestsConfig.get('kbnTestServer.serverArgs'),
|
||||
'--xpack.cloud.id=ftr_fake_cloud_id',
|
||||
`--xpack.security.authc.providers=${JSON.stringify({
|
||||
basic: { 'cloud-basic': { order: 0 } },
|
||||
saml: { 'cloud-saml-kibana': { order: 1, realm: 'cloud-saml-kibana' } },
|
||||
})}`,
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
|
@ -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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
export default function ({ loadTestFile }: FtrProviderContext) {
|
||||
describe('security APIs - Cloud SAML', function () {
|
||||
loadTestFile(require.resolve('./saml_login'));
|
||||
});
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { parse as parseCookie, Cookie } from 'tough-cookie';
|
||||
import { getSAMLResponse } from '../../fixtures/saml/saml_tools';
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
export default function ({ getService }: FtrProviderContext) {
|
||||
const randomness = getService('randomness');
|
||||
const supertest = getService('supertestWithoutAuth');
|
||||
const config = getService('config');
|
||||
|
||||
const kibanaServerConfig = config.get('servers.kibana');
|
||||
|
||||
function createSAMLResponse(options = {}) {
|
||||
return getSAMLResponse({
|
||||
destination: `http://localhost:${kibanaServerConfig.port}/api/security/saml/callback`,
|
||||
sessionIndex: String(randomness.naturalNumber()),
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
||||
async function checkSessionCookie(sessionCookie: Cookie, username = 'a@b.c') {
|
||||
const apiResponse = await supertest
|
||||
.get('/internal/security/me')
|
||||
.set('kbn-xsrf', 'xxx')
|
||||
.set('Cookie', sessionCookie.cookieString())
|
||||
.expect(200);
|
||||
|
||||
expect(apiResponse.body.username).to.be(username);
|
||||
expect(apiResponse.body.elastic_cloud_user).to.be(true);
|
||||
expect(apiResponse.body.authentication_realm).to.eql({
|
||||
type: 'saml',
|
||||
name: 'cloud-saml-kibana',
|
||||
});
|
||||
expect(apiResponse.body.authentication_provider).to.eql({
|
||||
type: 'saml',
|
||||
name: 'cloud-saml-kibana',
|
||||
});
|
||||
expect(apiResponse.body.authentication_type).to.be('token');
|
||||
}
|
||||
|
||||
describe('Cloud SAML authentication', () => {
|
||||
let sessionCookie: Cookie;
|
||||
|
||||
beforeEach(async () => {
|
||||
// Cloud SAML relies on IdP initiated login.
|
||||
const samlAuthenticationResponse = await supertest
|
||||
.post('/api/security/saml/callback')
|
||||
.send({ SAMLResponse: await createSAMLResponse({ username: 'a@b.c' }) })
|
||||
.expect(302);
|
||||
|
||||
expect(samlAuthenticationResponse.headers.location).to.be('/');
|
||||
|
||||
sessionCookie = parseCookie(samlAuthenticationResponse.headers['set-cookie'][0])!;
|
||||
});
|
||||
|
||||
it('should properly set `elastic_cloud_user` user property', async () => {
|
||||
// Same user, same provider - session ID hasn't changed and cookie should still be valid.
|
||||
await supertest
|
||||
.get('/internal/security/me')
|
||||
.set('kbn-xsrf', 'xxx')
|
||||
.set('Cookie', sessionCookie.cookieString())
|
||||
.expect(200);
|
||||
|
||||
// Check that all properties of the cloud saml user are properly set.
|
||||
await checkSessionCookie(sessionCookie);
|
||||
});
|
||||
});
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue