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,这样,系统才会优先验证代理授权

这一部分的设置,也可以参考官方文档里面的说明:

到此,整个从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=";
        }

  

 

 

 

 

 

 

posted @ 2023-04-21 15:45  羊脂玉净瓶  阅读(778)  评论(0)    收藏  举报