Контекст
Я встраиваю панель управления Kibana 4 в несколько мест в веб-приложении, над которым я работаю, используя Node.js и Express. Встраивание зависит от контекста, что означает, что в зависимости от того, где встроена панель мониторинга, изменяется запрос к Elasticsearch.
Более того, некоторые страницы, на которых встроены информационные панели, доступны только некоторым пользователям с соответствующими разрешениями.
Поскольку в Kibana 4 еще не реализована аутентификация, изменив запрос на встроенном URL-адресе панели инструментов, любой пользователь может отобразить панель инструментов страницы, к которой у него нет доступа.
Наше решение
Идея состоит в том, чтобы заблокировать любое внешнее соединение с Kibana (порт 5601) и иметь настраиваемый URL-адрес, проходящий через наше веб-приложение, и проверять разрешения пользователя (своего рода прокси). И если у пользователя есть разрешение, наше веб-приложение пересылает HTTP-запросы в Kibana. Поскольку наше веб-приложение и Kibana находятся на одном сервере, эти запросы не блокируются.
Чтобы направить настраиваемый URL-адрес и проверить разрешение, у нас есть следующее:
app.route('/items/:itemId/analytics/*')
.all(api.requiresAccess('user'),
api.requiresPermissions('item', 'modify'),
items.getAnalytics);
Затем мы используем Request в функции getAnalytics
:
exports.getAnalytics = function (req, res) {
var itemId = req.item.id;
var kibanaParamsRegexp = /analytics\/(.*)/;
var kibanaParamsMatch = kibanaParamsRegexp.exec(req.originalUrl);
var kibanaParams = kibanaParamsMatch[1];
var method = req.method;
var dashboardId = 'Standard-Dashboard';
var kibanaDashboardURL = 'http://localhost:5601';
if (kibanaParams === '') { // First request to get the dashboard
kibanaDashboardURL += '/#/dashboard/' + dashboardId + '?embed' +
'&_a=(query:(query_string:(analyze_wildcard:!t,query:\'path:' + itemId + '\')))' +
'&_g=(time:(from:now-1y,mode:quick,to:now))';
} else { // Following requests to get the dashboard
kibanaDashboardURL += '/' + kibanaParams;
}
app.logger.info('Received from the dashboard: ' + req.originalUrl);
app.logger.info('Requesting to Kibana: ' + kibanaDashboardURL);
app.logger.info('Query body: ' + JSON.stringify(req.body));
if (method === 'POST') {
var options = {
url: kibanaDashboardURL,
json: true,
body: req.body
};
request.post(options,
function (err, httpResponse, body) {
if (err) {
return console.log('POST failed: ', err);
}
console.log('POST successful. Sever response: ', body);
}).pipe(res);
} else if (method === 'GET' || method === 'HEAD') {
request.get(kibanaDashboardURL).pipe(res);
}
};
Поэтому вместо http://localhost:5601/#/dashboard/Standard-dashboard?embed&_a=(query:(query_string:(analyze_wildcard:!t,query:'path: 5539e831b5b79bf9f4b06a3c')))&_g=(time:(from:now-1y,mode:quick,to:now))
,
я должен использовать http://localhost:8000/items/5539e831b5b79bf9f4b06a3c/analytics/
, который проверяет разрешения.
Проблема
Первые запросы, которые в основном составляют GET
и несколько POST
, проходят без проблем. Но в какой-то момент у меня есть POST
запрос, который возвращает ошибку 500 Internal Sever в ответ на запрос, который останавливает загрузку панели мониторинга.
Чтобы попытаться найти проблему, я сравнил сетевой трафик (в веб-инспекторе) между загрузкой панели управления с исходным URL-адресом Kibana и перенаправленным URL-адресом через веб-приложение. Начало идентично, но в какой-то момент (до того, как запрос получит обратно ошибку 500), загрузка панели мониторинга через исходный URL-адрес делает запрос, который не выполняется с перенаправленным URL-адресом. Это запрос от POST
до http://localhost:5601/elasticsearch/_mget?timeout=0&ignore_unavailable=true&preference=1434374357241
со следующим телом: {"docs":[{"_index":".kibana","_type":"dashboard","_id":"Standard-Dashboard"}]}
.
Этот запрос кажется очень важным, поскольку он содержит идентификатор панели инструментов, и я полагаю, что его отсутствие является причиной ошибки 500 позже. Но я не знаю, почему этот запрос не отправляется, когда я перенаправляю запросы через веб-приложение.
Я также пробовал использовать модули http-proxy и express-http-proxy, но столкнулся с теми же проблемами.