Trifork Blog

Shield your Kibana dashboards

March 5th, 2015 by
|

You work with sensitive data in Elasticsearch indices that you do not want everyone to see in their Kibana dashboards. Like a hospital with patient names. You could give each department their own Elasticsearch cluster in order to prevent all departments to see the patient’s names, for example.

But wouldn’t it be great if there was only one Elasticsearch cluster and every departments could manage their own Kibana dashboards? And still have the security in place to prevent leaking of private data?

With Elasticsearch Shield, you can create a configurable layer of security on top of your Elasticsearch cluster. In this article, we will explore a small example setup with Shield and Kibana.

In this article, we’ll use Elasticsearch 1.4.4, Shield 1.0.1 and Kibana 4.0.0. These are at the time of writing the most-recent  versions. Beginner knowledge of Elasticsearch is expected.

Suppose we want to keep our patient’s names private. An index of patients will be available only for one department. An index of cases will be available to all departments.

First, we’ll add some test data to the cluster. Create a filehospital.jsonwith the following content:

{ "index" : { "_index" : "cases", "_type" : "case", "_id" : "101" } }
{ "admission" : "2015-01-03", "discharge" : "2015-01-04", "injury" : "broken arm" }
{ "index" : { "_index" : "cases", "_type" : "case", "_id" : "102" } }
{ "admission" : "2015-01-03", "discharge" : "2015-01-06", "injury" : "broken leg" }
{ "index" : { "_index" : "cases", "_type" : "case", "_id" : "103" } }
{ "admission" : "2015-01-06", "discharge" : "2015-01-07", "injury" : "broken nose" }
{ "index" : { "_index" : "cases", "_type" : "case", "_id" : "104" } }
{ "admission" : "2015-01-07", "discharge" : "2015-01-07", "injury" : "bruised arm" }
{ "index" : { "_index" : "cases", "_type" : "case", "_id" : "105" } }
{ "admission" : "2015-01-08", "discharge" : "2015-01-10", "injury" : "broken arm" }
{ "index" : { "_index" : "patients", "_type" : "patient", "_id" : "101" } }
{ "name" : "Adam", "age" : 28 }
{ "index" : { "_index" : "patients", "_type" : "patient", "_id" : "102" } }
{ "name" : "Bob", "age" : 45 }
{ "index" : { "_index" : "patients", "_type" : "patient", "_id" : "103" } }
{ "name" : "Carol", "age" : 34 }
{ "index" : { "_index" : "patients", "_type" : "patient", "_id" : "104" } }
{ "name" : "David", "age" : 14 }
{ "index" : { "_index" : "patients", "_type" : "patient", "_id" : "105" } }
{ "name" : "Eddie", "age" : 72 }

Then bulk index these documents in the cluster:

$ curl -X POST 'http://localhost:9200/_bulk' --data-binary @./hospital.json

Without security, every user can access all documents. Let’s install Shield to add security.

Directions on how to install Shield can be found at the Elasticsearch website. We will do this step by step.

Shield is a commercial product, so first we need to install the license manager:

$ elasticsearch/bin/plugin -i elasticsearch/license/latest
-> Installing elasticsearch/license/latest...
Trying http://download.elasticsearch.org/elasticsearch/license/license-latest.zip...
Downloading .....................................DONE
Installed elasticsearch/license/latest into /home/patrick/blog/elasticsearch/plugins/license

Now install Shield itself in the same manner:

$ elasticsearch/bin/plugin -i elasticsearch/shield/latest
-> Installing elasticsearch/shield/latest...
Trying http://download.elasticsearch.org/elasticsearch/shield/shield-latest.zip...
Downloading .....................................DONE
Installed elasticsearch/shield/latest into /home/patrick/blog/elasticsearch/plugins/shield

You will need to restart the nodes of your cluster to activate the plugins.

In the logs of Elasticsearch you’ll see some messages from the new plugins:

[2015-02-12 08:18:01,347][INFO ][shield.license ] [node0] enabling license for [shield]
[2015-02-12 08:18:01,347][INFO ][license.plugin.core ] [node0] license for [shield] - valid
[2015-02-12 08:18:01,355][ERROR][shield.license ] [node0]
#
# Shield license will expire on [Saturday, March 14, 2015]. Cluster health, cluster stats and indices stats operations are
# blocked on Shield license expiration. All data operations (read and write) continue to work. If you
# have a new license, please update it. Otherwise, please reach out to your support contact.
#

Notice that you will get a 30-day trial period to experiment with Shield.
Now all our data is protected. See what happens when we try to get a document:

$ curl localhost:9200/cases/case/101?pretty=true
{
    "error" : "AuthenticationException[missing authentication token for REST request [/cases/case/1]]",
    "status" : 401
}

