Skip to content

Commit

Permalink
Introduce Kerberos authentication provider.
Browse files Browse the repository at this point in the history
  • Loading branch information
azasypkin committed May 9, 2019
1 parent db59e44 commit 4726186
Show file tree
Hide file tree
Showing 17 changed files with 790 additions and 9 deletions.
4 changes: 4 additions & 0 deletions packages/kbn-es/src/cluster.js
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,10 @@ exports.Cluster = class Cluster {

this._process = execa(ES_BIN, args, {
cwd: installPath,
env: {
...process.env,
...(options.esEnvVars || {}),
},
stdio: ['ignore', 'pipe', 'pipe'],
});

Expand Down
3 changes: 2 additions & 1 deletion packages/kbn-test/src/es/es_test_cluster.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export function createEsTestCluster(options = {}) {
return esFrom === 'snapshot' ? 3 * minute : 6 * minute;
}

async start(esArgs = []) {
async start(esArgs = [], esEnvVars) {
let installPath;

if (esFrom === 'source') {
Expand All @@ -87,6 +87,7 @@ export function createEsTestCluster(options = {}) {
'discovery.type=single-node',
...esArgs,
],
esEnvVars,
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export async function runElasticsearch({ config, options }) {
const { log, esFrom } = options;
const license = config.get('esTestCluster.license');
const esArgs = config.get('esTestCluster.serverArgs');
const esEnvVars = config.get('esTestCluster.serverEnvVars');
const isSecurityEnabled = esArgs.includes('xpack.security.enabled=true');

const cluster = createEsTestCluster({
Expand All @@ -41,7 +42,7 @@ export async function runElasticsearch({ config, options }) {
dataArchive: config.get('esTestCluster.dataArchive'),
});

await cluster.start(esArgs);
await cluster.start(esArgs, esEnvVars);

if (isSecurityEnabled) {
await setupUsers(log, config.get('servers.elasticsearch.port'), [
Expand Down
1 change: 1 addition & 0 deletions src/functional_test_runner/lib/config/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ export const schema = Joi.object()
license: Joi.string().default('oss'),
from: Joi.string().default('snapshot'),
serverArgs: Joi.array(),
serverEnvVars: Joi.object(),
dataArchive: Joi.string(),
})
.default(),
Expand Down
19 changes: 14 additions & 5 deletions x-pack/plugins/security/server/lib/auth_redirect.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,27 @@ export function authenticateFactory(server) {

if (authenticationResult.succeeded()) {
return h.authenticated({ credentials: authenticationResult.user });
} else if (authenticationResult.redirected()) {
}

if (authenticationResult.redirected()) {
// Some authentication mechanisms may require user to be redirected to another location to
// initiate or complete authentication flow. It can be Kibana own login page for basic
// authentication (username and password) or arbitrary external page managed by 3rd party
// Identity Provider for SSO authentication mechanisms. Authentication provider is the one who
// decides what location user should be redirected to.
return h.redirect(authenticationResult.redirectURL).takeover();
} else if (authenticationResult.failed()) {
}

if (authenticationResult.failed()) {
server.log(['info', 'authentication'], `Authentication attempt failed: ${authenticationResult.error.message}`);
return wrapError(authenticationResult.error);
} else {
return Boom.unauthorized();
const error = wrapError(authenticationResult.error);
if (authenticationResult.challenges) {
error.output.headers['WWW-Authenticate'] = authenticationResult.challenges;
}

return error;
}

return Boom.unauthorized();
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* Represents status that `AuthenticationResult` can be in.
*/
import { AuthenticatedUser } from '../../../common/model';
import { getErrorStatusCode } from '../errors';

enum AuthenticationResultStatus {
/**
Expand Down Expand Up @@ -40,6 +41,7 @@ enum AuthenticationResultStatus {
*/
interface AuthenticationOptions {
error?: Error;
challenges?: string[];
redirectURL?: string;
state?: unknown;
user?: AuthenticatedUser;
Expand Down Expand Up @@ -73,13 +75,21 @@ export class AuthenticationResult {
/**
* Produces `AuthenticationResult` for the case when authentication fails.
* @param error Error that occurred during authentication attempt.
* @param [challenges] Optional list of the challenges that will be returned to the user within
* `WWW-Authenticate` HTTP header. Multiple challenges will result into multiple headers (one per
* challenge) as it's better supported by the browsers than comma separated list within a single
* header. Challenges can only be set for errors with `401` error status.
*/
public static failed(error: Error) {
public static failed(error: Error, challenges?: string[]) {
if (!error) {
throw new Error('Error should be specified.');
}

return new AuthenticationResult(AuthenticationResultStatus.Failed, { error });
if (challenges != null && getErrorStatusCode(error) !== 401) {
throw new Error('Challenges can only be provided with `401 Unauthorized` errors.');
}

return new AuthenticationResult(AuthenticationResultStatus.Failed, { error, challenges });
}

/**
Expand Down Expand Up @@ -117,6 +127,13 @@ export class AuthenticationResult {
return this.options.error;
}

/**
* Challenges that need to be sent to the user within `WWW-Authenticate` HTTP header.
*/
public get challenges() {
return this.options.challenges;
}

/**
* URL that should be used to redirect user to complete authentication only available
* for `redirected` result).
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
AuthenticationProviderOptions,
BaseAuthenticationProvider,
BasicAuthenticationProvider,
KerberosAuthenticationProvider,
SAMLAuthenticationProvider,
TokenAuthenticationProvider,
} from './providers';
Expand All @@ -32,6 +33,7 @@ const providerMap = new Map<
new (options: AuthenticationProviderOptions) => BaseAuthenticationProvider
>([
['basic', BasicAuthenticationProvider],
['kerberos', KerberosAuthenticationProvider],
['saml', SAMLAuthenticationProvider],
['token', TokenAuthenticationProvider],
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@

export { BaseAuthenticationProvider, AuthenticationProviderOptions } from './base';
export { BasicAuthenticationProvider, BasicCredentials } from './basic';
export { KerberosAuthenticationProvider } from './kerberos';
export { SAMLAuthenticationProvider } from './saml';
export { TokenAuthenticationProvider } from './token';
Loading

0 comments on commit 4726186

Please sign in to comment.