Skip to main content

Securing Elasticsearch with ReadOnlyREST

Jomsom, Nepal

Securing Elasticsearch with ReadonlyREST

Neither Elasticsearch nor Kibana offer a user authentication. In earlier Projects we circumvented this issue by blocking all access - only allowing our Website and Kibana to access the database via localhost.

But now we need an anonymous user account that is only allowed to Request and Read search results - while Writing to the database is forbidden.

Elastic offer their own solution for it called X-Pack (On how to set it up - read more) - which is a premium extension to the ELK stack and nobody seems to know how much it would cost to buy it. But as the wise man from the vintage sport car dealership knows - if you have to ask for the prize, you cannot afford it anyway. So are there free solutions out there?

Yes! Searching for alternatives lead me to 2 solutions that are mentioned often - there are more if you keep searching:

  1. ReadOnlyREST
  2. SearchGuard

Today we are going to set up the first of them. The first thing I noticed is, that those plugins are written for the exact Version number of Elasticsearch. The newest version of RestOnlyREST supports Elasticsearch Version 6.2.3 - I am using 6.2.4, which unfortunately means that I have to downgrade my ES version.... and since there is no downgrade option with ES, I have to shut off the service and go in manually to delete every folder that ES has generated on my CentOS server (really ? That is the only option that I could find online.. but it is really a mess...).

Install Elasticsearch

I. Download and install the public signing key

 rpm --import https://packages.elastic.co/GPG-KEY-elasticsearch

II. Add the following in your /etc/yum.repos.d/ directory in a file with a .repo suffix, for example elasticsearch.repo

[elasticsearch-6.x]
name=Elasticsearch repository for 6.x packages
baseurl=https://artifacts.elastic.co/packages/6.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md

III. Install a specific version of Elasticsearch

ReadOnlyREST requires us to install a specific version (6.2.3) of Elasticsearch. Let's check what versions are available to install (CentOS/yum):

yum --showduplicates list elasticsearch | expand
Installed Packages
elasticsearch.noarch 6.2.4-1 @elasticsearch-6.x
Available Packages
elasticsearch.noarch 6.0.0-1 elasticsearch-6.x
elasticsearch.noarch 6.0.0-1 kibana-6.x
elasticsearch.noarch 6.0.1-1 elasticsearch-6.x
elasticsearch.noarch 6.0.1-1 kibana-6.x
elasticsearch.noarch 6.1.0-1 elasticsearch-6.x
elasticsearch.noarch 6.1.0-1 kibana-6.x
elasticsearch.noarch 6.1.1-1 elasticsearch-6.x
elasticsearch.noarch 6.1.1-1 kibana-6.x
elasticsearch.noarch 6.1.2-1 elasticsearch-6.x
elasticsearch.noarch 6.1.2-1 kibana-6.x
elasticsearch.noarch 6.1.3-1 elasticsearch-6.x
elasticsearch.noarch 6.1.3-1 kibana-6.x
elasticsearch.noarch 6.1.4-1 elasticsearch-6.x
elasticsearch.noarch 6.1.4-1 kibana-6.x
elasticsearch.noarch 6.2.0-1 elasticsearch-6.x
elasticsearch.noarch 6.2.0-1 kibana-6.x
elasticsearch.noarch 6.2.1-1 elasticsearch-6.x
elasticsearch.noarch 6.2.1-1 kibana-6.x
elasticsearch.noarch 6.2.2-1 elasticsearch-6.x
elasticsearch.noarch 6.2.2-1 kibana-6.x
elasticsearch.noarch 6.2.3-1 elasticsearch-6.x
elasticsearch.noarch 6.2.3-1 kibana-6.x
elasticsearch.noarch 6.2.4-1 elasticsearch-6.x
elasticsearch.noarch 6.2.4-1 kibana-6.x

To install the version 6.2.3 of elasticsearch type:

yum install elasticsearch-6.2.3-1

Here I ran into issues due to the messy uninstall of the earlier (newer) version of Elasticsearch - if someone knows a cleaner way to do this, please tell :)

Yum still had the older version in its DB leading to an 'package already installed. Checking for update. Nothing to do' error. This can be fixed by:

rpm -e --justdb --nodeps elasticsearch
rpm -e --justdb --nodeps kibana

Now re-run the install command above:

yum install elasticsearch-6.2.3-1
Dependencies Resolved

====================================================================================================
Package Arch Version Repository Size
====================================================================================================
Installing:
elasticsearch noarch 6.2.3-1 elasticsearch-6.x 28 M

Transaction Summary
====================================================================================================
Install 1 Package

Total download size: 28 M
Installed size: 31 M
Is this ok [y/d/N]:y

IV. Restrict access to your Elasticsearch instance

To configure Elasticsearch open the following file inside your text editor: /etc/elasticsearch/elasticsearch.yml. We want to limit access to localhost and a public domain that we are going to configure in NGINX. This can be done with the variable network.host:

