Link Search Menu Expand Document Documentation Menu

You're viewing version 1.2 of the OpenSearch documentation. This version is no longer maintained. For the latest version, see the current documentation. For information about OpenSearch version maintenance, see Release Schedule and Maintenance Policy.

Document-level security

Document-level security lets you restrict a role to a subset of documents in an index. The easiest way to get started with document- and field-level security is open OpenSearch Dashboards and choose Security. Then choose Roles, create a new role, and review the Index permissions section.

Document- and field-level security screen in OpenSearch Dashboards

Simple roles

Document-level security uses the OpenSearch query DSL to define which documents a role grants access to. In OpenSearch Dashboards, choose an index pattern and provide a query in the Document level security section:

{
  "bool": {
    "must": {
      "match": {
        "genres": "Comedy"
      }
    }
  }
}

This query specifies that for the role to have access to a document, its genres field must include Comedy.

A typical request to the _search API includes { "query": { ... } } around the query, but in this case, you only need to specify the query itself.

In the REST API, you provide the query as a string, so you must escape your quotes. This role allows a user to read any document in any index with the field public set to true:

PUT _plugins/_security/api/roles/public_data
{
  "cluster_permissions": [
    "*"
  ],
  "index_permissions": [{
    "index_patterns": [
      "pub*"
    ],
    "dls": "{\"term\": { \"public\": true}}",
    "allowed_actions": [
      "read"
    ]
  }]
}

These queries can be as complex as you want, but we recommend keeping them simple to minimize the performance impact that the document-level security feature has on the cluster.

Parameter substitution

A number of variables exist that you can use to enforce rules based on the properties of a user. For example, ${user.name} is replaced with the name of the current user.

This rule allows a user to read any document where the username is a value of the readable_by field:

PUT _plugins/_security/api/roles/user_data
{
  "cluster_permissions": [
    "*"
  ],
  "index_permissions": [{
    "index_patterns": [
      "pub*"
    ],
    "dls": "{\"term\": { \"readable_by\": \"${user.name}\"}}",
    "allowed_actions": [
      "read"
    ]
  }]
}

This table lists substitutions.

Term Replaced with
${user.name} Username.
${user.roles} A comma-separated, quoted list of user roles.
${attr.<TYPE>.<NAME>} An attribute with name <NAME> defined for a user. <TYPE> is internal, jwt, proxy or ldap

Attribute-based security

You can use roles and parameter substitution with the terms_set query to enable attribute-based security.

Note that the security_attributes of the index need to be of type keyword.

User definition

PUT _plugins/_security/api/internalusers/user1
{
  "password": "asdf",
  "backend_roles": ["abac"],
  "attributes": {
    "permissions": "\"att1\", \"att2\", \"att3\""
  }
}

Role definition

PUT _plugins/_security/api/roles/abac
{
  "index_permissions": [{
    "index_patterns": [
      "*"
    ],
    "dls": "{\"terms_set\": {\"security_attributes\": {\"terms\": [${attr.internal.permissions}], \"minimum_should_match_script\": {\"source\": \"doc['security_attributes'].length\"}}}}",
    "allowed_actions": [
      "read"
    ]
  }]
}