Merge pull request #7067 from ycombinator/gh-7059
Disallow Console from functioning as an open web proxy
This commit is contained in:
commit
5a41292a68
|
@ -16,7 +16,9 @@ module.exports = function (kibana) {
|
|||
main: 'plugins/console/console',
|
||||
icon: 'plugins/console/logo.svg',
|
||||
injectVars: function (server, options) {
|
||||
return options;
|
||||
const varsToInject = options;
|
||||
varsToInject.elasticsearchUrl = server.config().get('elasticsearch.url');
|
||||
return varsToInject;
|
||||
}
|
||||
}
|
||||
];
|
||||
|
@ -33,11 +35,11 @@ module.exports = function (kibana) {
|
|||
|
||||
return new kibana.Plugin({
|
||||
id: 'console',
|
||||
require: [ 'elasticsearch' ],
|
||||
|
||||
config: function (Joi) {
|
||||
return Joi.object({
|
||||
enabled: Joi.boolean().default(true),
|
||||
defaultServerUrl: Joi.string().default('http://localhost:9200'),
|
||||
proxyFilter: Joi.array().items(Joi.string()).single().default(['.*']),
|
||||
ssl: Joi.object({
|
||||
verify: Joi.boolean(),
|
||||
|
@ -88,10 +90,7 @@ module.exports = function (kibana) {
|
|||
const proxyRouteConfig = {
|
||||
validate: {
|
||||
query: Joi.object().keys({
|
||||
uri: Joi.string().uri({
|
||||
allowRelative: false,
|
||||
shema: ['http:', 'https:'],
|
||||
}),
|
||||
uri: Joi.string()
|
||||
}).unknown(true),
|
||||
},
|
||||
|
||||
|
@ -111,15 +110,23 @@ module.exports = function (kibana) {
|
|||
],
|
||||
|
||||
handler(req, reply) {
|
||||
const { uri } = req.query;
|
||||
let baseUri = server.config().get('elasticsearch.url');
|
||||
let { uri:path } = req.query;
|
||||
|
||||
baseUri = baseUri.replace(/\/+$/, '');
|
||||
path = path.replace(/^\/+/, '');
|
||||
const uri = baseUri + '/' + path;
|
||||
|
||||
const requestHeadersWhitelist = server.config().get('elasticsearch.requestHeadersWhitelist');
|
||||
const filterHeaders = server.plugins.elasticsearch.filterHeaders;
|
||||
reply.proxy({
|
||||
uri,
|
||||
mapUri: function (request, done) {
|
||||
done(null, uri, filterHeaders(request.headers, requestHeadersWhitelist))
|
||||
},
|
||||
xforward: true,
|
||||
passThrough: true,
|
||||
onResponse(err, res, request, reply, settings, ttl) {
|
||||
if (err != null) {
|
||||
reply("Error connecting to '" + request.query.uri + "':\n\n" + err.message).type("text/plain").statusCode = 502;
|
||||
reply("Error connecting to '" + uri + "':\n\n" + err.message).type("text/plain").statusCode = 502;
|
||||
} else {
|
||||
reply(null, res);
|
||||
}
|
||||
|
|
|
@ -10,15 +10,10 @@ let utils = require('./utils');
|
|||
let _ = require('lodash');
|
||||
const chrome = require('ui/chrome');
|
||||
|
||||
const defaultServerUrl = chrome.getInjected('defaultServerUrl');
|
||||
|
||||
$(document.body).removeClass('fouc');
|
||||
|
||||
// set the value of the server and/or the input and clear the output
|
||||
function resetToValues(server, content) {
|
||||
if (server != null) {
|
||||
es.setBaseUrl(server);
|
||||
}
|
||||
// set the value of the input and clear the output
|
||||
function resetToValues(content) {
|
||||
if (content != null) {
|
||||
input.update(content);
|
||||
}
|
||||
|
@ -31,10 +26,10 @@ function loadSavedState() {
|
|||
|
||||
if (sourceLocation == "stored") {
|
||||
if (previousSaveState) {
|
||||
resetToValues(previousSaveState.server, previousSaveState.content);
|
||||
resetToValues(previousSaveState.content);
|
||||
}
|
||||
else {
|
||||
resetToValues(defaultServerUrl);
|
||||
resetToValues();
|
||||
input.autoIndent();
|
||||
}
|
||||
}
|
||||
|
@ -44,17 +39,14 @@ function loadSavedState() {
|
|||
loadFrom.headers = {Accept: "application/vnd.github.v3.raw"};
|
||||
}
|
||||
$.ajax(loadFrom).done(function (data) {
|
||||
resetToValues(defaultServerUrl, data);
|
||||
resetToValues(data);
|
||||
input.moveToNextRequestEdge(true);
|
||||
input.highlightCurrentRequestsAndUpdateActionBar();
|
||||
input.updateActionsBar();
|
||||
});
|
||||
}
|
||||
else if (previousSaveState) {
|
||||
resetToValues(previousSaveState.server);
|
||||
}
|
||||
else {
|
||||
resetToValues(defaultServerUrl);
|
||||
resetToValues();
|
||||
}
|
||||
input.moveToNextRequestEdge(true);
|
||||
}
|
||||
|
@ -69,15 +61,12 @@ function setupAutosave() {
|
|||
}
|
||||
timer = setTimeout(saveCurrentState, saveDelay);
|
||||
});
|
||||
|
||||
es.addServerChangeListener(saveCurrentState);
|
||||
}
|
||||
|
||||
function saveCurrentState() {
|
||||
try {
|
||||
var content = input.getValue();
|
||||
var server = es.getBaseUrl();
|
||||
history.updateCurrentState(server, content);
|
||||
history.updateCurrentState(content);
|
||||
}
|
||||
catch (e) {
|
||||
console.log("Ignoring saving error: " + e);
|
||||
|
|
|
@ -32,13 +32,4 @@ module.controller('SenseController', function SenseController($scope, docTitle)
|
|||
event.preventDefault();
|
||||
input.focus();
|
||||
};
|
||||
|
||||
this.serverUrl = es.getBaseUrl();
|
||||
|
||||
// read server url changes into scope
|
||||
es.addServerChangeListener((server) => {
|
||||
$scope.$evalAsync(() => {
|
||||
this.serverUrl = server;
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -7,27 +7,3 @@
|
|||
</span>
|
||||
</div>
|
||||
</kbn-top-nav>
|
||||
|
||||
<navbar ng-show="chrome.getVisible()" name="sense-serverInput">
|
||||
<form
|
||||
name="serverInput"
|
||||
class="fill inline-form"
|
||||
ng-submit="sense.sendSelected()"
|
||||
role="form">
|
||||
|
||||
<input
|
||||
type="text"
|
||||
placeholder="http://servername:port"
|
||||
aria-label="Server Name"
|
||||
class="form-control"
|
||||
ng-focus="navbar.updateServerUrlHistory()"
|
||||
ng-blur="navbar.commitServerUrlFormModel()"
|
||||
|
||||
sense-uib-typeahead="url for url in navbar.serverUrlHistory"
|
||||
ng-model="navbar.serverUrlFormModel"
|
||||
typeahead-append-to-body="true"
|
||||
typeahead-focus-first="false"
|
||||
|
||||
required>
|
||||
</form>
|
||||
</navbar>
|
||||
|
|
|
@ -14,7 +14,6 @@ require('ui/modules')
|
|||
scope: {},
|
||||
link($scope, $el, attrs, sense) {
|
||||
$scope.sense = sense
|
||||
$scope.navbar.link($scope)
|
||||
},
|
||||
controllerAs: 'navbar',
|
||||
controller: class SenseNavbarController {
|
||||
|
@ -49,21 +48,6 @@ require('ui/modules')
|
|||
this.menu.open('welcome')
|
||||
}
|
||||
|
||||
this.updateServerUrlHistory();
|
||||
}
|
||||
|
||||
link($scope) {
|
||||
$scope.$watch('sense.serverUrl', (url) => {
|
||||
this.serverUrlFormModel = url
|
||||
})
|
||||
}
|
||||
|
||||
updateServerUrlHistory() {
|
||||
this.serverUrlHistory = history.getHistoricalServers();
|
||||
}
|
||||
|
||||
commitServerUrlFormModel() {
|
||||
es.setBaseUrl(this.serverUrlFormModel);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1,13 +1,8 @@
|
|||
let _ = require('lodash');
|
||||
let $ = require('jquery');
|
||||
|
||||
let baseUrl;
|
||||
let serverChangeListeners = [];
|
||||
let esVersion = [];
|
||||
|
||||
module.exports.getBaseUrl = function () {
|
||||
return baseUrl;
|
||||
};
|
||||
module.exports.getVersion = function () {
|
||||
return esVersion;
|
||||
};
|
||||
|
@ -15,15 +10,7 @@ module.exports.getVersion = function () {
|
|||
module.exports.send = function (method, path, data, server, disable_auth_alert) {
|
||||
var wrappedDfd = $.Deferred();
|
||||
|
||||
server = server || exports.getBaseUrl();
|
||||
path = exports.constructESUrl(server, path);
|
||||
var uname_password_re = /^(https?:\/\/)?(?:(?:([^\/]*):)?([^\/]*?)@)?(.*)$/;
|
||||
var url_parts = path.match(uname_password_re);
|
||||
|
||||
var uname = url_parts[2];
|
||||
var password = url_parts[3];
|
||||
path = url_parts[1] + url_parts[4];
|
||||
console.log("Calling " + path + " (uname: " + uname + " pwd: " + password + ")");
|
||||
console.log("Calling " + path);
|
||||
if (data && method == "GET") {
|
||||
method = "POST";
|
||||
}
|
||||
|
@ -37,8 +24,6 @@ module.exports.send = function (method, path, data, server, disable_auth_alert)
|
|||
cache: false,
|
||||
crossDomain: true,
|
||||
type: method,
|
||||
password: password,
|
||||
username: uname,
|
||||
dataType: "text", // disable automatic guessing
|
||||
};
|
||||
|
||||
|
@ -56,61 +41,8 @@ module.exports.send = function (method, path, data, server, disable_auth_alert)
|
|||
return wrappedDfd;
|
||||
};
|
||||
|
||||
module.exports.constructESUrl = function (server, path) {
|
||||
if (!path) {
|
||||
path = server;
|
||||
server = exports.getBaseUrl();
|
||||
}
|
||||
if (path.indexOf("://") >= 0) {
|
||||
return path;
|
||||
}
|
||||
if (server.indexOf("://") < 0) {
|
||||
server = (document.location.protocol || "http:") + "//" + server;
|
||||
}
|
||||
if (server.substr(-1) == "/") {
|
||||
server = server.substr(0, server.length - 1);
|
||||
}
|
||||
if (path.charAt(0) === "/") {
|
||||
path = path.substr(1);
|
||||
}
|
||||
|
||||
return server + "/" + path;
|
||||
};
|
||||
|
||||
module.exports.forceRefresh = function () {
|
||||
exports.setBaseUrl(baseUrl, true)
|
||||
};
|
||||
|
||||
module.exports.setBaseUrl = function (base, force) {
|
||||
if (baseUrl !== base || force) {
|
||||
var old = baseUrl;
|
||||
baseUrl = base;
|
||||
exports.send("GET", "/").done(function (data, status, xhr) {
|
||||
if (xhr.status === 200) {
|
||||
// parse for version
|
||||
var value = xhr.responseText;
|
||||
try {
|
||||
value = JSON.parse(value);
|
||||
if (value.version && value.version.number) {
|
||||
esVersion = value.version.number.split(".");
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
|
||||
}
|
||||
}
|
||||
_.each(serverChangeListeners, function (cb) {
|
||||
cb(base, old)
|
||||
});
|
||||
}).fail(function () {
|
||||
esVersion = []; // unknown
|
||||
_.each(serverChangeListeners, function (cb) {
|
||||
cb(base, old)
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
module.exports.addServerChangeListener = function (cb) {
|
||||
serverChangeListeners.push(cb);
|
||||
module.exports.constructESUrl = function (baseUri, path) {
|
||||
baseUri = baseUri.replace(/\/+$/, '');
|
||||
path = path.replace(/^\/+/, '');
|
||||
return baseUri + '/' + path;
|
||||
};
|
||||
|
|
|
@ -3,8 +3,6 @@ const { uniq } = require('lodash');
|
|||
const storage = require('./storage');
|
||||
const chrome = require('ui/chrome');
|
||||
|
||||
const defaultServerUrl = chrome.getInjected('defaultServerUrl');
|
||||
|
||||
const history = module.exports = {
|
||||
restoreFromHistory() {
|
||||
// default method for history.restoreFromHistory
|
||||
|
@ -26,11 +24,7 @@ const history = module.exports = {
|
|||
.map(key => storage.get(key));
|
||||
},
|
||||
|
||||
getHistoricalServers() {
|
||||
return uniq(history.getHistory().map(req => req.server));
|
||||
},
|
||||
|
||||
addToHistory(server, endpoint, method, data) {
|
||||
addToHistory(endpoint, method, data) {
|
||||
var keys = history.getHistoryKeys();
|
||||
keys.splice(0, 500); // only maintain most recent X;
|
||||
$.each(keys, function (i, k) {
|
||||
|
@ -41,18 +35,16 @@ const history = module.exports = {
|
|||
var k = "hist_elem_" + timestamp;
|
||||
storage.set(k, {
|
||||
time: timestamp,
|
||||
server: server,
|
||||
endpoint: endpoint,
|
||||
method: method,
|
||||
data: data
|
||||
});
|
||||
},
|
||||
|
||||
updateCurrentState(server, content) {
|
||||
updateCurrentState(content) {
|
||||
var timestamp = new Date().getTime();
|
||||
storage.set("editor_state", {
|
||||
time: timestamp,
|
||||
server: server === defaultServerUrl ? undefined : server,
|
||||
content: content
|
||||
});
|
||||
},
|
||||
|
@ -60,8 +52,8 @@ const history = module.exports = {
|
|||
getSavedEditorState() {
|
||||
const saved = storage.get('editor_state');
|
||||
if (!saved) return;
|
||||
const { time, server = defaultServerUrl, content } = saved;
|
||||
return { time, server, content };
|
||||
const { time, content } = saved;
|
||||
return { time, content };
|
||||
},
|
||||
|
||||
clearHistory($el) {
|
||||
|
|
|
@ -158,7 +158,7 @@ function sendCurrentRequestToES() {
|
|||
((xhr.status >= 200 && xhr.status < 300) || xhr.status == 404)
|
||||
) {
|
||||
// we have someone on the other side. Add to history
|
||||
history.addToHistory(es.getBaseUrl(), es_path, es_method, es_data);
|
||||
history.addToHistory(es_path, es_method, es_data);
|
||||
|
||||
|
||||
let value = xhr.responseText;
|
||||
|
|
|
@ -238,27 +238,7 @@ function setActiveApi(api) {
|
|||
ACTIVE_API = api;
|
||||
}
|
||||
|
||||
es.addServerChangeListener(function () {
|
||||
var version = es.getVersion() || [];
|
||||
var api;
|
||||
|
||||
switch (version[0]) {
|
||||
case '5':
|
||||
api = 'es_5_0';
|
||||
break;
|
||||
case '2':
|
||||
api = 'es_2_0';
|
||||
break;
|
||||
case '1':
|
||||
default:
|
||||
api = 'es_1_0';
|
||||
}
|
||||
|
||||
if (api) {
|
||||
setActiveApi(api);
|
||||
}
|
||||
|
||||
});
|
||||
setActiveApi('es_5_0');
|
||||
|
||||
module.exports.setActiveApi = setActiveApi;
|
||||
module.exports.getGlobalAutocompleteComponents = getGlobalAutocompleteComponents;
|
||||
|
|
|
@ -279,8 +279,6 @@ function autocomplete_retriever() {
|
|||
}, 60000);
|
||||
}
|
||||
|
||||
es.addServerChangeListener(retrieveAutocompleteInfoFromServer);
|
||||
|
||||
module.exports = _.assign(mappingObj, {
|
||||
getFields: getFields,
|
||||
getIndices: getIndices,
|
||||
|
|
|
@ -6,6 +6,8 @@ let RowParser = require('./row_parser');
|
|||
let InputMode = require('./mode/input');
|
||||
let utils = require('../utils');
|
||||
let es = require('../es');
|
||||
import chrome from 'ui/chrome';
|
||||
|
||||
const smartResize = require('../smart_resize');
|
||||
|
||||
function isInt(x) {
|
||||
|
@ -538,7 +540,8 @@ function SenseEditor($el) {
|
|||
es_method = req.method,
|
||||
es_data = req.data;
|
||||
|
||||
var url = es.constructESUrl(es.getBaseUrl() || "localhost:9200", es_path);
|
||||
const elasticsearchBaseUrl = chrome.getInjected('elasticsearchUrl');
|
||||
var url = es.constructESUrl(elasticsearchBaseUrl, es_path);
|
||||
|
||||
var ret = 'curl -X' + es_method + ' "' + url + '"';
|
||||
if (es_data && es_data.length) {
|
||||
|
|
|
@ -61,7 +61,6 @@ function updateSettings({ fontSize, wrapMode, autocomplete}) {
|
|||
setWrapMode(wrapMode);
|
||||
setAutocomplete(autocomplete);
|
||||
require('./input').focus();
|
||||
es.forceRefresh();
|
||||
return getCurrentSettings();
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ var {test, module, ok, fail, asyncTest, deepEqual, equal, start} = QUnit;
|
|||
|
||||
module("Editor", {
|
||||
setup: function () {
|
||||
es.setBaseUrl("http://localhost:9200");
|
||||
input.$el.show();
|
||||
input.autocomplete._test.removeChangeListener();
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ const readFile = (file) => require('fs').readFileSync(file, 'utf8');
|
|||
import util from 'util';
|
||||
import url from 'url';
|
||||
import callWithRequest from './call_with_request';
|
||||
import filterHeaders from './filter_headers';
|
||||
|
||||
module.exports = function (server) {
|
||||
const config = server.config();
|
||||
|
@ -80,6 +81,7 @@ module.exports = function (server) {
|
|||
server.expose('createClient', createClient);
|
||||
server.expose('callWithRequestFactory', _.partial(callWithRequest, server));
|
||||
server.expose('callWithRequest', callWithRequest(server, noAuthClient));
|
||||
server.expose('filterHeaders', filterHeaders);
|
||||
server.expose('errors', elasticsearch.errors);
|
||||
|
||||
return client;
|
||||
|
|
|
@ -42,13 +42,9 @@ import {
|
|||
.catch(common.handleError(this));
|
||||
});
|
||||
|
||||
bdd.it('default request reponse should contain .kibana' , function () {
|
||||
bdd.it('default request response should contain .kibana' , function () {
|
||||
var expectedResponseContains = '"_index": ".kibana",';
|
||||
var elasticsearch = common.getEsHostPort();
|
||||
return consolePage.setServer(elasticsearch)
|
||||
.then(function () {
|
||||
return consolePage.clickPlay();
|
||||
})
|
||||
consolePage.clickPlay()
|
||||
.then(function () {
|
||||
return common.try(function () {
|
||||
return consolePage.getResponse()
|
||||
|
|
Loading…
Reference in a new issue