[DOCS] Creates field and document level security overview (#30937)

This commit is contained in:
Lisa Cawley 2018-06-21 10:08:50 -07:00 committed by GitHub
parent 872418ff94
commit bd06563e78
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 140 additions and 396 deletions

View File

@ -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.
<<field-level-security,Field level security permissions>> restrict access to
particular fields within a document.
<<document-level-security,Document level security permissions>> 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 <<multiple-roles-dls-fls>>.
=====================================================================
[[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
<<document-level-security, documents>>).
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[]

View File

@ -0,0 +1,71 @@
[[templating-role-query]]
==== Templating a role query
When you create a role, you can specify a query that defines the
<<document-level-security,document level security permissions>>. 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

View File

@ -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