We need to add some roles and users to configure the role-based access control of Shield. First we define the roles and their privileges. The definition of these are found in the elasticsearch/config/shield/roles.yml file. Some roles, like admin and user are predefined:

# All cluster rights
# All operations on all indices
admin:
  cluster: all
  indices:
    '*': all

# Read-only operations on indices
user:
  indices:
    '*': read

Let’s edit this roles.yml file to describe our needs. We do not want for every user to access all indices, so we’ll change user.indices. We’ll add the two roles needed for our organization: doctor and nurse. A doctor has more privileges than a nurse. Doctors can access all indices. Nurses can only access the cases index:

# Read-only operations on indices
#user:
#  indices:
#    '*': read

# Doctors can access all indices
doctor:
  indices:
    '*': read

# Nurses can only access the cases index
nurse:
  indices:
    'cases': read

Now that the roles are defined, we can create users that have these roles. Shield provides three realms to store the users: an internal realm, LDAP or Active Directory. For now, we use the internal realm. The realm is configured in elasticsearch/config/elasticsearch.yml. If nothing is explicitly configured, the internal realm is used.
To add users the esusers command line tool can be used. Let’s create two users (both with abc123 as password), one for each role:

$ elasticsearch/bin/shield/esusers useradd alice -r nurse
$ elasticsearch/bin/shield/esusers useradd bob -r doctor

Just to check if the security works:

$ curl --user alice:abc123 localhost:9200/_count?pretty=true
{
  "count" : 5,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "failed" : 0
  }
}
$ curl --user bob:abc123 localhost:9200/_count?pretty=true
{
  "count" : 10,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "failed" : 0
  }
}

Alice can see the 5 cases in our cases index. Bob can see those 5 cases plus the 5 patients in the patients index.

Now it’s time to add Kibana in the mix. Instructions to download and install Kibana 4 can be found on the Elasticsearch website.

When we start the Kibana server we notice that Kibana is not allowed access to the Elasticsearch cluster:

$ kibana/bin/kibana
{"@timestamp":"2015-02-26T08:24:48.958Z","level":"fatal","message":"AuthenticationException[missing authentication token for REST request [/.kibana/config/_search]]","node_env":"production","error":{"message":"AuthenticationException[missing authentication token for REST request [/.kibana/config/_search]]","name":"Error","stack":"Error: AuthenticationException[missing authentication token for REST request [/.kibana/config/_search]]\n at respond (/home/patrick/kibana/src/node_modules/elasticsearch/src/lib/transport.js:235:15)\n at checkRespForFailure (/home/patrick/kibana/src/node_modules/elasticsearch/src/lib/transport.js:203:7)\n at HttpConnector. (/home/patrick/kibana/src/node_modules/elasticsearch/src/lib/connectors/http.js:156:7)\n at IncomingMessage.bound (/home/patrick/kibana/src/node_modules/elasticsearch/node_modules/lodash-node/modern/internals/baseBind.js:56:17)\n at IncomingMessage.emit (events.js:117:20)\n at _stream_readable.js:944:16\n at process._tickCallback (node.js:442:13)\n"}}

We need to tell Shield that Kibana is allowed to access our cluster. Extra information of how to let Kibana work with Shield can be found in the Elasticsearch guide.

Shield is shipped with a default configuration for Kibana 4. We find the following role definition in elasticsearch/config/shield/roles.yml.

# The required role for kibana 4 users
kibana4:
  cluster: cluster:monitor/nodes/info
  indices:
    '*':
      - indices:admin/mappings/fields/get
      - indices:admin/validate/query
      - indices:data/read/search
      - indices:data/read/msearch
      - indices:admin/get
    '.kibana':
      - indices:admin/exists
      - indices:admin/mapping/put
      - indices:admin/mappings/fields/get
      - indices:admin/refresh
      - indices:admin/validate/query
      - indices:data/read/get
      - indices:data/read/mget
      - indices:data/read/search
      - indices:data/write/delete
      - indices:data/write/index
      - indices:data/write/update

When the Kibana Server starts it needs to access the .kibana index. So we need to create a user in Shield for Kibana to connect with:

$ elasticsearch/bin/shield/esusers useradd kibana -r kibana4

This account must be configured in Kibana. Modify kibana/conf/kibana.yml:

# If your Elasticsearch is protected with basic auth, this is the user credentials
# used by the Kibana server to perform maintence on the kibana_index at statup. Your Kibana
# users will still need to authenticate with Elasticsearch (which is proxied thorugh
# the Kibana server)
kibana_elasticsearch_username: kibana
kibana_elasticsearch_password: abc123

The Kibana users must have the kibana4 role to be able to work with Kibana. They must be able to store their visualizations and dashboards in the .kibana index:

$ elasticsearch/bin/shield/esusers roles alice -a kibana4
$ elasticsearch/bin/shield/esusers roles bob -a kibana4

