[role="xpack"]
[[defining-roles]]
=== Defining roles

A role is defined by the following JSON structure:

[source,js]
-----
{
  "run_as": [ ... ], <1>
  "cluster": [ ... ], <2>
  "indices": [ ... ] <3>
}
-----
// NOTCONSOLE

<1> A list of usernames the owners of this role can <<run-as-privilege, impersonate>>.
<2> A list of cluster privileges. These privileges define the
    cluster level actions users with this role are able to execute. This field
    is optional (missing `cluster` privileges effectively mean no cluster level
    permissions).
<3> A list of indices permissions entries. This field is optional (missing `indices`
    privileges effectively mean no index level permissions).

[[valid-role-name]]
NOTE: Role names must be at least 1 and no more than 1024 characters. They can
      contain alphanumeric characters (`a-z`, `A-Z`, `0-9`), spaces,
      punctuation, and printable symbols in the https://en.wikipedia.org/wiki/Basic_Latin_(Unicode_block)[Basic Latin (ASCII) block].
      Leading or trailing whitespace is not allowed.

The following describes the structure of an indices permissions entry:

[source,js]
-------
{
  "names": [ ... ], <1>
  "privileges": [ ... ], <2>
  "field_security" : { ... }, <3>
  "query": "..." <4>
}
-------
// NOTCONSOLE

<1> A list of indices (or index name patterns) to which the permissions in this
    entry apply.
<2> The index level privileges the owners of the role have on the associated
    indices (those indices that are specified in the `name` field)
<3> Specification for document fields the owners of the role have read access to.
    See <<field-and-document-access-control>> for details.
<4> A search query that defines the documents the owners of the role have read
    access to. A document within the associated indices must match this query
    in order for it to be accessible by the owners of the role.

[TIP]
==============================================================================
When specifying index names, you can use indices and aliases with their full
names or regular expressions that refer to multiple indices.

* Wildcard (default) - simple wildcard matching where `*` is a placeholder
  for zero or more characters, `?` is a placeholder for a single character
  and `\` may be used as an escape character.

* Regular Expressions - A more powerful syntax for matching more complex
  patterns. This regular expression is based on Lucene's regexp automaton
  syntax. To enable this syntax, it must be wrapped within a pair of
  forward slashes (`/`). Any pattern starting with `/` and not ending with
  `/` is considered to be malformed.

.Example Regular Expressions
[source,yaml]
------------------------------------------------------------------------------
"foo-bar":               # match the literal `foo-bar`
"foo-*":                 # match anything beginning with "foo-"
"logstash-201?-*":       # ? matches any one character
"/.*-201[0-9]-.*/":      # use a regex to match anything containing 2010-2019
"/foo":                  # syntax error - missing final /
------------------------------------------------------------------------------
==============================================================================

The following snippet shows an example definition of a `clicks_admin` role:

[source,js]
-----------
POST /_xpack/security/role/clicks_admin
{
  "run_as": [ "clicks_watcher_1" ],
  "cluster": [ "monitor" ],
  "indices": [
    {
      "names": [ "events-*" ],
      "privileges": [ "read" ],
      "field_security" : {
        "grant" : [ "category", "@timestamp", "message" ]
      },
      "query": "{\"match\": {\"category\": \"click\"}}"
    }
  ]
}
-----------
// CONSOLE

Based on the above definition, users owning the `clicks_admin` role can:

  * Impersonate the `clicks_watcher_1` user and execute requests on its behalf.
  * Monitor the {es} cluster
  * Read data from all indices prefixed with `events-`
  * Within these indices, only read the events of the `click` category
  * Within these document, only read the `category`, `@timestamp` and `message`
    fields.

TIP:  For a complete list of available <<security-privileges, cluster and indices privileges>>

There are two available mechanisms to define roles: using the _Role Management APIs_
or in local files on the {es} nodes.  {security} also supports implementing
custom roles providers.  If you need to integrate with another system to retrieve
user roles, you can build a custom roles provider plugin. For more information,
see <<custom-roles-provider, Custom Roles Provider Extension>>.

[float]
[[roles-management-ui]]
=== Role management UI

{security} enables you to easily manage users and roles from within {kib}. To
manage roles, log in to {kib} and go to *Management / Elasticsearch / Roles*. 

[float]
[[roles-management-api]]
=== Role management API

The _Role Management APIs_ enable you to add, update, remove and retrieve roles
dynamically. When you use the APIs to manage roles in the `native` realm, the
roles are stored in an internal {es} index. For more information and examples, 
see {ref}/security-api-roles.html[Role Management APIs]. 

[float]
[[roles-management-file]]
=== File-based role management

Apart from the _Role Management APIs_, roles can also be defined in local
`roles.yml` file located in `CONFIG_DIR`. This is a YAML file where each
role definition is keyed by its name.

[IMPORTANT]
==============================
If the same role name is used in the `roles.yml` file and through the
_Role Management APIs_, the role found in the file will be used.
==============================

While the _Role Management APIs_ is the preferred mechanism to define roles,
using the `roles.yml` file becomes useful if you want to define fixed roles that
no one (beside an administrator having physical access to the {es} nodes)
would be able to change.

[IMPORTANT]
==============================
The `roles.yml` file is managed locally by the node and is not globally by the
cluster. This means that with a typical multi-node cluster, the exact same
changes need to be applied on each and every node in the cluster.

A safer approach would be to apply the change on one of the nodes and have the
`roles.yml` distributed/copied to all other nodes in the cluster (either
manually or using a configuration management system such as Puppet or Chef).
==============================

The following snippet shows an example of the `roles.yml` file configuration:

[source,yaml]
-----------------------------------
click_admins:
  run_as: [ 'clicks_watcher_1' ]
  cluster: [ 'monitor' ]
  indices:
    - names: [ 'events-*' ]
      privileges: [ 'read' ]
      field_security:
        grant: ['category', '@timestamp', 'message' ]
      query: '{"match": {"category": "click"}}'
-----------------------------------

{security} continuously monitors the `roles.yml` file and automatically picks
up and applies any changes to it.
