search mobile facets autocomplete spellcheck crawler rankings weights synonyms analytics engage api customize documentation install setup technology content domains user history info home business cart chart contact email activate analyticsalt analytics autocomplete cart contact content crawling custom documentation domains email engage faceted history info install mobile person querybuilder search setup spellcheck synonyms weights engage_search_term engage_related_content engage_next_results engage_personalized_results engage_recent_results success add arrow-down arrow-left arrow-right arrow-up caret-down caret-left caret-right caret-up check close content conversions-small conversions details edit grid help small-info error live magento minus move photo pin plus preview refresh search settings small-home stat subtract text trash unpin wordpress x alert case_deflection advanced-permissions keyword-detection predictive-ai sso

Document Permissions Guide

Supported authentication modes: standard, elasticsearch-native.

Enterprise Search provides document level security via Elasticsearch.

Document level security restricts which documents a user is able to return in search results.

There are two key parts:

  1. Adding an _allow_permissions or _deny_permissions field value to your Custom API Source schema.
  2. Adding matching permissions for a given user.

Let's start with part 1: the schema to which your Custom API Source documents belong.

Maybe your document looks like this:

{
  "id" : 1234,
  "title" : "The Meaning of Life",
  "body" : "Be kind to others.",
  "url" : "https://example.com",
  "created_at": "2019-06-01T12:00:00+00:00",
  "type": "list"
}

The schema contains 6 informational fields.

But we want granular, user-level control over who can return each document.

We'll now consider two new reserved fields to help us accomplish this:

{
  "_allow_permissions": [],
  "_deny_permissions": [],
  "id" : 1235,
  "title" : "The Meaning of Time",
  "body" : "Not much. It is a made up thing.",
  "url" : "https://example.com",
  "created_at": "2019-06-01T12:00:00+00:00",
  "type": "list"
}

Our two new arrays, _allow_permissions and _deny_permissions, can hold a grouping of any strings.

What if we do not want someone to be able to view a document? Or have only certain people view a document?

There are two parts: (1) update the document with a permission and (2) reflect that permission within the user.

First, we add permission1 to _allow_permissions for a given document:

{
  "_allow_permissions": ["permission1"],
  "_deny_permissions": [],
  "id" : 1235,
  "title" : "The Meaning of Sleep",
  "body" : "Rest, recharge, and connect to the Ether.",
  "url" : "https://example.com",
  "created_at": "2019-06-01T12:00:00+00:00",
  "type": "list"
}

If we tried to search for this document, we wouldn't find it.

Why? The users are missing permission1!

In other words: permission1 is now required to view the document.

We can add permission1 to a user with the Enterprise Search Permissions API:

curl -X POST http://localhost:3002/api/v1/ent/sources/[CONTENT_SOURCE_KEY]/permissions \
-H "Authorization: Bearer [ACCESS_TOKEN]" \
-H "Content-Type: application/json" \
-d '{
  "user": "[USER_NAME]"
  "permissions": ["permission1"]
}'

The Enterprise Search user might have been created via Enterprise Search itself or through the Elasticsearch native realm.

Either way, let's recap.

We can assign any arbitrary value to the _allow_permissions and _deny_permissions arrays per document.

And then we can replicate that arbitrary value within the permissions array of a user to grant or deny access.

It's simple! But people may trip up on the flexibility of the permission values, for which we've used permission1 in the example.

Now when [USER_NAME] tries to search for document 1235 it will return in the search results.

And what if we to decide to provide a value for _deny_permissions? Like so:

{
  "_allow_permissions": ["permission1"],
  "_deny_permissions": ["permission2"],
  "id" : 1235,
  "title" : "The Meaning of Sleep",
  "body" : "Rest, recharge, and connect to the Ether.",
  "url" : "https://example.com",
  "created_at": "2019-06-01T12:00:00+00:00",
  "type": "list"
}

If the user searchers for the document it will not be returned if the user holds permission2.

Deny rules take precedence over allow rules.

So if a user holds both permission1 and permission2, the deny rule, permission2, will take precedence.

Let's add the permission to our user.

We'll put the user name in the request URL and the new permission in the request body.

When we hit the add endpoint, we'll add a new permission atop the existing:

curl -X POST http://localhost:3002/api/v1/ent/sources/[CONTENT_SOURCE_KEY]/permissions/[USER_NAME]/add \
-H "Authorization: Bearer [ACCESS_TOKEN]" \
-H "Content-Type: application/json" \
-d '{
  "permissions": ["permission2"]
}'

Returns...

{
  "user": "[USER_NAME]",
  "permissions": [
    "permission1",
    "permission2"
  ]
}

When [USER_NAME] tries to search, the documents with permission2 under _deny_permissions will not return.

You can apply these new fields and this logic to your documents to develop granular and comprehensive document level access control.

Enjoy the security. Be careful when editing user permissions, lest you assign the wrong things to the wrong people!

Read the Document Permissions API Reference to learn more about the endpoint.


Enjoying the beta? Something broken? Lost? Please send us your feedback or visit the Enterprise Search community.