Setting Up Basic Authentication with Elasticsearch

I've been working with elasticsearch a lot lately and have been really enjoying it. It has an awesome api and so many great built in tools. They make building complex search logic really enjoyable and the documentation is amazing. One of the downsides of using elasticsearch is they don't have any built in authentication. One way of handling this is to setup firewall rules or ufw rules (assuming you are running ubuntu) but this may not help if you want to access your elasticsearch server from the web. My current project is built in a fairly simple environment and I wanted to build authentication on top elasticsearch instead of via firewall rules. Since I want to access elasticsearch via the web I decided to setup authentication using Nginx.

Nginx Proxy

To try and keep things simple, I set up Nginx to act as a proxy for elasticsearch. I'm usig Nginx as the autentication server for elasticsearch. Inorder to keep things as secure as I possibly can, I've set up Nginx to run on port 443 and am running it over SSL. I've configured Nginx to forward all incoming requests on port 80 to port 443. If you are running elasticsearch on the same server as another process (I would advise against this) you can setup Nginx to listen on another port.

Below is my Nginx configuration that listens to incoming requests on port 443, forwards traffic from port 80 to 443, turns on ssl and sets up the proxy pass through. The configurion below is taken from my custom Ansible deployment templates. You should replace all text wrapped with {{ }} to a value that makes sense for your project.

server {
    listen      80;
    server_name {{ your_search_domain }};
    rewrite     ^ https://$server_name$request_uri? permanent;
server {
    listen 443;
    server_name {{ your_search_domain }};
    ssl on;
    ssl_certificate     {{ ssl_dir }}/elasticsearch.crt;
    ssl_certificate_key {{ ssl_dir }}/elasticsearch.key;
    access_log {{ nginx_log_file }};
    error_log {{ nginx_error_file }};
    location / {
        rewrite ^/(.*) /$1 break;
        proxy_ignore_client_abort on;
        proxy_pass http://localhost:9200;
        proxy_redirect http://localhost:9200 http://{{ your_search_domain }}/;
        proxy_set_header  X-Real-IP  $remote_addr;
        proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header  Host $http_host;
        auth_basic "Search Authentication";
        auth_basic_user_file {{ nginx_htcontrol }};

The interesting part is in the location section of the configuration. This is where we are configuring the proxy to forward all traffic to our elasticsearch server. Most of the settings are pretty straight forward. Using the proxy module we tell nginx to pass all traffic to the Elasticsearch server as long as the authentication is valid.

The last part of the configuration is setting up authentication using the http auth basic module to prompt us with a dialog before allowing access to Elasticsearch. The auth_basic directive enables validation of a user name and password using the HTTP Basic Authentication protocol. The auth_basic_user_file is the location of the file that we are going to use for our basic authentication. The file should be formated like so:

# Your Comment

Once you have finalized your configuration you will need to restart nginx.

$ sudo /etc/init.d/nginx reload
* Reloading nginx configuration...

Now when you try to access your elasticsearch site you should get a browser prompt asking you for your username and password. Enter the details from the auth_basic_user_file and you should be forwarded to your elasticsearch instance.

This is a little extra infrastructure over head but it allows us to secure our Elasticsearch server. This helps us keep control over our search server and will help prevent unauthorized queries from being run against our search engine.