mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
[SECURITY] Stop kibana crashes when no authentication providers are enabled (#118784)
* check if a provider is there * the last puzzle * fix lint * review oleg * Update x-pack/plugins/security/public/nav_control/nav_control_component.tsx Co-authored-by: Aleh Zasypkin <aleh.zasypkin@gmail.com> * Update x-pack/test/security_api_integration/http_no_auth_providers.config.ts Co-authored-by: Aleh Zasypkin <aleh.zasypkin@gmail.com> * Update x-pack/plugins/security/server/authentication/authenticator.test.ts Co-authored-by: Aleh Zasypkin <aleh.zasypkin@gmail.com> * Update x-pack/test/security_api_integration/tests/http_no_auth_providers/authentication.ts Co-authored-by: Aleh Zasypkin <aleh.zasypkin@gmail.com> * Update x-pack/test/security_api_integration/http_no_auth_providers.config.ts Co-authored-by: Aleh Zasypkin <aleh.zasypkin@gmail.com> * review II Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Aleh Zasypkin <aleh.zasypkin@gmail.com>
This commit is contained in:
parent
1ac885e428
commit
55fa55ddc9
8 changed files with 131 additions and 6 deletions
|
@ -128,6 +128,19 @@ describe('AuthenticationService', () => {
|
|||
expect.any(Function)
|
||||
);
|
||||
});
|
||||
|
||||
it('properly registers auth handler with no providers', () => {
|
||||
mockSetupAuthenticationParams.config.authc = {
|
||||
...mockSetupAuthenticationParams.config.authc,
|
||||
sortedProviders: [],
|
||||
};
|
||||
service.setup(mockSetupAuthenticationParams);
|
||||
|
||||
expect(mockSetupAuthenticationParams.http.registerAuth).toHaveBeenCalledTimes(1);
|
||||
expect(mockSetupAuthenticationParams.http.registerAuth).toHaveBeenCalledWith(
|
||||
expect.any(Function)
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('#start()', () => {
|
||||
|
|
|
@ -98,7 +98,8 @@ export class AuthenticationService {
|
|||
// 2. Login selector is disabled, but the provider with the lowest `order` uses login form
|
||||
const isLoginPageAvailable =
|
||||
config.authc.selector.enabled ||
|
||||
shouldProviderUseLoginForm(config.authc.sortedProviders[0].type);
|
||||
(config.authc.sortedProviders.length > 0 &&
|
||||
shouldProviderUseLoginForm(config.authc.sortedProviders[0].type));
|
||||
|
||||
http.registerAuth(async (request, response, t) => {
|
||||
if (!license.isLicenseAvailable()) {
|
||||
|
|
|
@ -1872,6 +1872,24 @@ describe('Authenticator', () => {
|
|||
expect(mockOptions.session.invalidate).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('if session does not exist and providers is empty, redirects to default logout path.', async () => {
|
||||
const request = httpServerMock.createKibanaRequest();
|
||||
|
||||
mockOptions = getMockOptions({
|
||||
providers: { basic: { basic1: { order: 0, enabled: false } } },
|
||||
});
|
||||
authenticator = new Authenticator(mockOptions);
|
||||
|
||||
await expect(authenticator.logout(request)).resolves.toEqual(
|
||||
DeauthenticationResult.redirectTo(
|
||||
'/mock-server-basepath/security/logged_out?msg=LOGGED_OUT'
|
||||
)
|
||||
);
|
||||
|
||||
expect(mockBasicAuthenticationProvider.logout).not.toHaveBeenCalled();
|
||||
expect(mockOptions.session.invalidate).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('redirects to login form if session does not exist and provider name is invalid', async () => {
|
||||
const request = httpServerMock.createKibanaRequest({ query: { provider: 'foo' } });
|
||||
mockOptions.session.get.mockResolvedValue(null);
|
||||
|
|
|
@ -806,10 +806,7 @@ export class Authenticator {
|
|||
* @param providerType Type of the provider that handles logout. If not specified, then the first
|
||||
* provider in the chain (default) is assumed.
|
||||
*/
|
||||
private getLoggedOutURL(
|
||||
request: KibanaRequest,
|
||||
providerType: string = this.options.config.authc.sortedProviders[0].type
|
||||
) {
|
||||
private getLoggedOutURL(request: KibanaRequest, providerType?: string) {
|
||||
// The app that handles logout needs to know the reason of the logout and the URL we may need to
|
||||
// redirect user to once they log in again (e.g. when session expires).
|
||||
const searchParams = new URLSearchParams();
|
||||
|
@ -825,7 +822,12 @@ export class Authenticator {
|
|||
|
||||
// Query string may contain the path where logout has been called or
|
||||
// logout reason that login page may need to know.
|
||||
return this.options.config.authc.selector.enabled || shouldProviderUseLoginForm(providerType)
|
||||
return this.options.config.authc.selector.enabled ||
|
||||
(providerType
|
||||
? shouldProviderUseLoginForm(providerType)
|
||||
: this.options.config.authc.sortedProviders.length > 0
|
||||
? shouldProviderUseLoginForm(this.options.config.authc.sortedProviders[0].type)
|
||||
: false)
|
||||
? `${this.options.basePath.serverBasePath}/login?${searchParams.toString()}`
|
||||
: `${this.options.basePath.serverBasePath}/security/logged_out?${searchParams.toString()}`;
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ const onlyNotInCoverageTests = [
|
|||
require.resolve('../test/security_api_integration/login_selector.config.ts'),
|
||||
require.resolve('../test/security_api_integration/audit.config.ts'),
|
||||
require.resolve('../test/security_api_integration/http_bearer.config.ts'),
|
||||
require.resolve('../test/security_api_integration/http_no_auth_providers.config.ts'),
|
||||
require.resolve('../test/security_api_integration/kerberos.config.ts'),
|
||||
require.resolve('../test/security_api_integration/kerberos_anonymous_access.config.ts'),
|
||||
require.resolve('../test/security_api_integration/pki.config.ts'),
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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 { FtrConfigProviderContext } from '@kbn/test';
|
||||
import { services } from './services';
|
||||
|
||||
export default async function ({ readConfigFile }: FtrConfigProviderContext) {
|
||||
const xPackAPITestsConfig = await readConfigFile(require.resolve('../api_integration/config.ts'));
|
||||
|
||||
return {
|
||||
testFiles: [require.resolve('./tests/http_no_auth_providers')],
|
||||
servers: xPackAPITestsConfig.get('servers'),
|
||||
security: { disableTestUser: true },
|
||||
services,
|
||||
junit: {
|
||||
reportName: 'X-Pack Security API Integration Tests (HTTP without providers)',
|
||||
},
|
||||
|
||||
esTestCluster: xPackAPITestsConfig.get('esTestCluster'),
|
||||
|
||||
kbnTestServer: {
|
||||
...xPackAPITestsConfig.get('kbnTestServer'),
|
||||
serverArgs: [
|
||||
...xPackAPITestsConfig.get('kbnTestServer.serverArgs'),
|
||||
`--xpack.security.authc.http.schemes=${JSON.stringify(['apikey', 'basic'])}`,
|
||||
`--xpack.security.authc.providers=${JSON.stringify({
|
||||
basic: { basic1: { order: 0, enabled: false } },
|
||||
})}`,
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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 { adminTestUser } from '@kbn/test';
|
||||
import { FtrProviderContext } from '../../ftr_provider_context';
|
||||
|
||||
export default function ({ getService }: FtrProviderContext) {
|
||||
const supertest = getService('supertestWithoutAuth');
|
||||
|
||||
describe('authorization', () => {
|
||||
it('fail request without authorization request header', async () => {
|
||||
await supertest.get('/internal/security/me').set('kbn-xsrf', 'true').expect(401);
|
||||
});
|
||||
|
||||
it('accept request with authorization request header', async () => {
|
||||
const credentials = Buffer.from(
|
||||
`${adminTestUser.username}:${adminTestUser.password}`
|
||||
).toString('base64');
|
||||
|
||||
const { body: user, headers } = await supertest
|
||||
.get('/internal/security/me')
|
||||
.set('kbn-xsrf', 'xxx')
|
||||
.set('Authorization', `Basic ${credentials}`)
|
||||
.expect(200);
|
||||
|
||||
expect(user.username).to.eql(adminTestUser.username);
|
||||
expect(user.authentication_provider).to.eql({ type: 'http', name: '__http__' });
|
||||
expect(user.authentication_type).to.eql('realm');
|
||||
|
||||
// Make sure we don't automatically create a session
|
||||
expect(headers['set-cookie']).to.be(undefined);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* 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 - HTTP no authentication providers are enabled', function () {
|
||||
this.tags('ciGroup6');
|
||||
loadTestFile(require.resolve('./authentication'));
|
||||
});
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue