Skip to main content

Securing MarkLogic Server

Example—Introducing Roles, Users, and Execute Privileges

Consider a simple scenario with two roles: engineering and sales. The engineering role is responsible for making widgets and has privileges needed to perform activities related to making widgets. The sales role is responsible for selling widgets and has privileges to perform activities related to selling widgets.

To begin, create two roles in MarkLogic Server named engineering and sales respectively.

The engineering role needs to be able to make widgets. You can create an execute privilege with the name make-widget, and action URI http://widget.com/make-widget to represent that privilege. The sales role needs to sell widgets, so you create an execute privilege with the name sell-widget and action URI http://widget.com/sell-widget to represent that privilege.

Note

Names for execute privileges are used only as display identifiers in the Admin Interface. The action URIs are used within XQuery or JavaScript code to identify the privilege.

Ron is an engineer in your company, so you create a user for Ron and assign the engineering role to the newly created user. Emily is an account representative, so you create a user for Emily and assign her the sales role.

In your XQuery code, use the xdmp:security-assert() function to ensure that only engineers make widgets and only account representatives sell widgets (if you are using JavaScript, you can similarly call xdmp.securityAssert() in your JavaScript function to protect the code). For example:

xquery version "1.0-ml"
define function make-widget(...) as ...
{
  xdmp:security-assert("http://widget.com/make-widget",
     "execute"), make widget...}

If Ron is logged into the application and executes the make-widget() function, xdmp:security-assert("http://widget.com/make-widget", "execute") succeeds since Ron is of the engineering role which has the execute privilege to make widgets.

If Emily attempts to execute the make-widget() function, the xdmp:security-assert() function call throws an exception. You can catch the exception and handle it with a try/catch in the code. If the exception is not caught, the transaction that called this function is rolled back.

Some functions are common to several protected actions. You can protect such a function with a single xdmp:security-assert() call by providing the appropriate action URIs in a list. For example, if a user needs to execute the count-widgets() function when making or selling widgets, you might protect the function as follows:

xquery version "1.0-ml"
define function count-widgets(...) as ...
{
  xdmp:security-assert( ("http://widget.com/make-widget", 
            "http://widget.com/sell-widget"), "execute"),
  count-widget...
}

If there is a function that requires more than one privilege before it can be performed, place the xdmp:security-assert() calls sequentially. For example, if you need to be a manager in the sales department to give discounts when selling the widgets, you can protect the function as follows:

xquery version "1.0-ml"
define function discount-widget(...) as ...
{
  xdmp:security-assert( "http://widget.com/sell-widget",
    "execute"),
  xdmp:security-assert( "http://widget.com/change-price",
    "execute"),
  discount widget...
}

where http://widget.com/change-price is an action URI for a change-price execute privilege assigned to the manager role. A user needs to have the sales role and the manager role, which provides the user with the sell-widget and change-price execute privileges, to be able to execute this function.