上下文
我正在使用 Node.js 和 Express 工作的 Web 应用程序中的几个位置嵌入 Kibana 4 仪表板。嵌入是 context-dependent,这意味着根据仪表板的嵌入位置,对 Elasticsearch 的查询会发生变化。
此外,嵌入仪表板的某些页面仅限于具有正确权限的某些用户。
由于 Kibana 4 中尚未实施身份验证,因此通过更改仪表板嵌入 URL 中的查询,任何用户都可以显示他们无权访问的页面的仪表板。
我们的方案
我们的想法是阻止任何与 Kibana(端口 5601)的外部连接,并通过我们的 Web 应用程序获取自定义 URL 并检查用户权限(代理类型)。如果用户拥有该权限,那么我们的 Web 应用程序会将 HTTP 查询转发给 Kibana。由于我们的 Web 应用程序和 Kibana 位于同一台服务器上,因此不会阻止这些查询。
要路由自定义 URL 并检查权限,我们提供以下信息:
app.route('/items/:itemId/analytics/*')
.all(api.requiresAccess('user'),
api.requiresPermissions('item', 'modify'),
items.getAnalytics);
然后我们在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 内部服务器错误,这会停止仪表板加载。
为了尝试找到问题,我将仪表板的负载与原始 Kibana URL 和通过 Web 应用程序重定向的 URL 之间的网络流量(在 Web 检查器中)进行了比较。开头是相同的,但在某些时候(在请求收到 500 错误之前),通过原始 URL 加载的仪表板会产生一个未使用重定向 URL 的请求。请求是POST
到http://localhost:5601/elasticsearch/_mget?timeout=0&ignore_unavailable=true&preference=1434374357241
,具有以下正文:{"docs":[{"_index":".kibana","_type":"dashboard","_id":"Standard-Dashboard"}]}
。
这个请求似乎非常重要,因为它包含仪表板 ID,我想它的缺席是后来产生 500 错误的原因。但我不知道为什么在通过 Web 应用程序重定向查询时不会发送此请求。
我也试过模块 http-proxy 和 express-http-proxy,但我面临同样的问题。
2 回答
对于那些正在寻找这类问题答案的人。我启用了一个位于我的 Elasticsearch 和 Kibana 之间的 Nginx 代理,用于配置对仪表板和图表的授权访问。看看我的帖子:https://udaysagars.wordpress.com/2016/04/04/how-i-configured-authorized-access-to-kibana-dashboards/
为了回答您的问题,Elastic Co 开发了一个名为 Shield 的产品,它提供访问控制,您可以为每个群集提供访问权限,为用户提供索引以及用于访问的用户名和密码。
您还可以使用用户制作的 Kibana 身份验证代理,该代理与 Kibana 完美配合,可在此处查看:
https://github.com/fangli/kibana-authentication-proxyhttps://github.com/fangli/kibana-authentication-proxy