Templates handling in indices rule
A ROR configuration for all examples below (click to expand)
```yaml readonlyrest: prompt_for_basic_auth: false access_control_rules: - name: "admin block" verbosity: error type: allow auth_key: admin:admin - name: "dev1 block" indices: ["idev1", "idev1_*"] auth_key: dev1:test - name: "dev2 block" indices: ["idev2", "idev2_*"] auth_key: dev2:test ```Index templates
An indices rule takes into consideration index patterns and aliases which are a part of a template definition. We should consider four types of template related requests:
Create an index template
The request will be allowed when all of following conditions are met: * a template with requested name does not exist (if it does, it's rather a template modification, than a creation), * all index patterns of the new, requested template are allowed, * all aliases of the new, requested template are allowed.
Example (click to expand)
Let's try to add an index template. We can see, using `admin` account, that there are no templates defined yet.$ curl -vk -u admin:admin "http://localhost:9200/_index_template?pretty"
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
{
"index_templates" : [ ]
}
Now, let's use `dev1` user account to create an index template `temp1`:
$ curl -vk -u dev1:test -XPUT "http://127.0.0.1:9200/_index_template/test?pretty" -H "Content-Type: application/json" -d \
'{
"index_patterns":["index*"],
"template": {
"aliases": {
"dev1_index": {},
"dev2_index": {}
}
}
}'
HTTP/1.1 403 Forbidden
content-type: application/json; charset=UTF-8
{
"error" : {
"root_cause" : [
{
"reason" : "forbidden",
"due_to" : ["OPERATION_NOT_ALLOWED"]
}
],
"reason" : "forbidden",
"due_to" : ["OPERATION_NOT_ALLOWED"],
"status" : 403
}
}
Oh, something went wrong. It seems that, a user `dev1` is not allowed to add this template. Let's check ROR logs to figure out why:
> FORBIDDEN by default req={ ID:193441275-173645661#8, TYP:PutComposableIndexTemplateAction$Request, CGR:N/A, USR:dev1 (attempted), BRS:true, KDX:null, ACT:indices:admin/index_template/put, OA:127.0.0.1/32, XFF:null, DA:127.0.0.1/32, `IDX:index*,dev2_index,dev1_index`, MET:PUT, `PTH:/_index_template/test`, CNT:$ curl -vk -u dev1:test -XPUT "http://127.0.0.1:9200/_index_template/test?pretty" -H "Content-Type: application/json" -d \
'{
"index_patterns":["idev1_test*"],
"template": {
"aliases": {
"idev1": {},
"idev1_test": {}
}
}
}'
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
{
"acknowledged" : true
}
Hooray! The index template was added. This time ROR allowed us to do so. It's because `dev1` user has an access to index pattern `idev1_test*`, because it is contained in `idev1_*`. Used aliases are also allowed.
Modify an index template
The request will be allowed when all of following conditions are met: * a template with requested name does exist, * all index patterns of the existing template are allowed, * all aliases of the existing template are allowed, * all index patterns of the requested template are allowed, * all aliases of the requested template are allowed.
Example (click to expand)
Let's assume the user `dev1` would like to modify the previously created template, because the index pattern is too detailed:$ curl -vk -u dev1:test -XPUT "http://127.0.0.1:9200/_index_template/test?pretty" -H "Content-Type: application/json" -d \
'{
"index_patterns":["idev*"],
"template": {
"aliases": {
"idev1": {},
"idev1_test": {}
}
}
}'
HTTP/1.1 403 Forbidden
content-type: application/json; charset=UTF-8
{
"error" : {
"root_cause" : [
{
"reason" : "forbidden",
"due_to" : ["OPERATION_NOT_ALLOWED"]
}
],
"reason" : "forbidden",
"due_to" : ["OPERATION_NOT_ALLOWED"],
"status" : 403
}
}
Ups! Something is wrong. Let's check the ROR forbidden log:
> FORBIDDEN by default req={ ID:918326057-1726421783#75, TYP:PutComposableIndexTemplateAction$Request, CGR:N/A, USR:dev1 (attempted), BRS:true, KDX:null, ACT:indices:admin/index_template/put, OA:127.0.0.1/32, XFF:null, DA:127.0.0.1/32, `IDX:idev*,idev1,idev1_test`, MET:PUT, PTH:/_index_template/test, CNT:$ curl -vk -u dev1:test -XPUT "http://127.0.0.1:9200/_index_template/test?pretty" -H "Content-Type: application/json" -d \
'{
"index_patterns":["idev1_*"],
"template": {
"aliases": {
"idev1": {},
"idev1_test": {}
}
}
}'
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
{
"acknowledged" : true
}
Yeah, now it works. Let's check if the template is modified (we will use `admin` user to do so):
$ curl -vk -u admin:admin "http://127.0.0.1:9200/_index_template?pretty"
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
{
"error" : {
"root_cause" : [
{
"reason" : "forbidden",
"due_to" : ["OPERATION_NOT_ALLOWED"]
}
],
"reason" : "forbidden",
"due_to" : ["OPERATION_NOT_ALLOWED"],
"status" : 403
}
}
All is good. We have only one template and the modifications was applied.
So far, so good. But we can wonder what happens if `dev2` will try to modify (or override) template `temp`? Let's check:
$ curl -vk -u dev2:test -XPUT "http://127.0.0.1:9200/_index_template/test?pretty" -H "Content-Type: application/json" -d \
'{
"index_patterns":["idev2_*"],
"template": {
"aliases": {
"idev2": {},
"idev2_test": {}
}
}
}'
HTTP/1.1 403 Forbidden
content-type: application/json; charset=UTF-8
{
"error" : {
"root_cause" : [
{
"reason" : "forbidden",
"due_to" : ["OPERATION_NOT_ALLOWED"]
}
],
"reason" : "forbidden",
"due_to" : ["OPERATION_NOT_ALLOWED"],
"status" : 403
}
}
Yes! This is something what we wanted like to see. Even if the request was correct and the user `dev2` has an access to the requested index pattern and aliases, the request was forbidden. Obviously, there is already existed template `temp` which has the index pattern and aliases, which are not allowed for `dev2`. ROR deduces that `dev2` cannot be considered as someone how can modify/overwrite it.
Pretty awesome. Won't `dev2` also be able to remove it? We'll see in next section ...
Delete an index template
The request will be allowed when template does not exist OR all of the following conditions are met: * a template with requested name does exist, * all index patterns of the existing template are allowed, * all aliases of the existing template are allowed.
Example (click to expand)
In the last section we wondered, if ROR will be able to block removing the template `temp` by the user `dev2`. Let's recall, that we proved that the user is not able to modify this template, because ROR considers that he doesn't have permissions to change/remove it.$ curl -vk -u dev2:test -XDELETE "http://127.0.0.1:9200/_index_template/test?pretty"
HTTP/1.1 403 Forbidden
content-type: application/json; charset=UTF-8
{
"error" : {
"root_cause" : [
{
"reason" : "forbidden",
"due_to" : ["OPERATION_NOT_ALLOWED"]
}
],
"reason" : "forbidden",
"due_to" : ["OPERATION_NOT_ALLOWED"],
"status" : 403
}
}
Perfect! OK, but we also would like to know if `user1` will be able to remove his template. Let's check it:
$ curl -vk -u dev1:test -XDELETE "http://127.0.0.1:9200/_index_template/test?pretty"
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
{
"acknowledged" : true
}
Great! Everything works.
Get index templates
At the moment ROR doesn't have templates rule (similar to
snapshots or repositories), which allows to restrict which
templates can be visible to the user (it is going to change in the
future). But the indices rule is enough to filter templates based
on index patterns in their definitions. An index template is
considered to be visible for a user, when the user has access to
AT LEAST ONE index pattern of the template's index pattern list.
ROR is going to show the template but to hide the information about not allowed index patterns and not allowed aliases.
Example (click to expand)
In previous sections we proved that ROR gets along with index templates adding, modifying and removing pretty well. Now, we'd like check what index templates are supposed to be visible for users. Let's assume we have 4 index templates:$ curl -vk -u admin:admin "http://127.0.0.1:9200/_index_template?pretty"
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
{
"index_templates" : [
{
"name" : "t1",
"index_template" : {
"index_patterns" : ["i*"],
"template" : {
"aliases" : {
"idev2" : { },
"idev3" : { },
"idev1" : { }
}
},
"composed_of" : [ ]
}
},
{
"name" : "t2",
"index_template" : {
"index_patterns" : ["idev1_*"],
"template" : {
"aliases" : {
"admin_idev" : { },
"idev1" : { }
}
},
"composed_of" : [ ],
"priority" : 1
}
},
{
"name" : "t3",
"index_template" : {
"index_patterns" : ["idev2_*"],
"template" : {
"aliases" : {
"idev2" : { },
"admin_idev" : { }
}
},
"composed_of" : [ ],
"priority" : 1
}
},
{
"name" : "t4",
"index_template" : {
"index_patterns" : ["idev1_*", "idev2_*"],
"template" : {
"aliases" : {
"idev2" : { },
"admin_idev" : { },
"idev1" : { }
}
},
"composed_of" : [ ],
"priority" : 2
}
}
]
}
`admin` has unrestricted access to all templates. Now, let's check which templates `dev` are supposed to see:
$ curl -vk -u dev1:test "http://127.0.0.1:9200/_index_template?pretty"
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
{
"index_templates" : [
{
"name" : "t1",
"index_template" : {
"index_patterns" : ["i*"],
"template" : {
"aliases" : {
"idev1" : { }
}
},
"composed_of" : [ ]
}
},
{
"name" : "t2",
"index_template" : {
"index_patterns" : ["idev1_*"],
"template" : {
"aliases" : {
"idev1" : { }
}
},
"composed_of" : [ ],
"priority" : 1
}
},
{
"name" : "t4",
"index_template" : {
"index_patterns" : ["idev1_*"],
"template" : {
"aliases" : {
"idev1" : { }
}
},
"composed_of" : [ ],
"priority" : 2
}
}
]
}
Hmm, we can see many weird things here. Let's start with the simplest case: index template `t2` is allowed for the user, because the used index pattern is allowed by `indices` rule. But we can also see that user `dev1` is not aware of existence the `admin_idev` alias - it was filter out from the aliases list. The user has no access to the alias, so he should not be able to see it.
What about the index template `t3`? `dev1` is not allowed to see it because the index pattern `idev2_*` is not allowed for him. It was also pretty much obvious!
The next is `t4`. When `admin` had listed index templates, we saw that template `t4` has 2 index patterns. But `dev1` can see only one. This is great, because he has an access to a part of that template, so he definitely should be able to see it. ROR behaviour here is pretty neat - it allows the user to see a template with filtered, not allowed parts of it, but at the same time, the user doesn't have permissions to modify/remove the template (Don't believe me? Go ahead and check!)
And the last one to explain - `t1`. The index pattern of the template is `i*`. Obviously user `dev1` has no access to it, because his allowed indices are `idev1, idev1_*`. But if we imagine all possible values generated from pattern `i*` and all possible values generated from `idev1, idev1_*`, we can notice that the latter will be a subset of the first. It means that this template can be interesting for the user `dev1`, because it will ba applied to indices created by him. That's why ROR decides to show it.
Component templates
Component templates doesn't have index patterns but could have aliases. So, in this case, we should also consider four types of template related requests:
Create a component template
The request will be allowed when all of following conditions are met: * a template with requested name does not exist (if it does, it's rather a template modification, than a creation), * all aliases of the new, requested template are allowed.
Example (click to expand)
Unlike index templates, component templates don't have index patterns. But they still have aliases. So, their behaviour according to an aliases usage is quite similar, but there are several differences which are worth mentioning. Let's check if `dev1` user can create a component template:$ curl -vk -u dev1:test "http://localhost:9200/_component_template/ctemp1?pretty" -XPUT -H "Content-Type: application/json" -d \
'{
"template": {
"settings": {
"index.number_of_replicas": 0
},
"aliases": {
"idev1": {},
"idev2": {}
}
}
}'
HTTP/1.1 403 Forbidden
content-type: application/json; charset=UTF-8
{
"error" : {
"root_cause" : [
{
"reason" : "forbidden",
"due_to" : ["OPERATION_NOT_ALLOWED"]
}
],
"reason" : "forbidden",
"due_to" : ["OPERATION_NOT_ALLOWED"],
"status" : 403
}
}
Oh, user `dev1` is not allowed to create this template. But wait! It looks like we have the same problem as had while creating index template. Alias `idev2` is not allowed. Let's try to do the same without this alias:
$ curl -vk -u dev1:test "http://localhost:9200/_component_template/ctemp1?pretty" -XPUT -H "Content-Type: application/json" -d \
'{
"template": {
"settings": {
"index.number_of_replicas": 0
},
"aliases": {
"idev1": {}
}
}
}'
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
{
"acknowledged" : true
}
Ha! As expected. A user has to have access to all aliases during adding a component template which has aliases defined.
*Note*
If a component template doesn't involve aliases, there is no restriction from ROR side to add one. It can be changed in future, when we add sth like `templates` rule.
Modify a component template
The request will be allowed when all of following conditions are met: * a template with requested name does exist, * all aliases of the existing template are allowed, * all aliases of the requested template are allowed.
Example (click to expand)
In the previous example, user `dev1` created the component template `ctemp1` with one alias `idev1`. Let's check if user `dev2` will be able to modify it:$ curl -vk -u dev2:test "http://localhost:9200/_component_template/ctemp1?pretty" -XPUT -H "Content-Type: application/json" -d \
'{
"template": {
"settings": {
"index.number_of_replicas": 0
},
"aliases": {
"idev2": {}
}
}
}'
HTTP/1.1 403 Forbidden
content-type: application/json; charset=UTF-8
{
"error" : {
"root_cause" : [
{
"reason" : "forbidden",
"due_to" : ["OPERATION_NOT_ALLOWED"]
}
],
"reason" : "forbidden",
"due_to" : ["OPERATION_NOT_ALLOWED"],
"status" : 403
}
}
No. And this is a good behaviour, because `dev2` doesn't have an access to the alias `idev1` which the `ctemp1` has. ROR assumes, that he cannot modify the component template (please notice, that the same request will be allowed when a different, nonexistent component template name is used). I can assure you that `dev1` is able to modify the template (you can check if you want).
Delete a component template
The request will be allowed when template does not exist OR all of the following conditions are met: * a template with requested name does exist, * all aliases of the existing template are allowed.
Example (click to expand)
If you read the previous example, you won't find anything interesting here. A component template can be removed only by someone whom ROR considers to have modification rights of the template. See that `dev2` is not able to remove `ctemp1`:$ curl -vk -u dev2:test -XDELETE "http://localhost:9200/_component_template/ctemp1?pretty"
HTTP/1.1 403 Forbidden
content-type: application/json; charset=UTF-8
{
"error" : {
"root_cause" : [
{
"reason" : "forbidden",
"due_to" : ["OPERATION_NOT_ALLOWED"]
}
],
"reason" : "forbidden",
"due_to" : ["OPERATION_NOT_ALLOWED"],
"status" : 403
}
}
I told you. But please remember that only aliases are checked by ROR when it's trying to figure out modification rights of a component template. If a component template doesn't have any aliases, it can be modified or deleted by any user.
Get component templates
At the moment there is no way to restrict which component templates can be visible to the user (it is going to change in the future - see a corresponding index template section). But ROR is going to hide the information about not allowed aliases of returned component templates.
Example (click to expand)
A careful reader can guess that ROR won't forbid showing component templates. But similar to indices templates, ROR will filter out aliases list depending on an aliases accessability of current user. Let's see an example:$ curl -vk -u admin:admin "http://localhost:9200/_component_template?pretty"
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
{
"component_templates" : [
{
"name" : "ctemp2",
"component_template" : {
"template" : {
"settings" : {
"index" : {
"number_of_replicas" : "0"
}
},
"aliases" : {
"idev2" : { }
}
}
}
},
{
"name" : "ctemp1",
"component_template" : {
"template" : {
"settings" : {
"index" : {
"number_of_replicas" : "0"
}
},
"aliases" : {
"idev1" : { }
}
}
}
}
]
}
We can see that we have two component templates. `ctemp1` has alias `idev1` and `ctemp2` alias `idev2`. Let check what templates `dev1` user will be able to see:
$ curl -vk -u dev1:test "http://localhost:9200/_component_template?pretty"
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
{
"component_templates" : [
{
"name" : "ctemp2",
"component_template" : {
"template" : {
"settings" : {
"index" : {
"number_of_replicas" : "0"
}
},
"aliases" : { }
}
}
},
{
"name" : "ctemp1",
"component_template" : {
"template" : {
"settings" : {
"index" : {
"number_of_replicas" : "0"
}
},
"aliases" : {
"idev1" : { }
}
}
}
}
]
}
We can see that he is able to see all component templates, but `ctemp2` doesn't have `idev2` alias. User `dev1` has no access to the alias, so response returned by ROR doesn't contain the alias. Similar behaviour we will observe when `dev2` user will try to get all templates.
Troubleshooting
To figure out why the template is not returned or/and cannot be altered, you should enable a DEBUG log level and check your logs. ROR logs each step of template request handling in the indices rule, so detailed description should explain the given template is not allowed.