Search
Close this search box.

Token Based Authentication Using API Keys to access Elasticsearch – part 2, more options

Access ELK With api keys

Table of Contents

1. Introduction

In the first part I show you basic functionality of API Keys. Now I want to elaborate a little more especially about role descriptors.

2. Start Elasticsearch

Start Elasticsearch cluster with trial license needed for field and document level security then setup password to continue next steps.

				
					docker run --rm \
--name elk \
-d \
-p 9200:9200 \
-e xpack.license.self_generated.type=trial \
docker.elastic.co/elasticsearch/elasticsearch:8.10.4

# set exaple password 123456 :)

docker exec -it elk bash -c "(mkfifo pipe1); ( (elasticsearch-reset-password -u elastic -i < pipe1) & ( echo $'y\n123456\n123456' > pipe1) );sleep 5;rm pipe1"

				
			

2.1 Load test data

To be able to follow later commands load sample records

				
					curl -k -XPOST -u elastic:123456 "https://localhost:9200/documents/_doc" -H 'Content-Type: application/json' -d'
{
    "country": "China",
    "data": "*********"
}'

curl -k -XPOST -u elastic:123456 "https://localhost:9200/documents/_doc" -H 'Content-Type: application/json' -d'
{
    "country": "USA",
    "data": "*********"
}'

curl -k -XPOST -u elastic:123456 "https://localhost:9200/documents/_doc" -H 'Content-Type: application/json' -d'
{
    "country": "Russia",
    "data": "*********"
}'
				
			

3. Request body structure – Create Key

Body elements of JSON message sent with request contain

  • name – obligatory field that is minimum to create API Key
  • expiration – time definition in seconds, minutes, hours etc
  • metadata – custom metadata to attach to API Key
  • role_descriptors – permissions definition, allow restrict user more

You can specify limitation as role descriptor to allow user to find only particular document. Imagine you are asked by user to have a view over China documents in database that contain documents specific for other countries too. Now you can give API Key with limitation that will allow person to see only specific documents. This feature require license for Elasticsearch.

 

				
					curl -k -u elastic:123456 -XPUT "https://localhost:9200/_security/api_key" -H 'content-type: application/json' -d'
{
  "name": "china-docs",
  "expiration": "1h",   
  "role_descriptors": { 
    "china": {
      "indices": [
        {
          "names": ["documents"],
          "privileges": ["read"],
          "query": "{\"match\":{\"country\": {\"query\": \"China\"}}}"
        }
      ]
    }
  },
  "metadata": {
    "intention": "Only to view China docs"
  }
}
'

# response
# {
#     "id": "3wOakosB5nUlv0OITHaT",
#     "name": "china-docs",
#     "expiration": 1698975267604,
#     "api_key": "DnqLG4FOR0qKD86MX1liWQ",
#     "encoded": "M3dPYWtvc0I1blVsdjBPSVRIYVQ6RG5xTEc0Rk9SMHFLRDg2TVgxbGlXUQ=="
# }
				
			

Now someone has 1 hour to search for documents matching query where country is equal to China

				
					curl -k -H "Authorization: ApiKey M3dPYWtvc0I1blVsdjBPSVRIYVQ6RG5xTEc0Rk9SMHFLRDg2TVgxbGlXUQ==" "https://localhost:9200/_search?pretty"

# response
# {
#   "took" : 1,
#   "timed_out" : false,
#   "_shards" : {
#     "total" : 1,
#     "successful" : 1,
#     "skipped" : 0,
#     "failed" : 0
#   },
#   "hits" : {
#     "total" : {
#       "value" : 1,
#       "relation" : "eq"
#     },
#     "max_score" : 1.0,
#     "hits" : [
#       {
#         "_index" : "documents",
#         "_id" : "2AOQkosB5nUlv0OIoHYf",
#         "_score" : 1.0,
#         "_source" : {
#           "country" : "China",
#           "data" : "*********"
#         }
#       }
#     ]
#   }
# }
				
			

Another example can be if you want user to only check health status of cluster. Therefore define below descriptor

				
					curl -k -u elastic:123456 -XPUT "https://localhost:9200/_security/api_key" -H 'content-type: application/json' -d'
{
  "name": "healthcheck",
  "role_descriptors": { 
    "for-monitoring": {
      "cluster": [
          "monitor"
            ]
    }
  },
  "metadata": {
    "intention": "Only to view cluster health"
  }
}
'
# response
# {"id":"5QOkkosB5nUlv0OIfHai","name":"healthcheck","api_key":"v-Gy-jmgSoGY82vlNBBNiQ","encoded":"NVFPa2tvc0I1blVsdjBPSWZIYWk6di1HeS1qbWdTb0dZODJ2bE5CQk5pUQ=="}
				
			
				
					curl -k -H "Authorization: ApiKey NVFPa2tvc0I1blVsdjBPSWZIYWk6di1HeS1qbWdTb0dZODJ2bE5CQk5pUQ==" "https://localhost:9200/_cluster/health?pretty"

