Nginx+Kibana+ElasticSearch"免密登录"
之前,搭建了一套ELK系统,主要用于日志分析。权限控制使用的是SearchGuard插件(主要是X-Pack收费,只得用SearchGuard来做替代了)。
最近,打算在某个Web应用中嵌入Kibana制作的数据图表,但是遇到了一个问题,就是通过Kibanas生成的iframe,放到Web应用中后,加载数据报表时,会要求登录Kibana。但是,Web系统本身就有一套用户权限的登录系统,这样,就会造成用户的二次登录。
为了解决这个问题,查阅了不少资料,做了几个尝试,最后终于找到了解决方法。
尝试一:
我通过页面调试,发现Kibana登录时,是用过调用接口http:///api/v1/auth/login来登录的。
于是,我尝试在加载自己页面的时候,也同样请求http:///api/v1/auth/login来登录获取session。传递的参数如下(测试工具使用的是Postman):

注意:Headers里面必须有kbn-name和kbn-version两个参数,否则请求无法成功。username、password则是登录Kibana的用户名和密码。
但是,我的Web应用和Kibana服务器不在同一个域名下,所以,这种方式会存在ajax的跨域问题。同时,因为是前端的Ajax请求,用户名和密码都暴露在了前端,所以,最终放弃此方案。
尝试二:
尝试一之后,我开始考虑后台调用接口/api/v1/auth/login,从而避开ajax的跨域问题。但是最终,会发现后台获取cookie,然后传递并保存在前台没有那么容易。因为,每个cookie是有作用域,通过后台获取的Kibana的cookie的作用域为,但是Web应用的作用域是,这样,后台需要处理作用域的问题,我最后也放弃了这种方案的进一步尝试。
尝试三:
后来,我使用了Nginx+htpasswd的方式,但是这种方式,最后还是无法满足要求。这种方式只是把用户的登录功能交给了Nginx,并没有解决我的核心问题。
因为,我不可能把Web应用的登录功能和Kibana的登录功能统一迁移到Nginx。
最后尝试
最后,终于找到了一个方法,可以彻底的解决我的问题。
使用Nginx代理传递Header的方式来自动获取Kibana的用户授权。
需要修改的几处配置如下:
nginx.conf
server {
listen 80;
server_name <Kibana_Server_Hostanme>;
location / {
proxy_pass http://<Kibana_Server_IP>:5600;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Authorization "Basic <username:password>";
}
error_page 404 /404.html;
location = /40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
}
}
注意:这里填写你的Kibana服务器的IP地址;
\这里是你Kibana登录用户和密码的Base64的加密字符串,例如:
如果你的Kibana登录用户和密码为:admin 123456,那么可以在Linux下通过如下命令生产对应的Base64加密字符串(注意用户和密码之间要用 : 分割)并填到配置文件对应的位置:
echo -n admin:123456 | base64
Kibana.yml
# List of Kibana client-side headers to send to Elasticsearch. To send *no* client-side
# headers, set this value to [] (an empty list).
elasticsearch.requestHeadersWhitelist: [authorization]
# Header names and values that are sent to Elasticsearch. Any custom headers cannot be overwritten
# by client-side headers, regardless of the elasticsearch.requestHeadersWhitelist configuration.
elasticsearch.customHeaders: {}
注意:在Kibana安装目录中,修改Kibana.yml,去掉如上两个配置的注释。这样配置后,Kibana才会将Nginx传递过来的Header信息传递给ElasticSearch,接着,ElasticSearch的SearchGuard才能处理用户登录授权的问题。
sg_config.yml
http:
anonymous_auth_enabled: false
xff:
enabled: true
internalProxies: '<Kibana_Server_IP>' # regex pattern
#internalProxies: '.*' # trust all internal proxies, regex pattern
remoteIpHeader: 'x-forwarded-for'
proxiesHeader: 'x-forwarded-by'
proxy_auth_domain:
http_enabled: true
transport_enabled: true
order: 0
http_authenticator:
type: proxy
challenge: false
config:
user_header: "x-proxy-user"
roles_header: "x-proxy-roles"
authentication_backend:
type: noop
注意:这个文件的主要修改涉及到上面两个部分:
internalProxies的配置,主要是把需要请求代理授权的服务器的IP加入到授权的IP地址列表中,我这里是Nginx的代理授权,中间有跳转到Kibana,然后Kibana再转跳到ElasticSearch上的SearchGuard,所以,我只需要把Kibana的服务器IP配置到这里就可以了。
第二段配置,是打开SearchGuard的代理授权的功能
proxy_auth_domain:
http_enabled: true
记得要将order设置为0,这样,系统才会优先验证代理授权
这一部分的设置,也可以参考官方文档里面的说明:https://docs.search-guard.com/latest/proxy-authentication
到此,整个从Nginx到Kibana,再到SearchGuard的代理“免密”授权的配置就算完成了,重启相应的Server后,然后通过域名打开Kibana的时候,你会发现没有登录框弹出了。
注意:当然,如果你用IP地址访问Kibana,还是会弹出登录框的,因为上述的配置,是基于Nginx做的域名代理解析。
配置示例
例如,我的用户名和密码是lifuqiang,python2019
[root@localhost ~]# echo -n lifuqiang:python2019 | base64
bGlmdXFpYW5nOnB5dGhvbjIwMTk=
然后在nginx中添加如下配置
location / {
proxy_pass http://192.168.59.67:8443;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Authorization "Basic bGlmdXFpYW5nOnB5dGhvbjIwMTk=";
}

浙公网安备 33010602011771号