Remove unused server functionality from the interpreter (#32133) (#32312)

This commit is contained in:
Chris Davies 2019-03-01 11:38:14 -05:00 committed by GitHub
parent 5035d13a52
commit aa73d53e96
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 4 additions and 290 deletions

View file

@ -17,5 +17,4 @@
* under the License.
*/
export const SECURITY_AUTH_MESSAGE = 'Authentication failed';
export const API_ROUTE = '/api/canvas';

View file

@ -19,12 +19,6 @@
import expect from 'expect.js';
import { createHandlers } from '../create_handlers';
import { SECURITY_AUTH_MESSAGE } from '../../../common/constants';
let securityMode = 'pass';
let isSecurityAvailable = true;
let isSecurityEnabled = true;
const authError = new Error('auth error');
const mockRequest = {
headers: 'i can haz headers',
@ -32,26 +26,11 @@ const mockRequest = {
const mockServer = {
plugins: {
security: {
authenticate: () => ({
succeeded: () => (securityMode === 'pass' ? true : false),
error: securityMode === 'pass' ? null : authError,
}),
},
elasticsearch: {
getCluster: () => ({
callWithRequest: (...args) => Promise.resolve(args),
}),
},
// TODO: remove this when we use the method exposed by security https://github.com/elastic/kibana/pull/24616
xpack_main: {
info: {
feature: () => ({
isAvailable: () => isSecurityAvailable,
isEnabled: () => isSecurityEnabled,
}),
},
},
},
config: () => ({
has: () => false,
@ -63,16 +42,9 @@ const mockServer = {
};
describe('server createHandlers', () => {
let handlers;
beforeEach(() => {
securityMode = 'pass';
isSecurityEnabled = true;
isSecurityAvailable = true;
handlers = createHandlers(mockRequest, mockServer);
});
it('provides helper methods and properties', () => {
const handlers = createHandlers(mockRequest, mockServer);
expect(handlers).to.have.property('environment', 'server');
expect(handlers).to.have.property('serverUri');
expect(handlers).to.have.property('elasticsearchClient');
@ -80,78 +52,7 @@ describe('server createHandlers', () => {
describe('elasticsearchClient', () => {
it('executes callWithRequest', async () => {
const [request, endpoint, payload] = await handlers.elasticsearchClient(
'endpoint',
'payload'
);
expect(request).to.equal(mockRequest);
expect(endpoint).to.equal('endpoint');
expect(payload).to.equal('payload');
});
it('rejects when authentication check fails', () => {
securityMode = 'fail';
return handlers
.elasticsearchClient('endpoint', 'payload')
.then(() => {
throw new Error('elasticsearchClient should fail when authentication fails');
})
.catch(err => {
expect(err.message).to.be.equal(SECURITY_AUTH_MESSAGE);
});
});
it('works without security plugin in kibana', async () => {
// create server without security plugin
const mockServerClone = {
...mockServer,
plugins: { ...mockServer.plugins },
};
delete mockServerClone.plugins.security;
expect(mockServer.plugins).to.have.property('security'); // confirm original server object
expect(mockServerClone.plugins).to.not.have.property('security');
// this shouldn't do anything
securityMode = 'fail';
// make sure the method still works
handlers = createHandlers(mockRequest, mockServerClone);
const [request, endpoint, payload] = await handlers.elasticsearchClient(
'endpoint',
'payload'
);
expect(request).to.equal(mockRequest);
expect(endpoint).to.equal('endpoint');
expect(payload).to.equal('payload');
});
it('works without security available', async () => {
// create server with security unavailable (i.e. when user is on a basic license)
isSecurityAvailable = false;
// this shouldn't do anything
securityMode = 'fail';
// make sure the method still works
handlers = createHandlers(mockRequest, mockServer);
const [request, endpoint, payload] = await handlers.elasticsearchClient(
'endpoint',
'payload'
);
expect(request).to.equal(mockRequest);
expect(endpoint).to.equal('endpoint');
expect(payload).to.equal('payload');
});
it('works with security disabled in elasticsearch', async () => {
// create server with security disabled
isSecurityEnabled = false;
// this shouldn't do anything
securityMode = 'fail';
// make sure the method still works
handlers = createHandlers(mockRequest, mockServer);
const handlers = createHandlers(mockRequest, mockServer);
const [request, endpoint, payload] = await handlers.elasticsearchClient(
'endpoint',
'payload'

View file

@ -17,10 +17,6 @@
* under the License.
*/
import boom from 'boom';
import { isSecurityEnabled } from './feature_check';
import { SECURITY_AUTH_MESSAGE } from '../../common/constants';
export const createHandlers = (request, server) => {
const { callWithRequest } = server.plugins.elasticsearch.getCluster('data');
const config = server.config();
@ -31,27 +27,6 @@ export const createHandlers = (request, server) => {
config.has('server.rewriteBasePath') && config.get('server.rewriteBasePath')
? `${server.info.uri}${config.get('server.basePath')}`
: server.info.uri,
elasticsearchClient: async (...args) => {
// check if the session is valid because continuing to use it
if (isSecurityEnabled(server)) {
try {
const authenticationResult = await server.plugins.security.authenticate(request);
if (!authenticationResult.succeeded()) {
throw boom.unauthorized(authenticationResult.error);
}
} catch (e) {
// if authenticate throws, show error in development
if (process.env.NODE_ENV !== 'production') {
e.message = `elasticsearchClient failed: ${e.message}`;
console.error(e);
}
// hide all failure information from the user
throw boom.unauthorized(SECURITY_AUTH_MESSAGE);
}
}
return callWithRequest(request, ...args);
},
elasticsearchClient: async (...args) => callWithRequest(request, ...args),
};
};

View file

@ -1,26 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
// TODO: replace this when we use the method exposed by security https://github.com/elastic/kibana/pull/24616
export const isSecurityEnabled = server => {
const kibanaSecurity = server.plugins.security;
const esSecurity = server.plugins.xpack_main.info.feature('security');
return kibanaSecurity && esSecurity.isAvailable() && esSecurity.isEnabled();
};

View file

@ -1,46 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { createError } from '@kbn/interpreter/common';
export const routeExpressionProvider = environments => {
async function routeExpression(ast, context = null) {
// List of environments in order of preference
return Promise.all(environments).then(async environments => {
const environmentFunctions = await Promise.all(environments.map(env => env.getFunctions()));
// Grab name of the first function in the chain
const fnName = ast.chain[0].function.toLowerCase();
// Check each environment for that function
for (let i = 0; i < environmentFunctions.length; i++) {
if (environmentFunctions[i].includes(fnName)) {
// If we find it, run in that environment, and only that environment
return environments[i].interpret(ast, context).catch(e => createError(e));
}
}
// If the function isn't found in any environment, give up
throw new Error(`Function not found: [${fnName}]`);
});
}
return routeExpression;
};

View file

@ -1,38 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { interpreterProvider } from '@kbn/interpreter/common';
import { createHandlers } from '../create_handlers';
export const server = async ({ server, request }) => {
const { serverFunctions, types } = server.plugins.interpreter.registries();
return {
interpret: (ast, context) => {
const interpret = interpreterProvider({
types: types.toJS(),
functions: serverFunctions.toJS(),
handlers: createHandlers(request, server),
});
return interpret(ast, context);
},
getFunctions: () => Object.keys(serverFunctions.toJS()),
};
};

View file

@ -17,10 +17,8 @@
* under the License.
*/
import { translate } from './translate';
import { registerServerFunctions } from './server_functions';
export function routes(server) {
translate(server);
registerServerFunctions(server);
}

View file

@ -1,48 +0,0 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { fromExpression, toExpression } from '@kbn/interpreter/common';
export function translate(server) {
/*
Get AST from expression
*/
server.route({
method: 'GET',
path: '/api/canvas/ast',
handler: function (request, h) {
if (!request.query.expression) {
return h.response({ error: '"expression" query is required' }).code(400);
}
return fromExpression(request.query.expression);
},
});
server.route({
method: 'POST',
path: '/api/canvas/expression',
handler: function (request, h) {
try {
return toExpression(request.payload);
} catch (e) {
return h.response({ error: e.message }).code(400);
}
},
});
}

View file

@ -18,6 +18,5 @@ export const LOCALSTORAGE_AUTOCOMPLETE_ENABLED = `${LOCALSTORAGE_PREFIX}.isAutoc
export const LOCALSTORAGE_LASTPAGE = 'canvas:lastpage';
export const FETCH_TIMEOUT = 30000; // 30 seconds
export const CANVAS_USAGE_TYPE = 'canvas';
export const SECURITY_AUTH_MESSAGE = 'Authentication failed';
export const DEFAULT_WORKPAD_CSS = '.canvasPage {\n\n}';
export const VALID_IMAGE_TYPES = ['gif', 'jpeg', 'png', 'svg+xml'];