SSL And Password Protection for Kibana
Kibana is a front-end to Logstash, a log collection server. By default, Kibana is configured without support for logins and without support for SSL. This is a fast-paced explanation of how I tried to get Kibana reasonably secure.
To begin, I have a Logstash server up and running on an Ubuntu 13.10 server. It has been collecting logs for a while. What I want to do is add Kibana as a front-end. But I want Kibana to be password-protected and served over SSL. And more importantly, I don't want the Logstash server (listening on port 9200) to be accessible directly without both SSL and password protection.
The latest version of Kibana is a browser-based app. It uses JSONP to directly query the Logstash Elasticsearch server (the one on port 9200). While I like the idea, securing this is a high priority for me.
To tighten up the security, I decided on this strategy: Use nginx as an HTTP server for Kibana's files, and also as a proxy for traffic to Elasticsearch. Fortunately for me, this is not the first time anyone's tried this. In fact, the Kibana GitHub repo has some good resources for this configuration.
Here's what I did, in abbreviated form:
- Install
nginx
as a web server (On Ubuntu, this was justsudo apt-get install nginx
) - Load my SSL certificates onto the server, putting them in
/etc/nginx/
- Install the
apache2-util
package to gethtpasswd
- Create a password file in
/etc/nginx/conf.d/kibana.htpasswd
usinghtpasswd -c ...
- Grab the latest copy of Kibana and unzip it into
/home/logstash/kibana
. While Kibana comes built-in with the latest (1.3.3) Logstash JAR file, I have found it easier to work with a stand-alone Kibana codebase. - Edit
/home/logstash/kibana/config.js
and change theelasticsearch:
line toelasticsearch: "https://"+window.location.hostname,
- Modify the
/etc/nginx/sites-available/default
file based on this example from Kibana, making sure to add password protection to all of thelocation
sections. - Start the server
My firewall only allows traffic onto this server for HTTPS (port 443). Since nginx
is proxying traffic locally to port 9200, I don't have to expose that port at all.
My final default
nginx config file looked like this:
server {
listen *:443;
ssl on;
ssl_certificate cert.pem;
ssl_certificate_key cert.key;
ssl_session_timeout 5m;
ssl_protocols SSLv3 TLSv1;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
ssl_prefer_server_ciphers on;
server_name kibana;
access_log /var/log/nginx/kibana.access.log;
index index.html index.htm;
location / {
root /home/logstash/kibana;
index index.html index.htm;
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/conf.d/kibana.htpasswd;
}
location ~ ^/_aliases$ {
proxy_pass http://127.0.0.1:9200;
proxy_read_timeout 90;
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/conf.d/kibana.htpasswd;
}
location ~ ^/.*/_aliases$ {
proxy_pass http://127.0.0.1:9200;
proxy_read_timeout 90;
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/conf.d/kibana.htpasswd;
}
location ~ ^/_nodes$ {
proxy_pass http://127.0.0.1:9200;
proxy_read_timeout 90;
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/conf.d/kibana.htpasswd;
}
location ~ ^/.*/_search$ {
proxy_pass http://127.0.0.1:9200;
proxy_read_timeout 90;
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/conf.d/kibana.htpasswd;
}
location ~ ^/.*/_mapping {
proxy_pass http://127.0.0.1:9200;
proxy_read_timeout 90;
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/conf.d/kibana.htpasswd;
}
location ~ ^/kibana-int/dashboard/.*$ {
proxy_pass http://127.0.0.1:9200;
proxy_read_timeout 90;
limit_except GET {
proxy_pass http://127.0.0.1:9200;
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/conf.d/kibana.htpasswd;
}
}
location ~ ^/kibana-int/temp.*$ {
proxy_pass http://127.0.0.1:9200;
proxy_read_timeout 90;
limit_except GET {
proxy_pass http://127.0.0.1:9200;
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/conf.d/kibana.htpasswd;
}
}
}
There may be some routes to simplifying all of those location
sections, but I haven't gotten to that yet.