mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-17 10:25:15 +00:00
[DOCS] Creates field and document level security overview (#30937)
This commit is contained in:
parent
872418ff94
commit
bd06563e78
@ -3,9 +3,11 @@
|
|||||||
=== 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
|
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
|
security permissions to a role.
|
||||||
to particular fields within a document. Document level security permissions
|
<<field-level-security,Field level security permissions>> restrict access to
|
||||||
restrict access to particular documents within an index.
|
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
|
NOTE: Document and field level security is currently meant to operate with
|
||||||
read-only privileged accounts. Users with document and field level
|
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>>.
|
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-dls-fls]]
|
||||||
==== Multiple roles with document and field level security
|
==== 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
|
If you need to restrict access to both documents and fields, consider splitting
|
||||||
documents by index instead.
|
documents by index instead.
|
||||||
|
|
||||||
|
include::role-templates.asciidoc[]
|
||||||
|
include::set-security-user.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
|
||||||
|
<<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
|
@ -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
|
Loading…
x
Reference in New Issue
Block a user