Debugging role-based access control to documents

Is there a way to see how access to a particular document set has been granted (i.e: where the permission has come from)?

context

We have several indices that employ document level security to restrict access, by role, to particular subsets of documents. This enables us to use an access control list to assign users to roles that grant read permissions over subsets of documents in our indices.

Although this has been working well for us previously, when it came time to configure this for a new index and role set, we find that users can see many more documents than they should be able to.

example where all is as-expected

GET /_security/role/banana_department_stockroom

{
  "banana_department_stockroom" : {
    "cluster" : [ ],
    "indices" : [
      {
        "names" : [
          "stockroom-reports-*",
          "stockroom-reports"
        ],
        "privileges" : [
          "read",
          "view_index_metadata"
        ],
        "query" : """{"bool":{"filter":[{"term":{"org.unit_code":"banana_department"}}]}}""",
        "allow_restricted_indices" : false
      }
    ],
    "applications" : [ /* kibana */ ],
    "run_as" : [ ],
    "metadata" : { },
    "transient_metadata" : {
      "enabled" : true
    }
  }
}

non-working example

GET /_security/role/banana_department_sales

{
  "banana_department_sales" : {
    "cluster" : [ ],
    "indices" : [
      {
        "names" : [
          "sales-reports-*",
          "sales-reports"
        ],
        "privileges" : [
          "read",
          "view_index_metadata"
        ],
        "query" : """{"bool":{"filter":[{"term":{"org.unit_code":"banana_department"}}]}}""",
        "allow_restricted_indices" : false
      }
    ],
    "applications" : [ ],
    "run_as" : [ ],
    "metadata" : { },
    "transient_metadata" : {
      "enabled" : true
    }
  }
}

In the working example, members of the banana department with the banana_department_stockroom role can query the stockroom reports and only see their own data and don't see any data from the other departments; in searches it is as if they were the only department in the whole organisation. In Kibana's logs, we see expected audit events granting access for these queries.

However, in the case of the sales reports index, they can view all the other department's data. Kibana's logs show the same audit events.

I have checked all the other roles of affected users and cannot see any extraneous permissions that would affect this. If I perform a search using the same query as above, I see the subset of documents I was expecting.

Any pointers would be greatly appreciated! I am going a little bananas myself trying to figure it out.

Many thanks!

Login as one of the sales users and run GetUserPrivileges API. What do you see? Does it still show document level security for the sales indices? If not, there are other roles granting more permissions.

Also, do you have anonymous access enabled?

Hello, thank you very much for your pointers.

  • Anonymous access is disabled: users must authenticate. Our load balancer picks a kibana or elasticsearch instance (as appropriate) to farm the request to and sets the es-security-runas-user header via its authentication provider. We know this part is working from the audit logs which correctly identify the user.name and displays the expected list of roles.

  • I used the elasticsearch Python library's es.security.get_user_privileges(), which shows me the following output:

{
  'cluster': [ ],
  'global': [ ],
  'indices': [
    { 
      'names': [ 'stockroom-reports',
                 'stockroom-reports-*' ],
      'privileges': [ 'read', 'view_index_metadata' ],
      'query': [
        '{"bool":{"filter":[{"term":{"org.unit_code":"banana_department"}}]}}'
      ],
      'allow_restricted_indices': False
    },
    {
      'names': [ 'sales-reports',
                 'sales-reports-*' ],
      'privileges': [ 'read', 'view_index_metadata' ],
      'query': [
        '{"bool":{"filter":[{"term":{"org.unit_code":"banana_department"}}]}}'
      ],
      'allow_restricted_indices': False
    }
  ],
  'applications': [ { 'application': 'kibana-.kibana',
            # snip for brevity
                  } ],
  'run_as': [ ]
}

This seems to reflect what I would have expected. What ideally would be helpful is if there was some way of logging or producing an explanation for the role and permission set used to gain access to a particular document or results set in a search. For example, "run as user bananateam_alice successful due to the read permission inherited from role banana_department_sales", or alternatively an "explain permission" API that can be run against an index, so that comparisons can be made between functional and non-functional indices.

The audit log can show the effective user and its role for every granted action. You can use that to make sure the user and roles are working as expected. Elasticsearch currently does not provide more information about exactly which role and which index permission is used to grant the access.

In your case, I'd suggest reduce the number of variables. Maybe start with a new user, grant it a single role that has a single index privileges, e.g.:

PUT _security/role/foo-role
{
  "indices": [
    {
      "names": [
        "sales-reports"
      ],
      "privileges": [
        "read"
      ],
      'query': [
        '{"bool":{"filter":[{"term":{"org.unit_code":"banana_department"}}]}}'
      ]
    }
  ]
}

PUT _security/user/foo
{"password":"password","roles":["foo-role"]}

And see if permissions work correctly for the new user foo. This should help narrowing down the problem.

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