Restrict ES data proxy to msearch and search (#13020)

We are only using msearch and search on this proxy, so there's no reason
for us to expose more capabilities than this. Ultimately we want to move
all functionality like this to REST API rather than being a straight up
proxy, so this will help proxy usage not expand throughout upcoming
versions until it can be removed entirely.
This commit is contained in:
Court Ewing 2017-07-21 11:29:49 -04:00 committed by GitHub
parent 72f6b8a37f
commit 1b024200cd
3 changed files with 14 additions and 53 deletions

View file

@ -1,6 +1,5 @@
import { compact, get, has, set, trim, trimRight } from 'lodash';
import { compact, get, has, set } from 'lodash';
import { unset } from '../../utils';
import { methodNotAllowed } from 'boom';
import healthCheck from './lib/health_check';
import { createDataCluster } from './lib/create_data_cluster';
@ -9,7 +8,7 @@ import { clientLogger } from './lib/client_logger';
import { createClusters } from './lib/create_clusters';
import filterHeaders from './lib/filter_headers';
import { createProxy, createPath } from './lib/create_proxy';
import { createProxy } from './lib/create_proxy';
const DEFAULT_REQUEST_HEADERS = [ 'authorization' ];
@ -106,7 +105,6 @@ export default function (kibana) {
},
init(server) {
const kibanaIndex = server.config().get('kibana.index');
const clusters = createClusters(server);
server.expose('getCluster', clusters.get);
@ -118,46 +116,9 @@ export default function (kibana) {
createDataCluster(server);
createAdminCluster(server);
createProxy(server, 'GET', '/{paths*}');
createProxy(server, 'POST', '/_mget');
createProxy(server, 'POST', '/{index}/_search');
createProxy(server, 'POST', '/{index}/_field_stats');
createProxy(server, 'POST', '/_msearch');
createProxy(server, 'POST', '/_search/scroll');
function noBulkCheck({ path }, reply) {
if (/\/_bulk/.test(path)) {
return reply({
error: 'You can not send _bulk requests to this interface.'
}).code(400).takeover();
}
return reply.continue();
}
function noDirectIndex({ path }, reply) {
const requestPath = trimRight(trim(path), '/');
const matchPath = createPath('/elasticsearch', kibanaIndex);
if (requestPath === matchPath) {
return reply(methodNotAllowed('You cannot modify the primary kibana index through this interface.'));
}
reply.continue();
}
// These routes are actually used to deal with things such as managing
// index patterns and advanced settings, but since hapi treats route
// wildcards as zero-or-more, the routes also match the kibana index
// itself. The client-side kibana code does not deal with creating nor
// destroying the kibana index, so we limit that ability here.
createProxy(
server,
['PUT', 'POST', 'DELETE'],
`/${kibanaIndex}/{paths*}`,
{
pre: [ noDirectIndex, noBulkCheck ]
}
);
// Set up the health check service and start it.
const { start, waitUntilReady } = healthCheck(this, server);
server.expose('waitUntilReady', waitUntilReady);

View file

@ -50,38 +50,38 @@ describe('plugins/elasticsearch', function () {
testRoute({
method: 'GET',
url: '/elasticsearch/_nodes'
});
}, 404);
testRoute({
method: 'GET',
url: '/elasticsearch/'
});
url: '/elasticsearch'
}, 404);
testRoute({
method: 'POST',
url: '/elasticsearch/.kibana'
}, 405);
}, 404);
testRoute({
method: 'PUT',
url: '/elasticsearch/.kibana'
}, 405);
}, 404);
testRoute({
method: 'DELETE',
url: '/elasticsearch/.kibana'
}, 405);
}, 404);
testRoute({
method: 'GET',
url: '/elasticsearch/.kibana'
});
}, 404);
testRoute({
method: 'POST',
url: '/elasticsearch/.kibana/_bulk',
payload: '{}'
}, 400);
}, 404);
testRoute({
method: 'POST',
@ -90,7 +90,7 @@ describe('plugins/elasticsearch', function () {
'content-type': 'application/json'
},
payload: { query: { query_string: { analyze_wildcard: true, query: '*' } } }
});
}, 404);
testRoute({
method: 'POST',
@ -99,7 +99,7 @@ describe('plugins/elasticsearch', function () {
'content-type': 'application/json'
},
payload: { docs: [{ _index: '.kibana', _type: 'index-pattern', _id: '[logstash-]YYYY.MM.DD' }] }
});
}, 404);
testRoute({
method: 'POST',

View file

@ -26,7 +26,7 @@ describe('formatMsg', function () {
data: {
statusCode: 403,
error: 'Forbidden',
message: '[security_exception] action [indices:data/read/mget] is unauthorized for user [user]'
message: '[security_exception] action [indices:data/read/msearch] is unauthorized for user [user]'
},
status: 403,
config: {},
@ -34,7 +34,7 @@ describe('formatMsg', function () {
};
const actual = formatMsg(err);
expect(actual).to.equal('Error 403 Forbidden: [security_exception] action [indices:data/read/mget] is unauthorized for user [user]');
expect(actual).to.equal('Error 403 Forbidden: [security_exception] action [indices:data/read/msearch] is unauthorized for user [user]');
});
it('should handle an extended elasticsearch error', function () {