Skip to main content

Securing MarkLogic Server

Overlapping Protected Paths

Consider a more complex case with multiple paths matching the same node. Suppose you have a document like this:

<root>
  <foo a=1 b=2 c=3>Hello</foo>
</root>

It is possible to define three different protected paths that all match the foo element, overlapping each other:

sec:protect-path("/root/foo[@a=1]", (), (xdmp:permission("els-role-1", "read")))
sec:protect-path("/root/foo[@b=2]", (), (xdmp:permission("els-role-2", "read")))
sec:protect-path("/root/foo[@c=3]", (), (xdmp:permission("els-role-3", "read")))

MarkLogic Server will still create just one term for “Hello”, which is the combination of the word and the query rolesets ((“els-role-1”),(“els-role-2”),(“els-role-3”)).

As a side note, in the above example the query rolesets is ((“els-role-1”),(“els-role-2”),(“els-role-3”)), which is different from simply (“els-role-1”,“els-role-2”,“els-role-3”).

Note

In MarkLogic Server 9.0-2 query rolesets have been simplified and optimized. Existing documents with query rolesets configured in 9.0-1 will still be protected in 9.0-2. To take advantage of the optimization however, you need to reindex your documents and regenerate your query rolesets using the helper functions (APIs for Element Level Security). It is highly recommended that you reindex any protected documents already in your database and regenerate your query rolesets, since documents may be reindexed by another operation, which may cause a mismatch between the documents and the query rolesets. See Algorithm That Determines Which Query Rolesets to Use for examples and more details.

This is what the query rolesets hierarchy looks like for ((“els-role-1”),(“els-role-2”),(“els-role-3”)); three query rolesets and three roles:

Diagram of query rolesets hierarchy with three query rolesets and three roles

This is what the query rolesets hierarchy looks like for (“els-role-1”,“els-role-2”,“els-role-3”); one query roleset and three roles:

Diagram of query rolesets hierarchy with one query roleset and three roles

If you only have one protected path that matches foo in the above example but with three roles, like this:

sec:protect-path("//foo", (), (
xdmp:permission("els-role-1", "read"),
xdmp:permission("els-role-2", "read"), 
xdmp:permission("els-role-3", "read")))

Then (“els-role-1”,“els-role-2”,“els-role-3”) would be the proper query roleset to use. To configure the former ((“els-role-1”),(“els-role-2”),(“els-role-3”)), you would call:

(:run against the Security database :)
xquery version "1.0-ml";
import module namespace sec="http://marklogic.com/xdmp/security" 
  at "/MarkLogic/security.xqy";
  
let $roleset1 := sec:query-roleset(("els-role-1"))
let $roleset2 := sec:query-roleset(("els-role-2"))
let $roleset3 := sec:query-roleset(("els-role-3"))
return sec:add-query-rolesets(sec:query-rolesets(($roleset1,$roleset2,$roleset3)))

To configure the latter (“els-role-1”,“els-role-2”,“els-role-3”), you can simply call:

(:run against the Security database :)
xquery version "1.0-ml";
import module namespace sec="http://marklogic.com/xdmp/security" 
  at "/MarkLogic/security.xqy";
  
let $roleset1 := sec:query-roleset(("els-role-1","els-role-2","els-role-3"))
return
sec:add-query-rolesets(sec:query-rolesets($roleset1))

When you are starting to configure and use element level security, the two query rolesets helper functions, xdmp:database-node-query-rolesets() and xdmp:node-query-rolesets() can simplify the process of setting up your query rolesets. These functions can be used for configuring query rolesets either for documents in the database, or for documents during ingestion. See Helper Functions for Query Rolesets for more information.