diff --git a/x-pack/docs/en/security/authorization/field-and-document-access-control.asciidoc b/x-pack/docs/en/security/authorization/field-and-document-access-control.asciidoc index a1aa44895c6a6..119a090232c2f 100644 --- a/x-pack/docs/en/security/authorization/field-and-document-access-control.asciidoc +++ b/x-pack/docs/en/security/authorization/field-and-document-access-control.asciidoc @@ -3,9 +3,11 @@ === 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. +security permissions to a role. +<> restrict access to +particular fields within a document. +<> restrict access +to particular documents within an index. NOTE: Document and field level security is currently meant to operate with read-only privileged accounts. Users with document and field level @@ -23,399 +25,6 @@ grant wider access than intended. Each user has a single set of field level and document level permissions per index. See <>. ===================================================================== -[[field-level-security]] -==== Field level security - -To enable field level security, specify the fields that each role can access -as part of the indices permissions in a role definition. Field level security is -thus bound to a well-defined set of indices (and potentially a set of -<>). - -The following role definition grants read access only to the `category`, -`@timestamp`, and `message` fields in all the `events-*` indices. - -[source,js] --------------------------------------------------- -{ - "indices": [ - { - "names": [ "events-*" ], - "privileges": [ "read" ], - "field_security" : { - "grant" : [ "category", "@timestamp", "message" ] - } - } - ] -} --------------------------------------------------- - -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. - -You can also specify field expressions. For example, the following -example grants read access to all fields that start with an `event_` prefix: - -[source,js] --------------------------------------------------- -{ - "indices" : [ - { - "names" : [ "*" ], - "privileges" : [ "read" ], - "field_security" : { - "grant" : [ "event_*" ] - } - } - ] -} --------------------------------------------------- - -Use the dot notations to refer to nested fields in more complex documents. For -example, assuming the following document: - -[source,js] --------------------------------------------------- -{ - "customer": { - "handle": "Jim", - "email": "jim@mycompany.com", - "phone": "555-555-5555" - } -} --------------------------------------------------- - -The following role definition enables only read access to the customer `handle` -field: - -[source,js] --------------------------------------------------- -{ - "indices" : [ - { - "names" : [ "*" ], - "privileges" : [ "read" ], - "field_security" : { - "grant" : [ "customer.handle" ] - } - } - ] -} --------------------------------------------------- - -This is where wildcard support shines. For example, use `customer.*` to enable -only read access to the `customer` data: - -[source,js] --------------------------------------------------- -{ - "indices" : [ - { - "names" : [ "*" ], - "privileges" : [ "read" ], - "field_security" : { - "grant" : [ "customer.*" ] - } - } - ] -} --------------------------------------------------- - -You can deny permission to access fields with the following syntax: - -[source,js] --------------------------------------------------- -{ - "indices" : [ - { - "names" : [ "*" ], - "privileges" : [ "read" ], - "field_security" : { - "grant" : [ "*"], - "except": [ "customer.handle" ] - } - } - ] -} --------------------------------------------------- - - -The following rules apply: - -* The absence of `field_security` in a role is equivalent to * access. -* If permission has been granted explicitly to some fields, you can specify -denied fields. The denied fields must be a subset of the fields to which -permissions were granted. -* Defining denied and granted fields implies access to all granted fields except -those which match the pattern in the denied fields. - -For example: - -[source,js] --------------------------------------------------- -{ - "indices" : [ - { - "names" : [ "*" ], - "privileges" : [ "read" ], - "field_security" : { - "except": [ "customer.handle" ], - "grant" : [ "customer.*" ] - } - } - ] -} --------------------------------------------------- - -In the above example, users can read all fields with the prefix "customer." -except for "customer.handle". - -An empty array for `grant` (for example, `"grant" : []`) means that access has -not been granted to any fields. - -===== Field Level Security and Roles - -When a user has several roles that specify field level permissions, the -resulting field level permissions per index are the union of the individual role -permissions. For example, if these two roles are merged: - -[source,js] --------------------------------------------------- -{ - // role 1 - ... - "indices" : [ - { - "names" : [ "*" ], - "privileges" : [ "read" ], - "field_security" : { - "grant": [ "a.*" ], - "except" : [ "a.b*" ] - } - } - ] -} - -{ - // role 2 - ... - "indices" : [ - { - "names" : [ "*" ], - "privileges" : [ "read" ], - "field_security" : { - "grant": [ "a.b*" ], - "except" : [ "a.b.c*" ] - } - } - ] -} --------------------------------------------------- - -The resulting permission is equal to: - -[source,js] --------------------------------------------------- -{ - // role 1 + role 2 - ... - "indices" : [ - { - "names" : [ "*" ], - "privileges" : [ "read" ], - "field_security" : { - "grant": [ "a.*" ], - "except" : [ "a.b.c*" ] - } - } - ] -} --------------------------------------------------- - - -[[document-level-security]] -==== Document level security - -Document level security restricts the documents that users have read access to. -To enable document level security, specify a query that matches all the -accessible documents as part of the indices permissions within a role definition. -Document level security is thus bound to a well defined set of indices. - -Enabling document level security restricts which documents can be accessed from -any document-based read 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. - -The following role definition grants read access only to documents that -belong to the `click` category within all the `events-*` indices: - -[source,js] --------------------------------------------------- -{ - "indices": [ - { - "names": [ "events-*" ], - "privileges": [ "read" ], - "query": "{\"match\": {\"category\": \"click\"}}" - } - ] -} --------------------------------------------------- - -NOTE: Omitting the `query` entry entirely disables document level security for - the respective indices permission entry. - -The specified `query` expects the same format as if it was defined in the -search request and supports the full {es} {ref}/query-dsl.html[Query DSL]. - -For example, the following role grants read access only to the documents whose -`department_id` equals `12`: - -[source,js] --------------------------------------------------- -{ - "indices" : [ - { - "names" : [ "*" ], - "privileges" : [ "read" ], - "query" : { - "term" : { "department_id" : 12 } - } - } - ] -} --------------------------------------------------- - -NOTE: `query` also accepts queries written as string values. - -[[templating-role-query]] -===== Templating a role query - -You can use Mustache templates in a role query to insert the username of the -current authenticated user into the role. Like other places in {es} that support -templating or scripting, you can specify inline, stored, or file-based templates -and define custom parameters. You access the details for the current -authenticated user through the `_user` parameter. - -For example, the following role query uses a template to insert the username -of the current authenticated user: - -[source,js] --------------------------------------------------- -{ - "indices" : [ - { - "names" : [ "my_index" ], - "privileges" : [ "read" ], - "query" : { - "template" : { - "source" : { - "term" : { "acl.username" : "{{_user.username}}" } - } - } - } - } - ] -} --------------------------------------------------- - -You can access the following information through the `_user` variable: - -[options="header"] -|====== -| Property | Description -| `_user.username` | The username of the current authenticated user. -| `_user.full_name` | If specified, the full name of the current authenticated user. -| `_user.email` | If specified, the email of the current authenticated user. -| `_user.roles` | If associated, a list of the role names of the current authenticated user. -| `_user.metadata` | If specified, a hash holding custom metadata of the current authenticated user. -|====== - -You can also access custom user metadata. For example, if you maintain a -`group_id` in your user metadata, you can apply document level security -based on the `group.id` field in your documents: - -[source,js] --------------------------------------------------- -{ - "indices" : [ - { - "names" : [ "my_index" ], - "privileges" : [ "read" ], - "query" : { - "template" : { - "source" : { - "term" : { "group.id" : "{{_user.metadata.group_id}}" } - } - } - } - } - ] -} --------------------------------------------------- - -[[set-security-user-processor]] -===== Set security user ingest processor - -If an index is shared by many small users it makes sense to put all these users -into the same index. Having a dedicated index or shard per user is wasteful. -To guarantee that a user reads only their own documents, it makes sense to set up -document level security. In this scenario, each document must have the username -or role name associated with it, so that this information can be used by the -role query for document level security. This is a situation where the -`set_security_user` ingest processor can help. - -NOTE: Document level security doesn't apply to write APIs. You must use unique -ids for each user that uses the same index, otherwise they might overwrite other -users' documents. The ingest processor just adds properties for the current -authenticated user to the documents that are being indexed. - -The `set_security_user` processor attaches user-related details (such as -`username`, `roles`, `email`, `full_name` and `metadata` ) from the current -authenticated user to the current document by pre-processing the ingest. When -you index data with an ingest pipeline, user details are automatically attached -to the document. For example: - -[source,js] --------------------------------------------------- -PUT shared-logs/log/1?pipeline=my_pipeline_id -{ - ... -} --------------------------------------------------- - -Read the {ref}/ingest.html[ingest docs] for more information -about setting up a pipeline and other processors. - -[[set-security-user-options]] -.Set Security User Options -[options="header"] -|====== -| Name | Required | Default | Description -| `field` | yes | - | The field to store the user information into. -| `properties` | no | [`username`, `roles`, `email`, `full_name`, `metadata`] | Controls what user related properties are added to the `field`. -|====== - -The following example adds all user details for the current authenticated user -to the `user` field for all documents that are processed by this pipeline: - -[source,js] --------------------------------------------------- -{ - "processors" : [ - { - "set_security_user": { - "field": "user" - } - } - ] -} --------------------------------------------------- - [[multiple-roles-dls-fls]] ==== Multiple roles with document and field level security @@ -447,3 +56,6 @@ fields. If you need to restrict access to both documents and fields, consider splitting documents by index instead. + +include::role-templates.asciidoc[] +include::set-security-user.asciidoc[] diff --git a/x-pack/docs/en/security/authorization/role-templates.asciidoc b/x-pack/docs/en/security/authorization/role-templates.asciidoc new file mode 100644 index 0000000000000..1bad73a5d1e94 --- /dev/null +++ b/x-pack/docs/en/security/authorization/role-templates.asciidoc @@ -0,0 +1,71 @@ +[[templating-role-query]] +==== Templating a role query + +When you create a role, you can specify a query that defines the +<>. You can +optionally use Mustache templates in the role query to insert the username of the +current authenticated user into the role. Like other places in {es} that support +templating or scripting, you can specify inline, stored, or file-based templates +and define custom parameters. You access the details for the current +authenticated user through the `_user` parameter. + +For example, the following role query uses a template to insert the username +of the current authenticated user: + +[source,js] +-------------------------------------------------- +POST /_xpack/security/role/example1 +{ + "indices" : [ + { + "names" : [ "my_index" ], + "privileges" : [ "read" ], + "query" : { + "template" : { + "source" : { + "term" : { "acl.username" : "{{_user.username}}" } + } + } + } + } + ] +} +-------------------------------------------------- +// CONSOLE + +You can access the following information through the `_user` variable: + +[options="header"] +|====== +| Property | Description +| `_user.username` | The username of the current authenticated user. +| `_user.full_name` | If specified, the full name of the current authenticated user. +| `_user.email` | If specified, the email of the current authenticated user. +| `_user.roles` | If associated, a list of the role names of the current authenticated user. +| `_user.metadata` | If specified, a hash holding custom metadata of the current authenticated user. +|====== + +You can also access custom user metadata. For example, if you maintain a +`group_id` in your user metadata, you can apply document level security +based on the `group.id` field in your documents: + +[source,js] +-------------------------------------------------- +POST /_xpack/security/role/example2 +{ + "indices" : [ + { + "names" : [ "my_index" ], + "privileges" : [ "read" ], + "query" : { + "template" : { + "source" : { + "term" : { "group.id" : "{{_user.metadata.group_id}}" } + } + } + } + } + ] +} +-------------------------------------------------- +// CONSOLE \ No newline at end of file diff --git a/x-pack/docs/en/security/authorization/set-security-user.asciidoc b/x-pack/docs/en/security/authorization/set-security-user.asciidoc new file mode 100644 index 0000000000000..92b9ae275aec8 --- /dev/null +++ b/x-pack/docs/en/security/authorization/set-security-user.asciidoc @@ -0,0 +1,61 @@ +[[set-security-user-processor]] +==== Pre-processing documents to add security details + +// If an index is shared by many small users it makes sense to put all these users +// into the same index. Having a dedicated index or shard per user is wasteful. +// TBD: It's unclear why we're putting users in an index here. + +To guarantee that a user reads only their own documents, it makes sense to set up +document level security. In this scenario, each document must have the username +or role name associated with it, so that this information can be used by the +role query for document level security. This is a situation where the +`set_security_user` ingest processor can help. + +NOTE: Document level security doesn't apply to write APIs. You must use unique +ids for each user that uses the same index, otherwise they might overwrite other +users' documents. The ingest processor just adds properties for the current +authenticated user to the documents that are being indexed. + +The `set_security_user` processor attaches user-related details (such as +`username`, `roles`, `email`, `full_name` and `metadata` ) from the current +authenticated user to the current document by pre-processing the ingest. When +you index data with an ingest pipeline, user details are automatically attached +to the document. For example: + +[source,js] +-------------------------------------------------- +PUT shared-logs/log/1?pipeline=my_pipeline_id +{ + ... +} +-------------------------------------------------- +// NOTCONSOLE + +For more information about setting up a pipeline and other processors, see +{ref}/ingest.html[ingest node]. + +[[set-security-user-options]] +.Set Security User Options +[options="header"] +|====== +| Name | Required | Default | Description +| `field` | yes | - | The field to store the user information into. +| `properties` | no | [`username`, `roles`, `email`, `full_name`, `metadata`] | Controls what user related properties are added to the `field`. +|====== + +The following example adds all user details for the current authenticated user +to the `user` field for all documents that are processed by this pipeline: + +[source,js] +-------------------------------------------------- +{ + "processors" : [ + { + "set_security_user": { + "field": "user" + } + } + ] +} +-------------------------------------------------- +// NOTCONSOLE \ No newline at end of file