Skip to content

Commit

Permalink
Migrate authentication subsystem to the new platform. (#39446)
Browse files Browse the repository at this point in the history
* Temporary Core workarounds.

* Move files to NP Security Plugin.

* Fix references.

* Migrate to the New Platform.

* Review#1: remove unused `loginAttempt` from provider iterator, rely more on RecursiveReadonly, etc.

* Integrate latest core changes: isTlsEnabled and get rid of legacy ES config.

* Revert `deepFreeze` changes and rely on `src/core/utils`.

* Review#2: do not mutate injectedVars in onInit. Integrate latest upstream changes.

* Use mocks provided by the Core.

* Expect ElasticsearchError instead of Boom errors as 401 Cluster client errors.

* Simplify session handling for `login`.

* Review#3: properly handle session updates for `login`, remove redundant hapi-auth-cookie deps from x-pack package.json, migrate to new core sessionStorage API, integrate latest Kerberos provider changes from upstream

* Do not clear session on login if it does not exist.
  • Loading branch information
azasypkin committed Jul 19, 2019
1 parent a4bedf0 commit 91e1d9c
Show file tree
Hide file tree
Showing 81 changed files with 5,771 additions and 5,399 deletions.
2 changes: 1 addition & 1 deletion src/test_utils/kbn_server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export function createRootWithSettings(
repl: false,
basePath: false,
optimize: false,
oss: false,
oss: true,
...cliArgs,
},
isDevClusterMaster: false,
Expand Down
54 changes: 0 additions & 54 deletions x-pack/legacy/plugins/security/__snapshots__/index.test.js.snap

This file was deleted.

7 changes: 5 additions & 2 deletions x-pack/legacy/plugins/security/common/model/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ export { Role, RoleIndexPrivilege, RoleKibanaPrivilege } from './role';
export { FeaturesPrivileges } from './features_privileges';
export { RawKibanaPrivileges, RawKibanaFeaturePrivileges } from './raw_kibana_privileges';
export { KibanaPrivileges } from './kibana_privileges';
export { User, EditUser, getUserDisplayName } from './user';
export { AuthenticatedUser, canUserChangePassword } from './authenticated_user';
export { User, EditUser, getUserDisplayName } from '../../../../../plugins/security/common/model';
export {
AuthenticatedUser,
canUserChangePassword,
} from '../../../../../plugins/security/common/model';
export { BuiltinESPrivileges } from './builtin_es_privileges';
4 changes: 0 additions & 4 deletions x-pack/legacy/plugins/security/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,12 @@

import { Legacy } from 'kibana';
import { AuthenticatedUser } from './common/model';
import { AuthenticationResult, DeauthenticationResult } from './server/lib/authentication';
import { AuthorizationService } from './server/lib/authorization/service';

/**
* Public interface of the security plugin.
*/
export interface SecurityPlugin {
authorization: Readonly<AuthorizationService>;
authenticate: (request: Legacy.Request) => Promise<AuthenticationResult>;
deauthenticate: (request: Legacy.Request) => Promise<DeauthenticationResult>;
getUser: (request: Legacy.Request) => Promise<AuthenticatedUser>;
isAuthenticated: (request: Legacy.Request) => Promise<boolean>;
}
81 changes: 32 additions & 49 deletions x-pack/legacy/plugins/security/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
*/

import { resolve } from 'path';
import { getUserProvider } from './server/lib/get_user';
import { initAuthenticateApi } from './server/routes/api/v1/authenticate';
import { initUsersApi } from './server/routes/api/v1/users';
import { initExternalRolesApi } from './server/routes/api/external/roles';
Expand All @@ -16,10 +15,7 @@ import { initOverwrittenSessionView } from './server/routes/views/overwritten_se
import { initLoginView } from './server/routes/views/login';
import { initLogoutView } from './server/routes/views/logout';
import { initLoggedOutView } from './server/routes/views/logged_out';
import { validateConfig } from './server/lib/validate_config';
import { authenticateFactory } from './server/lib/auth_redirect';
import { checkLicense } from './server/lib/check_license';
import { initAuthenticator } from './server/lib/authentication/authenticator';
import { SecurityAuditLogger } from './server/lib/audit_logger';
import { AuditLogger } from '../../server/lib/audit_logger';
import {
Expand All @@ -34,6 +30,7 @@ import { watchStatusAndLicenseToInitialize } from '../../server/lib/watch_status
import { SecureSavedObjectsClientWrapper } from './server/lib/saved_objects_client/secure_saved_objects_client_wrapper';
import { deepFreeze } from './server/lib/deep_freeze';
import { createOptionalPlugin } from '../../server/lib/optional_plugin';
import { KibanaRequest } from '../../../../src/core/server';

export const security = (kibana) => new kibana.Plugin({
id: 'security',
Expand All @@ -42,23 +39,12 @@ export const security = (kibana) => new kibana.Plugin({
require: ['kibana', 'elasticsearch', 'xpack_main'],

config(Joi) {
const providerOptionsSchema = (providerName, schema) => Joi.any()
.when('providers', {
is: Joi.array().items(Joi.string().valid(providerName).required(), Joi.string()),
then: schema,
otherwise: Joi.any().forbidden(),
});

return Joi.object({
enabled: Joi.boolean().default(true),
cookieName: Joi.string().default('sid'),
encryptionKey: Joi.when(Joi.ref('$dist'), {
is: true,
then: Joi.string(),
otherwise: Joi.string().default('a'.repeat(32)),
}),
sessionTimeout: Joi.number().allow(null).default(null),
secureCookies: Joi.boolean().default(false),
cookieName: Joi.any().description('This key is handled in the new platform security plugin ONLY'),
encryptionKey: Joi.any().description('This key is handled in the new platform security plugin ONLY'),
sessionTimeout: Joi.any().description('This key is handled in the new platform security plugin ONLY'),
secureCookies: Joi.any().description('This key is handled in the new platform security plugin ONLY'),
authorization: Joi.object({
legacyFallback: Joi.object({
enabled: Joi.boolean().default(true) // deprecated
Expand All @@ -67,11 +53,7 @@ export const security = (kibana) => new kibana.Plugin({
audit: Joi.object({
enabled: Joi.boolean().default(false)
}).default(),
authc: Joi.object({
providers: Joi.array().items(Joi.string()).default(['basic']),
oidc: providerOptionsSchema('oidc', Joi.object({ realm: Joi.string().required() }).required()),
saml: providerOptionsSchema('saml', Joi.object({ realm: Joi.string().required() }).required()),
}).default()
authc: Joi.any().description('This key is handled in the new platform security plugin ONLY')
}).default();
},

Expand Down Expand Up @@ -112,15 +94,18 @@ export const security = (kibana) => new kibana.Plugin({
'plugins/security/hacks/on_unauthorized_response'
],
home: ['plugins/security/register_feature'],
injectDefaultVars: function (server) {
const config = server.config();
injectDefaultVars: (server) => {
const securityPlugin = server.newPlatform.setup.plugins.security;
if (!securityPlugin) {
throw new Error('New Platform XPack Security plugin is not available.');
}

return {
secureCookies: config.get('xpack.security.secureCookies'),
sessionTimeout: config.get('xpack.security.sessionTimeout'),
enableSpaceAwarePrivileges: config.get('xpack.spaces.enabled'),
secureCookies: securityPlugin.config.secureCookies,
sessionTimeout: securityPlugin.config.sessionTimeout,
enableSpaceAwarePrivileges: server.config().get('xpack.spaces.enabled'),
};
}
},
},

async postInit(server) {
Expand All @@ -138,28 +123,29 @@ export const security = (kibana) => new kibana.Plugin({
},

async init(server) {
const plugin = this;
const securityPlugin = server.newPlatform.setup.plugins.security;
if (!securityPlugin) {
throw new Error('New Platform XPack Security plugin is not available.');
}

const config = server.config();
const xpackMainPlugin = server.plugins.xpack_main;
const xpackInfo = xpackMainPlugin.info;
securityPlugin.registerLegacyAPI({
xpackInfo,
isSystemAPIRequest: server.plugins.kibana.systemApi.isSystemApiRequest.bind(
server.plugins.kibana.systemApi
),
});

const plugin = this;
const config = server.config();
const xpackInfoFeature = xpackInfo.feature(plugin.id);

// Register a function that is called whenever the xpack info changes,
// to re-compute the license check results for this plugin
xpackInfoFeature.registerLicenseCheckResultsGenerator(checkLicense);

validateConfig(config, message => server.log(['security', 'warning'], message));

// Create a Hapi auth scheme that should be applied to each request.
server.auth.scheme('login', () => ({ authenticate: authenticateFactory(server) }));

server.auth.strategy('session', 'login');

// The default means that the `session` strategy that is based on `login` schema defined above will be
// automatically assigned to all routes that don't contain an auth config.
server.auth.default('session');
server.expose({ getUser: request => securityPlugin.authc.getCurrentUser(KibanaRequest.from(request)) });

const { savedObjects } = server;

Expand Down Expand Up @@ -203,20 +189,17 @@ export const security = (kibana) => new kibana.Plugin({
return client;
});

getUserProvider(server);

await initAuthenticator(server);
initAuthenticateApi(server);
initAuthenticateApi(securityPlugin, server);
initAPIAuthorization(server, authorization);
initAppAuthorization(server, xpackMainPlugin, authorization);
initUsersApi(server);
initUsersApi(securityPlugin, server);
initExternalRolesApi(server);
initIndicesApi(server);
initPrivilegesApi(server);
initGetBuiltinPrivilegesApi(server);
initLoginView(server, xpackMainPlugin);
initLoginView(securityPlugin, server, xpackMainPlugin);
initLogoutView(server);
initLoggedOutView(server);
initLoggedOutView(securityPlugin, server);
initOverwrittenSessionView(server);

server.injectUiAppVars('login', () => {
Expand Down
116 changes: 0 additions & 116 deletions x-pack/legacy/plugins/security/index.test.js

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { EuiFieldText } from '@elastic/eui';
import { ReactWrapper } from 'enzyme';
import React from 'react';
import { mountWithIntl } from 'test_utils/enzyme_helpers';
import { User } from '../../../../common/model/user';
import { User } from '../../../../common/model';
import { UserAPIClient } from '../../../lib/api';
import { ChangePasswordForm } from './change_password_form';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n/react';
import React, { ChangeEvent, Component } from 'react';
import { toastNotifications } from 'ui/notify';
import { User } from '../../../../common/model/user';
import { User } from '../../../../common/model';
import { UserAPIClient } from '../../../lib/api';

interface Props {
Expand Down
Loading

0 comments on commit 91e1d9c

Please sign in to comment.