Document level security: placeholders for USERNAME and ROLE in the role's query


#1

Hello All,

I'm wondering if it is possible to use placeholders (like
{USERNAME} or {ROLENAME} in the "Edit Role" query for restricting access to some documents?
Let's say, we'd have the following ACL field in a document:

"acl_allow": ["user1", "group1", "group2"]

Then the following general Indices Privileges query would grant access to user1 only:

{"match": {"acl_allow": "{USERNAME}" } }

The same method could be used to restrict access by groups/roles. As you can imagine, the point is: to reduce the role management efforts on the Elasticsearch side, because the mapping feature (unmapped_groups_as_roles: true) of external realms would allow us to manage access externally (in AD/LDAP).

Make sense? :slight_smile:
Thank you!


(Tim Vernum) #2

Assuming I understand your question correctly, the feature you are looking for is templates in role queries.


#3

That is exactly, what I was looking for! Sorry, I didn't realized it has been documented already!
So, I'm trying the template role query right now, but I'm not getting results:

GET /_xpack/security/role/searchgrp
{
  "searchgrp": {
	"cluster": [],
	"indices": [
	  {
		"names": [
		  "topbeat-*",
		  "test",
		  ".kibana"
		],
		"privileges": [
		  "read",
		  "view_index_metadata"
		],
		"field_security": {
		  "grant": [
			"*"
		  ]
		},
		"query": "{ \"match\" : { \"acl_allow\" : \"{{_user.username}}\" }}"
	  }
	],
	"run_as": [],
	"metadata": {}
  }
}

Query:

GET http://localhost:9200/test/_search
{
	"took": 2,
	"timed_out": false,
	"_shards": {
		"total": 1,
		"successful": 1,
		"failed": 0
	},
	"hits": {
		"total": 0,
		"max_score": null,
		"hits": []
	}
}

Logs:

[2017-01-18T14:27:26,784][DEBUG][o.e.x.s.a.a.ActiveDirectoryRealm] [host] authenticated user [search], with roles [[searchgrp, Domain Users, Users]]
[2017-01-18T14:27:26,790] [transport] [access_granted]  origin_type=[rest], origin_address=[127.0.0.1], principal=[search], action=[indices:data/read/search], indices=[test], request=[SearchRequest]
[2017-01-18T14:27:26,791] [transport] [access_granted]  origin_type=[rest], origin_address=[127.0.0.1], principal=[search], action=[indices:data/read/search[phase/query+fetch]], indices=[test], request=[ShardSearchTransportRequest]

If I replace the template {{_user.username}} by the real user name ("search") in the role query, then the "secured" documents get found.

Am I missing something?

Thank you!

Update:
Index mapping:

PUT test
{
  "mappings": {
	"t": {
	  "properties": {
		"acl_allow": {
		  "type": "string",
		  "index": "not_analyzed"
		}
	  }
	}
  }
}

corresponding superuser query:

GET test/_search
{
  "query": {
	"match": {
	  "acl_allow": "search"
	}
  }
}

{
  "took": 1,
  "timed_out": false,
  "_shards": {
	"total": 1,
	"successful": 1,
	"failed": 0
  },
  "hits": {
	"total": 1,
	"max_score": 1.2039728,
	"hits": [
	  {
		"_index": "test",
		"_type": "t",
		"_id": "1",
		"_score": 1.2039728,
		"_source": {
		  "title": "document 1",
		  "acl_allow": [
			"search"
		  ]
		}
	  }
	]
  }
}

Update II
Upgraded the ES instance from 5.0.0 to 5.1.2 - no improvements, can't make the "mustache" template working.
Any suggestions would be highly appreciated!
Thanks!


#4

so, is it a bug?..


(Jay Modi) #5

You need to use the template query in the role for the substitutions to work


#6

I apologize! Indeed, I forgot to "template" the role query!
Sorry again - everything is well documented and working!

Thank you very much guys!


#7

I'm sorry, still need help with _user.roles template. Since it should contain a list of the role names of the current user, I assume, that the terms query should be used. The following role query does not produce result:

{
  "template": {
	"inline": {
		  "terms": {"acl_allow":["{{_user.roles}}"]}
		}
  }
}

What is the right way to query with _user.roles list?
Thank you!


#8

I did my "homework", and it turned out, that this topic is a duplicate of X-Pack Security : Role definition query template with 'terms'

Anyway, I'm going to summarize my "finding" here again:

User:

{
	"template": {
		"inline": {
			"match": {
				"acl_allow": "{{_user.username}}"
			}
		}
	}
}

Roles:

{
	"template": {
		"inline": "{\"terms\":{\"acl_allow\": {{#toJson}}_user.roles{{/toJson}}}}"
	}
}

Thank you for your help again!


(system) #9

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