# ---------------------------------- Network -----------------------------------
#
# Set the bind address to a specific IP (IPv4 or IPv6):
#
network.host: 127.0.0.1, my.domain.com
#
# Set a custom port for HTTP:
#
http.port: 9200

The HTTP port 9200 is the default port and should be changed - but we are only going to use it on localhost. NGINX will take care of it on the outside - so we will just leave it at it's default value. The webserver will also add a security layer to our app - which means, we will need to enable CORS header for the transaction. Add the following lines below the Network Block:

# --------------------------------- CORS ----------------------------------
#
#
#http.cors:
# enabled: true
# allow-origin: /https?:\/\/my.domain.com(:[0-9]+)?/
http.cors:
enabled: true
allow-origin: /https?:\/\/my.domain.com(:[0-9][0-9][0-9][0-9])?/

Both examples above allow Cross-Origin Resource Sharing for your domain on every available port - but for some reasons the first regular expression stopped to work in Elasticsearch 6.2.x. You just need one of them.

V. Set up the Elasticsearch Service

To configure Elasticsearch to start automatically when the system boots up, run the following commands:

sudo /bin/systemctl daemon-reload
sudo /bin/systemctl enable elasticsearch.service

Elasticsearch can be started and stopped as follows:

sudo systemctl start elasticsearch.service
sudo systemctl stop elasticsearch.service

Install Kibana

Since we installed a specific version (6.2.3) of Elasticsearch we now need to install the same version of the admin panel Kibana. First Create and edit a new yum repository file for Kibana in /etc/yum.repos.d/kibana.repo:

[kibana-6.x]
name=Kibana repository for 6.x packages
baseurl=https://artifacts.elastic.co/packages/6.x/yum
gpgcheck=1
gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch
enabled=1
autorefresh=1
type=rpm-md

Then install the correct version as listed earlier:

yum install kibana-6.2.3-1

Now set the Elasticsearch Connection URL for Kibana in /etc/kibana/kibana.yml:

elasticsearch.url: 'http://localhost:9200'

To configure Kibana to start automatically when the system boots up, run the following commands:

sudo /bin/systemctl daemon-reload
sudo /bin/systemctl enable kibana.service

Kibana can be started and stopped as follows:

sudo systemctl start kibana.service
sudo systemctl stop kibana.service

Secure Elasticsearch

Now we can install RestOnlyREST to secure the database. First download the correct package for the installed version of Elasticsearch and place it inside the ./tmp directory.

First set up the configuration file in /etc/elasticsearch/readonlyrest.yml to allow all access from localhost (required by Kibana) and restrict outside access to specific indices to read only:

readonlyrest:
#optional
response_if_req_forbidden: Sorry, your request is forbidden.

access_control_rules:

- name: Accept all requests from localhost
hosts: [127.0.0.1]

- name: Just certain indices, and read only
actions: ['indices:data/read/*']
indices: ['all_my_public_indices_start_with*'] # index aliases are taken in account!

Then install the plugin to the elasticsearch plugin directory:

cd /usr/share/elasticsearch/bin
./elasticsearch-plugin install file:///tmp/readonlyrest-1.16.18_es6.2.3.zip

-> Downloading file:///tmp/readonlyrest-1.16.18_es6.2.3.zip
[=================================================] 100%  
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: plugin requires additional permissions @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
* java.io.FilePermission << ALL FILES >> read
* java.lang.RuntimePermission accessDeclaredMembers
* java.lang.RuntimePermission getClassLoader
* java.lang.reflect.ReflectPermission suppressAccessChecks
* java.net.SocketPermission * connect,accept,resolve
* java.security.SecurityPermission getProperty.ssl.KeyManagerFactory.algorithm
* java.util.PropertyPermission * read,write
See http://docs.oracle.com/javase/8/docs/technotes/guides/security/permissions.html
for descriptions of what these permissions allow and the associated risks.

Continue with installation? [y/N]y
-> Installed readonlyrest

Disable X-Pack security module

(applies to ES 6.4.0 or greater)

ReadonlyREST and X-Pack security module can't run together, so the latter needs to be disabled.

Edit elasticsearch.yml and append xpack.security.enabled: false:

$ES_HOME/conf/elasticsearch.yml

Upgrading the plugin

To upgrade ReadonlyREST for Elasticsearch:

  1. Stop Elasticsearch. Either kill the process manually, or use:
service stop elasticsearch

depending on your environment.

  1. Uninstall ReadonlyREST
bin/elasticsearch-plugin remove readonlyrest
  1. Install the new version of ReadonlyREST into Elasticsearch.
bin/elasticsearch-plugin install file://<download_dir>/readonlyrest-<ROR_VERSION>_es<ES_VERSION>.zip

e.g. bin/elasticsearch-plugin install file:///tmp/readonlyrest-1.16.15_es6.1.1.zip

  1. Restart Elasticsearch.
service start elasticsearch

Securing Kibana

Remember to secure Kibana with NGINX, since it is not protected by the free version of ReadOnlyREST!