Since the default kibana4 role has read access on all indices, alice and bob will be granted all access on all indices. Therefore the role permissions must be modified:

# Doctors can access all indices
doctor:
  indices:
    'cases,patients':
      - indices:admin/mappings/fields/get
      - indices:admin/validate/query
      - indices:data/read/search
      - indices:data/read/msearch
      - indices:admin/get

# Nurses can only access the cases index
nurse:
  indices:
    'cases':
      - indices:admin/mappings/fields/get
      - indices:admin/validate/query
      - indices:data/read/search
      - indices:data/read/msearch
      - indices:admin/get

# The required role for kibana 4 users
kibana4:
  cluster:
      - cluster:monitor/nodes/info
      - cluster:monitor/health
  indices:
    '.kibana':
      - indices:admin/exists
      - indices:admin/mapping/put
      - indices:admin/mappings/fields/get
      - indices:admin/refresh
      - indices:admin/validate/query
      - indices:data/read/get
      - indices:data/read/mget
      - indices:data/read/search
      - indices:data/write/delete
      - indices:data/write/index
      - indices:data/write/update
      - indices:admin/create

With this configuration any user with the kibana4 role is able to use Kibana but only sees data that he or she has the proper clearance for.

We can now start the Kibana Server and see that it runs as it should:

$ kibana/bin/kibana
{"@timestamp":"2015-02-26T08:53:18.961Z","level":"info","message":"Listening on 0.0.0.0:5601","node_env":"production"}

We can open a browser and head to localhost:5601 to open the Kibana web interface. Log in as Alice:

kibana-dialog-alice

After logging in, Kibana will ask for the index pattern. We’ll keep it simple:

kibana-configure-index-pattern

Then in the discover tab you can add fields to your view. Notice that Alice only sees cases:

When we log in as Bob our discover tab shows both cases and patients:

To summarize: we added security to Elasticsearch with Shield and configured some users and roles. There’s nothing more to it!

