Loading...

Setup AWS Elasticsearch Service

:heavy_exclamation_mark: This post is older than a year. Consider some information might not be accurate anymore. :heavy_exclamation_mark:

Running Elasticsearch Service on AWS (Amazon Web Services)

  • Elasticsearch Service is running as VPC (Virtual Private Cloud)
  • Expose service with EC2 container running nginx

Security is an onion, and good strategies have multiple layers.

Networking

Open http and https

  • inbound
  • outbound

Elastic IP

DNS: ec2-.eu-central-1.compute.amazonaws.com IP:

HTTPS everywhere

Let’s encrypt rejects ephemeral AWS instances. Create a self signed certificate. For detailed instructions.

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt

Secure it

chmod 0400 /etc/ssl/private/nginx-selfsigned.key

Certificate config

sudo vim /etc/nginx/snippets/self-signed.conf

Add this content

ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;

TLS parameters

Create a strong Diffie-Hellman group, which is used in negotiating Perfect Forward Secrecy with clients.

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
sudo vim /etc/nginx/snippets/ssl-params.conf

Add this content

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Disable preloading HSTS for now.  You can use the commented out header line that includes
# the "preload" directive if you understand the implications.
#add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

ssl_dhparam /etc/ssl/certs/dhparam.pem;

Copy default to new config file elasticsearch

root@aws:/etc/nginx/sites-available# cp default elasticsearch

elasticsearch contains rules to redirect all traffic to https

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    # redirect to https
    # setup aws dns name of elastic ip
    server_name ec2-elastic-ip.eu-central-1.compute.amazonaws.com;
    return 301 https://$server_name$request_uri;

    root /var/www/html;

    # Add index.php to the list if you are using PHP
    index index.html index.htm index.nginx-debian.html;

    server_name _;

    location / {
            # First attempt to serve request as file, then
            # as directory, then fall back to displaying a 404.
            try_files $uri $uri/ =404;
    }

}

server {
        # SSL configuration
        listen 443 ssl http2 default_server;
        listen [::]:443 ssl http2 default_server;
        include snippets/self-signed.conf;
        include snippets/ssl-params.conf;
}

test config

root@aws:~# nginx -t
nginx: [warn] "ssl_stapling" ignored, issuer certificate not found
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

rm symlink of default

root@aws:/etc/nginx/sites-available# rm ../sites-enabled/default

create symlink for elasticsearch

root@aws:/etc/nginx# cd ../sites-enabled/
root@aws:/etc/nginx/sites-enabled# ln -s /etc/nginx/sites-available/elasticsearch elasticsearch

restart nginx

Add Elasticsearch upstream (only one source, but may change in time)

upstream elasticsearch_servers {
    server vpc-elasticsearch.eu-central-1.es.amazonaws.com;
    keepalive 15;
}

server {
        # SSL configuration
        listen 443 ssl http2 default_server;
        listen [::]:443 ssl http2 default_server;

        auth_basic "Jojo's Memory - Notes and Memos";
        auth_basic_user_file /etc/nginx/.htpasswd;

        location / {
                proxy_pass http://elasticsearch_servers;
                proxy_pass_request_headers off;
                proxy_redirect off;
                proxy_http_version 1.1;
                proxy_set_header Connection "Keep-Alive";
                proxy_set_header Proxy-Connection "Keep-Alive";
                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;
                proxy_connect_timeout 5s;
                proxy_read_timeout 10s;
        }

        include snippets/self-signed.conf;
        include snippets/ssl-params.conf;
}

add basic auth file

sudo sh -c "echo -n 'cinhtau:' >> /etc/nginx/.htpasswd"
sudo sh -c "openssl passwd -apr1 >> /etc/nginx/.htpasswd"

proxy_pass_request_headers off; is important, as it would be used for auth against the vpc elasticsearch endpoint.

Expose Kibana on port 5601

server {
    # SSL configuration
    listen 5601 ssl http2 default_server;
    listen [::]:5601 ssl http2 default_server;

    auth_basic "Jojo's Memory - Notes and Memos";
    auth_basic_user_file /etc/nginx/.htpasswd;

    location / {
        proxy_set_header Host ec2-elastic-ip.eu-central-1.compute.amazonaws.com;
        proxy_set_header X-Real-IP <your elastic ip>;

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

        proxy_pass http://vpc-elasticsearch.eu-central-1.es.amazonaws.com/_plugin/kibana/;
        proxy_redirect http://vpc-elasticsearch.eu-central-1.es.amazonaws.com/_plugin/kibana/ http://<your elastic ip>/kibana/;
    }

    location ~ (/app/kibana|/app/timelion|/bundles|/es_admin|/plugins|/api|/ui|/elasticsearch) {
        proxy_pass              http://vpc-elasticsearch.eu-central-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;
        proxy_set_header Authorization "";
    }

    include snippets/self-signed.conf;
    include snippets/ssl-params.conf;
}
Please remember the terms for blog comments.