# response
# {
#   "cluster_name" : "docker-cluster",
#   "status" : "yellow",
#   "timed_out" : false,
#   "number_of_nodes" : 1,
#   "number_of_data_nodes" : 1,
#   "active_primary_shards" : 2,
#   "active_shards" : 2,
#   "relocating_shards" : 0,
#   "initializing_shards" : 0,
#   "unassigned_shards" : 1,
#   "delayed_unassigned_shards" : 0,
#   "number_of_pending_tasks" : 0,
#   "number_of_in_flight_fetch" : 0,
#   "task_max_waiting_in_queue_millis" : 0,
#   "active_shards_percent_as_number" : 66.66666666666666
# }
				
			

4. Update API Key

You can update created before API Key before it getting expired.

				
					curl -k -u elastic:123456 -XPUT "https://localhost:9200/_security/api_key" -H 'content-type: application/json' -d'
{
  "name": "short",
  "expiration": "20s"
}'
				
			

In response you are getting id(not api_key), that you will use for update queries.

				
					{
    "id": "DciLkYsBO9UU75Sr77um",
    "name": "short",
    "expiration": 1698953969095,
    "api_key": "3oxaXqfUQF6wmhvx8Ro0wA",
    "encoded": "RGNpTGtZc0JPOVVVNzVTcjc3dW06M294YVhxZlVRRjZ3bWh2eDhSbzB3QQ=="
}
				
			

curl to update API Key metadata

				
					curl -k -u elastic:123456 -XPUT "https://localhost:9200/_security/api_key/DciLkYsBO9UU75Sr77um" -H 'content-type: application/json' -d'
{
  "metadata": {
    "toughcoding": {
       "presenter": "tomd"
    }
}
}'
				
			

response:

				
					{"updated":true}
				
			

If you run query after API Key is expired you will see an error:

				
					{
    "error": {
        "root_cause": [
            {
                "type": "illegal_argument_exception",
                "reason": "cannot update expired API key [DciLkYsBO9UU75Sr77um]"
            }
        ],
        "type": "illegal_argument_exception",
        "reason": "cannot update expired API key [DciLkYsBO9UU75Sr77um]"
    },
    "status": 400
}
				
			

5. Get information about key

It is possible to get information about expired key

				
					curl -k -u elastic:123456 -XGET "https://localhost:9200/_security/api_key?id=DciLkYsBO9UU75Sr77um"

				
			
				
					{
    "api_keys": [
        {
            "id": "DciLkYsBO9UU75Sr77um",
            "name": "short",
            "type": "rest",
            "creation": 1698953949095,
            "expiration": 1698953969095,
            "invalidated": false,
            "username": "elastic",
            "realm": "reserved",
            "metadata": {
                "toughcoding": {
                    "presenter": "tomd"
                }
            },
            "role_descriptors": {}
        }
    ]
}
				
			

Also about all keys if no parameter provided

				
					curl -k -u elastic:123456 -XGET "https://localhost:9200/_security/api_key"
				
			

6. DELETE key

Deleting key will invalidate it

				
					curl -k -u elastic:123456 -XDELETE "https://localhost:9200/_security/api_key" -H 'content-type: application/json' -d'
{
"ids" : ["DciLkYsBO9UU75Sr77um"]
}'
				
			
				
					curl -k -u elastic:123456 -XGET "https://localhost:9200/_security/api_key?id=DciLkYsBO9UU75Sr77um&pretty"
{
  "api_keys" : [
    {
      "id" : "DciLkYsBO9UU75Sr77um",
      "name" : "short",
      "type" : "rest",
      "creation" : 1698953949095,
      "expiration" : 1698953969095,
      "invalidated" : true,
      "username" : "elastic",
      "realm" : "reserved",
      "metadata" : {
        "toughcoding" : {
          "presenter" : "tomd"
        }
      },
      "role_descriptors" : { }
    }
  ]
}
				
			

If you want to invalidate all keys owned by currently authenticated user you can run

				
					curl -k -u elastic:123456 -XDELETE "https://localhost:9200/_security/api_key" -H 'content-type: application/json' -d'
{
"owner" : "true"
}'

# response 
# {
#     "invalidated_api_keys": [
#         "Bch_kYsBO9UU75Sr0btY",
#         "C8iLkYsBO9UU75SrOLtU",
#         "Ach9kYsBO9UU75Sr3rtU",
#         "A8h-kYsBO9UU75Sr9Lu3",
#         "_ch4kYsBO9UU75Sr0brt",
#         "_8h8kYsBO9UU75Sr4boW",
#         "B8iBkYsBO9UU75SrHrsp",
#         "CciBkYsBO9UU75SroLvS"
#     ],
#     "previously_invalidated_api_keys": [],
#     "error_count": 0
# }
				
			

Now checking active keys will return empty list

				
					curl -k -u elastic:123456 -XGET "https://localhost:9200/_security/api_key?active_only=true&pretty"

# response:
# {
#   "api_keys" : [ ]
# }

				
			

7. Summary

After these exercises you have practiced how to create, modify and delete API Key. You also practice query based security limitation applied with role descriptor. If you have any questions please leave in comments section.

Follow me on LinkedIn

Leave a Reply

Your email address will not be published. Required fields are marked *

Share the Post:

Enjoy Free Useful Amazing Content

Related Posts