我已将弹性搜索服务器放在提供基本身份验证的Apache反向代理之后。
直接从浏览器对Apache进行身份验证工作正常。但是,当我使用Kibana 3访问服务器时,我收到身份验证错误。
显然因为没有与Kibana的Ajax调用一起发送auth标头。
我将以下内容添加到Kibana供应商目录中的elastic-angular-client.js,以实现快速和脏的身份验证。但由于某种原因,它不起作用。
$http.defaults.headers.common.Authorization = 'Basic ' + Base64Encode('user:Password');
在Kibana中实施基本身份验证的最佳方法和地点是什么?
/*! elastic.js - v1.1.1 - 2013-05-24
* https://github.com/fullscale/elastic.js
* Copyright (c) 2013 FullScale Labs, LLC; Licensed MIT */
/*jshint browser:true */
/*global angular:true */
'use strict';
/*
Angular.js service wrapping the elastic.js API. This module can simply
be injected into your angular controllers.
*/
angular.module('elasticjs.service', [])
.factory('ejsResource', ['$http', function ($http) {
return function (config) {
var
// use existing ejs object if it exists
ejs = window.ejs || {},
/* results are returned as a promise */
promiseThen = function (httpPromise, successcb, errorcb) {
return httpPromise.then(function (response) {
(successcb || angular.noop)(response.data);
return response.data;
}, function (response) {
(errorcb || angular.noop)(response.data);
return response.data;
});
};
// check if we have a config object
// if not, we have the server url so
// we convert it to a config object
if (config !== Object(config)) {
config = {server: config};
}
// set url to empty string if it was not specified
if (config.server == null) {
config.server = '';
}
/* implement the elastic.js client interface for angular */
ejs.client = {
server: function (s) {
if (s == null) {
return config.server;
}
config.server = s;
return this;
},
post: function (path, data, successcb, errorcb) {
$http.defaults.headers.common.Authorization = 'Basic ' + Base64Encode('user:Password');
console.log($http.defaults.headers);
path = config.server + path;
var reqConfig = {url: path, data: data, method: 'POST'};
return promiseThen($http(angular.extend(reqConfig, config)), successcb, errorcb);
},
get: function (path, data, successcb, errorcb) {
$http.defaults.headers.common.Authorization = 'Basic ' + Base64Encode('user:Password');
path = config.server + path;
// no body on get request, data will be request params
var reqConfig = {url: path, params: data, method: 'GET'};
return promiseThen($http(angular.extend(reqConfig, config)), successcb, errorcb);
},
put: function (path, data, successcb, errorcb) {
$http.defaults.headers.common.Authorization = 'Basic ' + Base64Encode('user:Password');
path = config.server + path;
var reqConfig = {url: path, data: data, method: 'PUT'};
return promiseThen($http(angular.extend(reqConfig, config)), successcb, errorcb);
},
del: function (path, data, successcb, errorcb) {
$http.defaults.headers.common.Authorization = 'Basic ' + Base64Encode('user:Password');
path = config.server + path;
var reqConfig = {url: path, data: data, method: 'DELETE'};
return promiseThen($http(angular.extend(reqConfig, config)), successcb, errorcb);
},
head: function (path, data, successcb, errorcb) {
$http.defaults.headers.common.Authorization = 'Basic ' + Base64Encode('user:Password');
path = config.server + path;
// no body on HEAD request, data will be request params
var reqConfig = {url: path, params: data, method: 'HEAD'};
return $http(angular.extend(reqConfig, config))
.then(function (response) {
(successcb || angular.noop)(response.headers());
return response.headers();
}, function (response) {
(errorcb || angular.noop)(undefined);
return undefined;
});
}
};
return ejs;
};
}]);
更新1:我实施了Matts建议。但是,服务器返回一个奇怪的响应。似乎授权标头不起作用。可能与事实有关,我在81端口运行Kibana,在8181上运行elasticsearch?
OPTIONS /solar_vendor/_search HTTP/1.1
Host: 46.252.46.173:8181
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Origin: http://46.252.46.173:81
Access-Control-Request-Method: POST
Access-Control-Request-Headers: authorization,content-type
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
这是回复
HTTP/1.1 401 Authorization Required
Date: Fri, 08 Nov 2013 23:47:02 GMT
WWW-Authenticate: Basic realm="Username/Password"
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 346
Connection: close
Content-Type: text/html; charset=iso-8859-1
更新2:使用这些Kibana文件中已修改的标头更新了所有实例
root@localhost:/var/www/kibana# grep -r 'ejsResource(' .
./src/app/controllers/dash.js: $scope.ejs = ejsResource({server: config.elasticsearch, headers: {'Access-Control-Request-Headers': 'Accept, Origin, Authorization', 'Authorization': 'Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXX=='}});
./src/app/services/querySrv.js: var ejs = ejsResource({server: config.elasticsearch, headers: {'Access-Control-Request-Headers': 'Accept, Origin, Authorization', 'Authorization': 'Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXX=='}});
./src/app/services/filterSrv.js: var ejs = ejsResource({server: config.elasticsearch, headers: {'Access-Control-Request-Headers': 'Accept, Origin, Authorization', 'Authorization': 'Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXX=='}});
./src/app/services/dashboard.js: var ejs = ejsResource({server: config.elasticsearch, headers: {'Access-Control-Request-Headers': 'Accept, Origin, Authorization', 'Authorization': 'Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXX=='}});
并像我这样修改了我的vhost conf for reverse proxy
<VirtualHost *:8181>
ProxyRequests Off
ProxyPass / http://127.0.0.1:9200/
ProxyPassReverse / https://127.0.0.1:9200/
<Location />
Order deny,allow
Allow from all
AuthType Basic
AuthName “Username/Password”
AuthUserFile /var/www/cake2.2.4/.htpasswd
Require valid-user
Header always set Access-Control-Allow-Methods "GET, POST, DELETE, OPTIONS, PUT"
Header always set Access-Control-Allow-Headers "Content-Type, X-Requested-With, X-HTTP-Method-Override, Origin, Accept, Authorization"
Header always set Access-Control-Allow-Credentials "true"
Header always set Cache-Control "max-age=0"
Header always set Access-Control-Allow-Origin *
</Location>
ErrorLog ${APACHE_LOG_DIR}/error.log
</VirtualHost>
Apache发送回新的响应标头,但请求标头在某处似乎仍然是错误的。身份验证不起作用。
请求标题
OPTIONS /solar_vendor/_search HTTP/1.1
Host: 46.252.26.173:8181
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:25.0) Gecko/20100101 Firefox/25.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Origin: http://46.252.26.173:81
Access-Control-Request-Method: POST
Access-Control-Request-Headers: authorization,content-type
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
响应标头
HTTP/1.1 401 Authorization Required
Date: Sat, 09 Nov 2013 08:48:48 GMT
Access-Control-Allow-Methods: GET, POST, DELETE, OPTIONS, PUT
Access-Control-Allow-Headers: Content-Type, X-Requested-With, X-HTTP-Method-Override, Origin, Accept, Authorization
Access-Control-Allow-Credentials: true
Cache-Control: max-age=0
Access-Control-Allow-Origin: *
WWW-Authenticate: Basic realm="Username/Password"
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 346
Connection: close
Content-Type: text/html; charset=iso-8859-1
解: 在做了一些更多的研究之后,我发现这肯定是关于CORS的配置问题。关于该主题有很多帖子可用,但似乎为了解决我的问题,有必要在apache上做一些非常精细的配置,并确保从浏览器发送正确的东西。
所以我重新考虑了这个策略并找到了一个更简单的解决方案。只需修改vhost反向代理配置,即可在同一个http端口上移动弹性系统服务器和kibana。这也为Kibana增添了更好的安全性。
这就是我所做的:
<VirtualHost *:8181>
ProxyRequests Off
ProxyPass /bigdatadesk/ http://127.0.0.1:81/bigdatadesk/src/
ProxyPassReverse /bigdatadesk/ http://127.0.0.1:81/bigdatadesk/src/
ProxyPass / http://127.0.0.1:9200/
ProxyPassReverse / https://127.0.0.1:9200/
<Location />
Order deny,allow
Allow from all
AuthType Basic
AuthName “Username/Password”
AuthUserFile /var/www/.htpasswd
Require valid-user
</Location>
ErrorLog ${APACHE_LOG_DIR}/error.log
</VirtualHost>
答案 0 :(得分:10)
这是一个完美的解决方案:
https://github.com/fangli/kibana-authentication-proxy
不仅支持basicAuth后端,还支持客户端的GoogleOAuth和BasicAuth。 如果有效,请给一个明星,谢谢。
答案 1 :(得分:7)
在Kibana中,将现有的elastic-angular-client.js替换为最新的here。然后,在Kibana代码中替换所有实例:
$scope.ejs = ejsResource(config.elasticsearch);
与
$scope.ejs = ejsResource({server: config.elasticsearch, headers: {'Access-Control-Request-Headers': 'accept, origin, authorization', 'Authorization': 'Basic ' + Base64Encode('user:Password')}});
这应该是你所需要的一切。
更新
是否为CORS配置了apache?请参阅this。
Header always set Access-Control-Allow-Methods "GET, POST, DELETE, OPTIONS, PUT"
Header always set Access-Control-Allow-Headers "Content-Type, X-Requested-With, X-HTTP-Method-Override, Origin, Accept, Authorization"
Header always set Access-Control-Allow-Credentials "true"
Header always set Cache-Control "max-age=0"
Header always set Access-Control-Allow-Origin *
答案 2 :(得分:1)
你是对的,因为它是一个CORS问题。 Kibana 3使用CORS与ElasticSearch进行通信。
为了使用Kibana CORS请求发送HTTP身份验证标头和Cookie,您需要做两件事:
ONE:在您的Kibana config.js文件中,找到定义ElasticSearch服务器的设置:
elasticsearch: "http://localhost:9200",
这需要更改为:
elasticsearch: {server: "http://localhost:9200", withCredentials: true},
这将告诉Kibana发送身份验证标头和Cookie,如果服务器能够接收它们。
TWO:接下来你需要进入你的ElasticSearch配置文件(主机服务器上的elasticsearch.yml;我的位于CentOS7服务器上的/etc/elasticsearch/elasticsearch.yml)。在此文件中,您将找到一个&#34;网络和HTTP&#34;部分。您需要找到以下行:
#http.port: 9200
取消注释此行并将端口更改为您希望运行ElasticSearch的端口。我选择了19200.然后为#transport.tcp.port: 9300
设置做同样的事情。我再次选择19300。
最后,在本节结尾处(仅为了组织起见,您还可以简单地将以下内容附加到文件的末尾)添加:
http.cors.allow-origin: http://localhost:8080
http.cors.allow-credentials: true
http.cors.enabled: true
您可以将上述原始地址更改为您的网络服务器从哪里提供Kibana。或者,您可以简单地将/.*/
与所有来源匹配,但这不建议。
现在保存elasticsearch.yml文件并重新启动elasticsearch服务器。您的反向代理应配置为在端口9200上运行,如果请求进行身份验证,则指向19200。
警告提示,如果您使用Cookie对请求进行身份验证,则应确保在反向代理配置中列出HTTP OPTIONS方法,因为只有GET,PUT,POST和DELETE请求包含Cookie。我还没有测试OPTIONS是否包含Authentication头,但它可能与cookies的情况相同。如果OPTIONS请求也无法通过,Kibana将无法正常运行。
将反向代理配置为将所有以_shutdown结尾的请求列入黑名单也是一个好主意,因为在大多数情况下,通过外部请求不需要此命令。