Document level security not behaving as expected

Hello.

I am trying to setup document level security for a single index. My goal is to restrict access to documents in a way, where users only have access to the documents where their username match a field in the document. After logging into the newly created users, I am expecting to only see documents related to that user. However, I receive all documents. I am currently using a trial license.

My license:

{
  "license": {
    "status": "active",
    "uid": "68d47d6b-e629-4cf6-b882-f2fc4ecae7a2",
    "type": "trial",
    "issue_date": "2022-10-07T11:12:25.839Z",
    "issue_date_in_millis": 1665141145839,
    "expiry_date": "2022-11-06T11:12:25.839Z",
    "expiry_date_in_millis": 1667733145839,
    "max_nodes": 1000,
    "max_resource_units": null,
    "issued_to": "elasticsearch",
    "issuer": "elasticsearch",
    "start_date_in_millis": -1
  }
}

Here is my (very simple) approach:

First, I create an index. Let's call it "abc_index":

PUT abc_index
{
  "mappings" : {
    "properties" : {
      "body" : { "type" : "text" },
      "user" : { "type" : "text" }
    }
  }
}

Response:

{
  "acknowledged": true,
  "shards_acknowledged": true,
  "index": "abc_index"
}

Then, I create three documents. Two belonging to "jimmy" and one belonging to "thomas":

PUT abc_index/_doc/1
{ 
  "user": "jimmy",
  "body": "This is a document written by Jimmy :)"
}

PUT abc_index/_doc/2
{ 
  "user": "jimmy",
  "body": "This is another document written by Jimmy :-("
}

PUT abc_index/_doc/3
{ 
  "user": "thomas",
  "body": "THIS DOCUMENT IS THOMAS' PRIVATE DOCUMENT DO NOT READ"
}

Response of all 3 queries above (note that I have altered _id to reflect the individual runs):

{
  "_index": "abc_index",
  "_id": "<1/2/3>",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 2,
  "_primary_term": 1
}

Now I want to create a role for users to restrict their access to documents related to them. For simplicity's sake, let's create a role that will show only results belonging to jimmy and assign jimmy to that role:

Note: I've done the following based on this.

POST /_security/role/abc_role
{
  "indices": [
    {
      "names": [ "abc_*" ],
      "privileges": [ "read" ],
      "query": "{\"match\": {\"user\": \"jimmy\"}}"
    }
  ]
}

Result:

{
  "role": {
    "created": true
  }
}

... Then create the "jimmy" user with the new role:

PUT /_security/user/jimmy
{
    "username": "jimmy",
    "password":"test1234",
    "roles": ["abc_role", "viewer"],
    "full_name": "Jimmy Neutron",
    "email": "Jimmy@Neutron.com"
}

Result:

{
  "created": true
}

Now, after logging into the newly created "jimmy" account, I should expect to only get document 1 and 2, belonging to jimmy. However, I get the following result:

GET abc_index/_search

Result:

{
  "took": 0,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 3,
      "relation": "eq"
    },
    "max_score": 1,
    "hits": [
      {
        "_index": "abc_index",
        "_id": "1",
        "_score": 1,
        "_source": {
          "user": "jimmy",
          "body": "This is a document written by Jimmy :)"
        }
      },
      {
        "_index": "abc_index",
        "_id": "2",
        "_score": 1,
        "_source": {
          "user": "jimmy",
          "body": "This is another document written by Jimmy :-("
        }
      },
      {
        "_index": "abc_index",
        "_id": "3",
        "_score": 1,
        "_source": {
          "user": "thomas",
          "body": "THIS DOCUMENT IS THOMAS' PRIVATE DOCUMENT DO NOT READ"
        }
      }
    ]
  }
}

Trying the following yields the expected result:

GET abc_index/_search
{
  "query": {
    "match": {
      "user": "jimmy"
    }
  }
}

Result:

{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": {
      "value": 2,
      "relation": "eq"
    },
    "max_score": 0.4700036,
    "hits": [
      {
        "_index": "abc_index",
        "_id": "1",
        "_score": 0.4700036,
        "_source": {
          "user": "jimmy",
          "body": "This is a document written by Jimmy :)"
        }
      },
      {
        "_index": "abc_index",
        "_id": "2",
        "_score": 0.4700036,
        "_source": {
          "user": "jimmy",
          "body": "This is another document written by Jimmy :-("
        }
      }
    ]
  }
}

...
What am I missing? Cleary, I must be misunderstanding something. If so, please let me know.
I've searched around a lot and I have tried numerous things but nothing has worked for me.

Based on this thread, I thought it might have something to do with role permissions being overwritten or something similar, but I was unable to find anything that indicated that this was the issue.

I am fearly new to all of this so any help is greatly appreciated.
Thanks.

The built in viewer role gives access to all indices, so overrides the more restrictive access in your abc_role.

1 Like

Hello @Christian_Dahlqvist

Thank you so much for your response. This was indeed the issue. After creating the user with only the "abc_role", I was able to get only the documents related to Jimmy.

Originally I added the viewer role to the user to enable access to the interface, so the user could inspect data from there. When using curl, I get the expected result.

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.