27 Responses

  1. April 8, 2015 at 15:25 by Pat

    thanks for the tutorial. I follwed it and the original one from elasticsearch, but I don’t get authentication to work, even a test with:

    curl –user kibana:1b2HzEb662Y5 localhost:9200/_count?pretty=true

    brings:

    {
    “error” : “AuthenticationException[unable to authenticate user [kibana] for REST request [/_count?pretty=true]]”,
    “status” : 401
    }

    any idea?

    • April 30, 2015 at 13:12 by Patrick Kik

      @Pat (2015/04/08 at 15:25)
      Does the user kibana exists? You can use the esusers utility to list all the users known to the system.

  2. April 14, 2015 at 19:36 by Matheus Dias

    Great post! Quick and easy.
    Thank you!

    • April 30, 2015 at 13:13 by Patrick Kik

      @Matheus Dias (2015/04/14 at 19:36)
      Thank you!

  3. April 17, 2015 at 12:17 by prem

    I have edited the roles.yml and tried to add doctor and nurse according to the eg mentioned above. The security is not worked for me.Any help would be highly appreicated.

    ubuntu@ip-10-142-247-183:~/elkproject/elasticsearch-1.4.4/config/shield$ curl –user alice:abc123 localhost:9200/_count?pretty=true
    {
    “error” : “AuthenticationException[unable to authenticate user [alice] for REST request [/_count?pretty=true]]”,
    “status” : 401
    }

    • April 30, 2015 at 13:25 by Patrick Kik

      @prem (2015/04/17 at 12:17)
      You can use the esusers utility to list the users known to the system. You can verify that the user exists.

  4. April 17, 2015 at 18:39 by Derek

    Thank you for this post.

    I have one important question :
    Is there a way to associate a user with a query parameter that will be injected in all his searches inside of Kibana ? For example, let’s assume that one of the “doctor” users is a pedophile (ok, weird example). Can i restrict the patients that he will be able to see by injecting some kind of sub-query (age > 18) in all the reports that he will see ?

    Actually, my use case is simple (and does not involve pedophiles): my index contains all customer datas and i want my customers to log in to kibana and only see their own data. I can’t create roles for each one of them and need an automatic solution.

    • April 30, 2015 at 13:24 by Patrick Kik

      @Derek (2015/04/17 at 18:39)
      Shield does not (yet?) support security on document level. You can use filtered index aliases to some extend.

  5. May 11, 2015 at 14:16 by M

    Thanks for this post!
    I follow it but I have one question.
    How did you log out on Kibana? because I’m always log in. I have also try to restart elasticsearch and kibana but it’s the same.

  6. May 19, 2015 at 11:49 by Patrick Kik

    @M (May 11, 2015 at 14:16)
    It’s the browser that’s keeping you logged on. I’ve found that using a new private tab for every session will be very usefull for testing.

  7. May 27, 2015 at 08:10 by harvey

    I also got the question that browser keeping the logged on.
    I find a solution is close the browser which session will be clear.
    The next time you open the browser elasticsearch or kibana will ask you input shield username and password again.

  8. May 28, 2015 at 09:21 by Jan

    Did you find any way to hide visualizations/dashboards for individual roles? I would like to setup one ELK cluster for my whole company. But I do not want people from individual departments to see all the dashboards of another department (this would just confuse them). Shield is working to an extend that if not authorized your dashboards will remain empty (no data to show), but everyone will still see all the available dashboards. Any ideas?

  9. June 2, 2015 at 16:25 by Patrick Kik

    @Jan (May 28, 2015 at 09:21)
    Since Kibana stores all the definitions of the dashboards in the .kibana index, and Shield operates on a per-index bases, this will continu to be a problem.
    You could use filtered aliases on the .kibana index. But that’s tedious.

  10. June 25, 2015 at 13:58 by prem

    @Patrick Kik Apolozies for the late reply,I checked with esusers utility it has users.Here is the result
    elasticsearch/bin/shield/esusers list
    bob : doctor
    alice : nurse

    • July 6, 2015 at 08:41 by Patrick Kik

      Then I think you forgot to add the kibana user.

  11. July 1, 2015 at 11:43 by vikas

    Thanks for such a wonderful blog
    I have a question here , can’t we stop the user on the first page of Kibana ?. I mean when the user searches index in kibana to configure, it should not allow that user to fetch if he is not authorized for the index.

    • July 6, 2015 at 08:46 by Patrick Kik

      I’m not sure what you mean. Do you mean that the user is now stopped *before* the first page, instead of *on* the first page?
      That’s because Shield will prevent making connections to the cluster at all. Shield is a layer around the cluster.

  12. July 7, 2015 at 08:31 by Frank

    I can seem to be able to add users. Getting a Error: Could not find or load main class org.elasticsearch.shield.authc.esusers.tool.ESUsersTool. Tried both on my mac and ubuntu platform. Anyone have any ideas on how to solve this ??

    • July 7, 2015 at 08:55 by Patrick Kik

      Wow. I guess your installation is wrong. The Java classloader is not able to load said class.
      You can also try to ask your question at https://discuss.elastic.co/c/shield. Good luck!

      • July 7, 2015 at 09:12 by Frank

        Thanks !!

  13. July 23, 2015 at 02:28 by Carmelo

    Just a question please,
    The ‘Authentication Required’ popup login form for Kibana – when you type ‘alice’ user and password – comes from an additional reverse proxy (like nginx or apache) . Is it correct?

    Thanks

  14. July 23, 2015 at 08:01 by Patrick Kik

    Kibana 4 has a server that hosts the Kibana web front end. Queries go through that server to Elasticsearch (via Shield). I don’t know the internals of the server. You could check https://discuss.elastic.co/c/kibana.

  15. August 10, 2015 at 12:07 by Rabeet

    In your /opt/kibana4/config/kibana.yml file :

    Replace elasticsearch_url with this :

    elasticsearch_url: “http://user:pass@localhost:9200”

    Thank you

  16. September 7, 2015 at 08:55 by jerrychen

    elasticsearch:1.7.1
    license:1.0.0
    shield:1.3.2

    #esusers list
    bob : doctor
    alice : nurse
    adm : admin

    #curl -u adm:abc123 -XGET ‘http://XXX:9200/_nodes/process?pretty’
    {
    “error” : “AuthenticationException[unable to authenticate user [adm] for REST request [/_nodes/process?pretty]]”,
    “status” : 401
    }

    any idea?

    • September 7, 2015 at 11:50 by Patrick Kik

      I failed to reproduce your error. Some checks you can do:
      – reset the password of user adm;
      – are you running multiple nodes? Does every node have the same roles/user config?
      – is the role admin defined in roles.yml?

  17. December 12, 2015 at 08:46 by prem

    It’s very stange to see this scenarion,
    Environment Elasticsearch 2.0 and kibana 4.2 Shield version 2.0
    I have created the users and roles but If I run the elasticsearch I can see the following warning
    [2015-12-12 02:39:08,936][INFO ][node ] [Asbestos Man] starting …
    [2015-12-12 02:39:10,288][WARN ][shield.authc.esusers ] [Asbestos Man] no users found in users file [/home/ec2-user/elasticsearch-2.0.0/config/shield/users]. use bin/shield/esusers to add users and role mappings
    [2015-12-12 02:39:10,298][WARN ][shield.authc.esusers ] [Asbestos Man] no entries found in users_roles file [/home/ubuntu-user

    [ubuntu-user@ec2-22-09-21-322 elasticsearch-2.0.0]$

    Here my userlist which I had created
    bin/shield/esusers list
    demo : kibana4
    webshop : kibana4
    user1 : tab014
    kibana : kibana4

    I’m seeing Elasticsearch authentication exception in kibana url?