Defining Document Permissions for Custom Sources

The following guide applies to Custom Sources. For more information on Custom Sources, visit the Custom sources API guide.

Document-level permissions are used to manage access to various pieces of content based on an individual’s or team’s attributes. A user may be allowed or denied access to certain documents, and when properly implemented, the returned results respect the varying degrees of authorization. Document-level permissions are also known as, or derived from Access Control Lists (ACLs).

Workplace Search’s document-level permissions are early-bound (e.g. applied at index time).

When reasoning about document-level permissions for Custom Sources, there are two key parts to consider:

  1. Adding a _allow_permissions or _deny_permissions field value to your Custom Source documents
  2. Adding matching permission attributes for a given user

Defining document-level permissions

Let’s start with a simple document:

{
  "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 document consists of six (6) content fields. From here, we want to add granular, user-level control information, which will allow us to restrict who gets to see this result. We can accomplish this using the document-level permission attributes:

{
  "_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 arbitrary strings.

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 searching for this document immediately, we wouldn’t find it. Why? A user or group of users must first be mapped to this permission value. In other words: permission1 is now required to view the document.

We can map permission1 to a user or group of users with the Permissions API.

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

For detailed information about the Permissions API, head to the Document permissions for Custom Sources.

The Workplace Search user must have been created via Workplace Search itself (known as Standard Authentication) or through the Elasticsearch Native Realm.

Let’s recap: we can assign any arbitrary value to the _allow_permissions and _deny_permissions arrays, for any Custom Source document. Once a user has been assigned a permission value, it can be reused across documents in the Custom Source itself.


Let’s now provide a value for _deny_permissions:

{
  "_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"
}

A user assigned both permission1 and permission2 would not have access to the document, because the permission2 deny rule takes precedence.

Deny rules take precedence over allow rules.

Let’s add the permission2 permission to our user. This time, we can update the user data directly by using it’s ID when posting to the Permissions endpoint.

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

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

The Permissions endpoint supports partial updates. Providing new document-level permission mappings for users will not override the previously established ones.

With these changes applied, documents with the permission2 attributes will not be returned for [USER_NAME].

Read the Document permissions for Custom Sources to learn more about the Document Permissions endpoint.