Skip to content

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: , HDR:Accept=*/*, Authorization=, Content-Length=157, Content-Type=application/json, Host=127.0.0.1:9200, User-Agent=curl/7.64.1, HIS:[CONTAINER ADMIN-> RULES:[auth_key->false] RESOLVED:[indices=index*,dev2_index,dev1_index;template=ADD(test:index*:dev2_index,dev1_index)]], `[dev1 block-> RULES:[auth_key->true, indices->false]` RESOLVED:[user=dev1;indices=index*,dev2_index,dev1_index;template=ADD(test:index*:dev2_index,dev1_index)]], [dev2 block-> RULES:[auth_key->false] RESOLVED:[indices=index*,dev2_index,dev1_index;template=ADD(test:index*:dev2_index,dev1_index)]], } We can see that our request was forbidden - credentials were OK, but `indices` rule was not matched in `dev1 block`. We can see also that ROR found 3 indices which are related to the request: * `index*` - an index pattern from our request * `dev1_index` - a first alias from out request * `dev2_index` - a second alias from out request When we take a look at indices configured in `indices` rule for our user, we can see that, he has an access only to `idev1` and `idev1_*` indices. Now, it's pretty much obvious why the request was blocked - the user has no access to index pattern and aliases used in the request. Let's try to fix that:
$ 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: , HDR:Accept=*/*, Authorization=, Content-Length=151, Content-Type=application/json, Host=127.0.0.1:9200, User-Agent=curl/7.64.1, HIS:[CONTAINER ADMIN-> RULES:[auth_key->false] RESOLVED:[indices=idev*,idev1,idev1_test;template=ADD(test:idev*:idev1,idev1_test)]], `[dev1 block-> RULES:[auth_key->true, indices->false]` RESOLVED:[user=dev1;indices=idev*,idev1,idev1_test;template=ADD(test:idev*:idev1,idev1_test)]], [dev2 block-> RULES:[auth_key->false] RESOLVED:[indices=idev*,idev1,idev1_test;template=ADD(test:idev*:idev1,idev1_test)]], } We can see that `indices` rule hasn't not been matched. Looking at the IDX section, we can figure out that the index pattern we requested `idev*`, cannot be allowed. `idev*` is too generic, because in the `indices` list we have `["idev1", "idev1_*"]`. Let's try to fix that:
$ 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.