Kibana5.0.0に、認証、認可を実装する
概要
Kibanaを管理者以外の誰かに使わせる場合、そのユーザを認証し、閲覧できるインデックスを限定したいことがある。
Shieldという有償プラグインで認証、認可が可能らしいが、お金をかけずに実現したかった。
今回は、OpenRestyを使い、認証、認可を付け加えた。
環境
OS
- Ubuntu 16.04
Kibana5.0.0
- この記事では、192.168.0.2で動作する。
NginxとKibanaは同一のサーバ内で動作している。
Kibanaへの直アクセス禁止
KibanaのURLへ直接アクセスされると、認証、認可が適用されないので、外部から5601へのアクセスを閉じておく。
ただし、リバースプロキシ経由のアクセスは許可する。
# iptables -A INPUT -i lo -j ACCEPT # iptables -A OUTPUT -o lo -j ACCEPT # iptables -A INPUT -p tcp --dport 5601 -j REJECT
OpenRestyのセットアップ
良さげなGistがあったので、参考にした。
Easy install openresty (used and tested on Ubuntu 14.04, 15.10 and 16.04) · GitHub
最新版は、本家から持ってくる。
認証
KibanaへのNginxのリバースプロキシ設定は、記事で書いたので貼っておく。
認証は、Basic認証をつけてるだけ。
手順
必要なモジュールを入手する。
# apt install apache2-utils
ユーザにパスワードを発行する。とりあえず、sales、support、techユーザにした。
# htpasswd -c -b /etc/nginx/.htpasswd sales salespasswd # htpasswd -b /etc/nginx/.htpasswd support supportpasswd # htpasswd -b /etc/nginx/.htpasswd tech techpasswd # cat /etc/nginx/.htpasswd sales:$apr1$BMU.bsHb$c/jXRc1T3.keiYTtmdtua/ support:$apr1$Yvlq26fj$vtrYnqrc/XW/2WSRG6vlN. tech:$apr1$Zqt0uiD3$xWO72SD10EFYB4Fq.JEw.1
locationディレクティブに、auth_basicとauth_basic_user_fileを追加して、nginxを再起動する。
(snip) location ~ (/app/kibana|/bundles/|/status|/elasticsearch|/plugins|/timelion|/console|/api/) { auth_basic "Restricted"; auth_basic_user_file "/etc/nginx/.htpasswd"; proxy_pass http://192.168.0.2:5601; 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 X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $http_host; } (snip)
認可
インデックスsales-* 、support-* 、tech-*がある場合に、ユーザは関連するインデックスしか閲覧できないようにしたい。
例えば、ユーザsalesは、インデックスsales-*を閲覧できるが、インデックスsupport-* 、tech-* は閲覧できないようにする。
手順
Luaで書いたサンプルを示す。
Kibanaが、Elasticsearchに、インデックスを要求する際、HTTPリクエストのボディ部分に、インデックス名を含む。
それを利用して、アクセス拒否するようにした。
no_allow_indexesに、ユーザ名とアクセス制限するインデックスを記述する。
ngx.var.remote_userで、認証されたユーザを取得できる。
-- /etc/nginx/custom/kibana_simple_acl.lua local no_allow_indexes = { sales = { "support-*", "tech-*" }, support = { "tech-*", "sales-*" }, tech = { "sales-*", "support-*" } } local user_ = ngx.var.remote_user if user_ == nil then ngx.header.content_type = "text/plain" ngx.log(ngx.STDERR, "no user.") ngx.status(403) ngx.say("403 Forbidden: You do not have access to this page.") return ngx.exit(403) end user_check = false for user, indexes in pairs(no_allow_indexes) do local p = string.match(user, user_) ngx.log(ngx.STDERR, string.format("user: %s, user_: %s", user, user_)) if p then user_check = true ngx.req.read_body() local body_data = ngx.req.get_body_data() if body_data == nil then return end for _, index in pairs(indexes) do local matcher = ngx.re.match(body_data, index) if matcher then ngx.log(ngx.STDERR, string.format("User does not have access to %s", index)) return ngx.exit(403) end end end end if not user_check then ngx.header.content_type = "text/plain" ngx.log(ngx.STDERR, string.format("invalid user: %s", user_)) ngx.status = 403 ngx.say("403 Forbidden: You do not have access to this page.") return ngx.exit(403) end
locationディレクティブに、access_by_lua_fileを追加して、再起動する。
(snip) location ~ (/app/kibana|/bundles/|/status|/elasticsearch|/plugins|/timelion|/console|/api/) { auth_basic "Restricted"; auth_basic_user_file "/etc/nginx/.htpasswd"; access_by_lua_file /etc/nginx/custom/kibana_simple_acl.lua; proxy_pass http://192.168.0.2:5601; 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 X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Host $http_host; } (snip)
認証されたユーザが認可されてないインデックスを含むDiscoverやDashBoardが閲覧できないことを確認する。