/ Elasticsearch

AWS: Access Kibana 5 behind ELB via Nginx Reverse Proxy on Custom DNS

Update:

In one of my previous posts: Secure Access to Kibana on AWS Elasticsearch Service, I walked you through on how to setup Basic HTTP Authentication to secure your Kibana UI.

What are we doing today?

In this post, we will setup 2 Nginx Reverse Proxy Instances which is hosted on EC2, which sits behind an ELB (Elastic Load Balancer), to access Kibana5.

Note: This is a great blopost by logz.io on the differences and improvements on Kibana5

In other words:

Our Kibana-Users will hit the ELB, which translates to the 2 EC2 instances, which then Proxy their connections through to the Kibana endpoint of our Elasticsearch Domain.

We will also setup DNS via Route53, so that we can access Kibana on kibana.mydomain.com

Assumptions made:

I will assume that you already have the following:

Our Environment:

Domain: 
* kibana.mydomain.com

ELB: 
* kibana-elb.eu-west-1.elb.amazonaws.com

ELB Backend-Instances:
 * nginx1 [52.10.20.30]
 * nginx2 [52.40.50.60] 

Route53: 
* Alias Record kibana.mydomain.com -> ELB: kibana-elb

ES Domain: 
* search-aws-es.eu-west-1.es.amazonaws.com

Lets get started with our Setup.

Access Policies on Elasticsearch:

We would like to authorize only connections coming from our Nginx Instances, therefore we should allow the 2 mentioned IP Addresses, the config should look more or less like the following:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "AWS": "*"
      },
      "Action": "es:*",
      "Resource": "arn:aws:es:eu-west-1:123456789012:domain/search-aws-es/*",
      "Condition": {
        "IpAddress": {
          "aws:SourceIp": [
            "52.10.20.30",
            "52.40.50.60"
          ]
        }
      }
    }
  ]
}

Nginx Config:

Now we should configure our Nginx Configuration. This config will be applied on both instances, the only thing that will differ, would be the Public IP of the Nginx Instances.

To get the Public IP for each instance, simply run the following, once logged into the instance:

$ curl ip.ruanbekker.com
<returned-public-ip>

Backup nginx config:

$ sudo mv /etc/nginx/nginx.conf{,.bak}

Create a simple HTML Page for ELB Health Checks:

$ sudo mkdir /usr/share/nginx/html/status
$ sudo echo -e "<html>\nOK\n</html>" > /usr/share/nginx/html/status/index.html

Apply the following config:

worker_processes auto;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;

include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;
    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    include /etc/nginx/conf.d/*.conf;

    server {
      listen 80 default_server;
      listen [::]:80 default_server ipv6only=on;
      server_name kibana.mydomain.com;

      # for elb health checks
      location /status {
        root /usr/share/nginx/html/ ;
      }

      location / {
        proxy_set_header Host search-aws-es.eu-west-1.es.amazonaws.com;
        proxy_set_header X-Real-IP <public-ip-for-instance>;

        proxy_http_version 1.1;
        proxy_set_header Connection "Keep-Alive";
        proxy_set_header Proxy-Connection "Keep-Alive";
        proxy_set_header Authorization "";

        proxy_pass https://search-aws-es.eu-west-1.es.amazonaws.com/_plugin/kibana/;
        proxy_redirect https://search-aws-es.eu-west-1.es.amazonaws.com/_plugin/kibana/ http://<public-ip-for-instance>/kibana/;
      }

      location ~ (/app/kibana|/app/timelion|/bundles|/es_admin|/plugins|/api|/ui|/elasticsearch) {
         proxy_pass              http://search-aws-es.eu-west-1.es.amazonaws.com;
         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;
    }
  }
}

Restart the Nginx Server:

$ sudo /etc/init.d/nginx restart

Now, you should be able to access Kibana on kibana.mydomain.com