[[setting-up-field-and-document-level-security]]
=== Setting Up Field and Document Level Security

You can control access to data within an index by adding field and document level security permissions to a role.
Field level security permissions restrict access to particular fields within a document.
Document level security permissions restrict access to particular documents within an index.

Field and document level permissions are specified separately, but a role can define both field and document level permissions.
Field and document level security permissions can be configured on a per-index basis.

==== Field Level Security

To enable field level security, you specify the fields that each role can access in the `roles.yml` file.
You list the allowed fields with the `fields` option. Fields are associated with a particular index or index pattern and
operate in conjunction with the privileges specified for the indices.

[source,yaml]
--------------------------------------------------
<role_name>:
  indices:
    <index_permission_expression>:
      privileges: <privileges>
      fields:
        - <allowed_field_1>
        - <allowed_field_2>
        - <allowed_field_N>
--------------------------------------------------

To allow access to the `_all` meta field, you must explicitly list it as an allowed field. Access to the following meta fields
is always allowed: _id, _type, _parent, _routing, _timestamp, _ttl, _size and _index. If you specify an empty list of fields,
only these meta fields are accessible.

NOTE: Omitting the fields entry entirely disables field-level security.

For example, the following `customer_care` role grants read access to six fields in any index:

[source,yaml]
--------------------------------------------------
customer_care:
  indices:
    '*':
      privileges: read
      fields:
        - issue_id
        - description
        - customer_handle
        - customer_email
        - customer_address
        - customer_phone
--------------------------------------------------

Also wildcard field expressions can be added to the `fields` options in the `roles.yml` file. For example the following
example has the same effect as the previous example:

[source,yaml]
--------------------------------------------------
customer_care:
  indices:
    '*':
      privileges: read
      fields:
        - issue_id
        - description
        - 'customer_*'
--------------------------------------------------

If documents are more complex and contain json objects then the fields with dot notion should be used.

Assume the following document:

[source,json]
--------------------------------------------------
{
  "customer": {
    "handle": "Jim",
    "email": "jim@mycompany.com",
    "phone": "555-555-5555"
  }
}
--------------------------------------------------

If only access to the `handle` field is allowed then the following role should be setup:

[source,yaml]
--------------------------------------------------
my_role:
  indices:
    '*':
      privileges: read
      fields:
        - customer.handle
--------------------------------------------------

If access to the entire `customer` object is allowed then the wildcard dot notation can be used to make this easier:

[source,yaml]
--------------------------------------------------
my_role:
  indices:
    '*':
      privileges: read
      fields:
        - customer.*
--------------------------------------------------

===== Limitations

When field level security is enabled for an index:

* The get, multi get, termsvector and multi termsvector APIs aren't executed in real time. The realtime option for these APIs is forcefully set to false.
* The query cache and the request cache are disabled for search requests.
* The update API is blocked. An update request needs to be executed via a role that doesn't have field level security enabled.

[[document-level-security]]
==== Document Level Security

Enabling document level security restricts which documents can be accessed from any document based API.
To enable document level security, you use a query to specify the documents that each role can access in the `roles.yml` file.
You specify the document query with the `query` option. The document query is associated with a particular index or index pattern and
operates in conjunction with the privileges specified for the indices.

[source,yaml]
--------------------------------------------------
<role_name>:
  indices:
    <index_permission_expression>:
      privileges: <privileges>
      query:
        <query>
--------------------------------------------------

NOTE: Omitting the `query` entry entirely disables document-level security.

The `query` should follow the same format as if a query was defined in the request body of a search request,
but here the format is YAML. Any query from the query-dsl can be defined in the `query` entry.

For example, the following `customer_care` role grants read access to all indices, but restricts access to documents whose `department_id` equals `12`.

[source,yaml]
--------------------------------------------------
customer_care:
  indices:
    '*':
      privileges: read
      query:
        term:
         department_id: 12
--------------------------------------------------

Alternatively the query can also be defined in JSON as a string. This makes it easier to define queries that already have
been defined in the JSON body of search request body elsewhere.

[source,yaml]
--------------------------------------------------
customer_care:
  indices:
    '*':
      privileges: read
      query: '{"term" : {"department_id" : "12"}}''
--------------------------------------------------
