This post is older than a year. Consider some information might not be accurate anymore.
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-
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;
}