Some tips when implementing find grained code execution security in MarkLogic Server…
You may be familiar with my MarkLogic Workflow library. This is being used in production in some customers. In order to gain wider adoption though I need to open up the API to non-administrative users.
So I decided to add a set of execute privileges, workflow specific roles, and security assertions in my code. Sounds simple – but there are a few things to consider.
Firstly, all users are deemed evil until permissions say otherwise. And rightly so. Those darn users. Thus you can’t even see a REST extension or dependant library until those pieces of code themselves have had a read permission added.
You also need the execute privilege when wanting to run those files, not just a read permission. Makes sense of course, but you need both read and execute – one is not enough!
REST extensions are also a funny beast. As a convenience, a simple REST extension that doesn’t call any libraries can happily be executed by anyone with a role that includes the rest-extension-user privilege.
BUT if you want that extension to call a library, you need to all of a sudden ensure that user’s role has execute and read permissions explicitly on that REST extension too – even if you DO have this privilege on the library files you are calling! This bit me in the bottom today, so I thought I’d write it down here.
In summary, to lock down a library you need to:-
- Create a set of privileges for your code – I have workflow-designer, workflow-user, workflow-instantiator, workflow-administrator, workflow-monitor and workflow-manager privileges. Each of these belongs to a role too, which also inherits rest-reader, rest-writer and rest-extension-user roles.
- Create at least one role per privilege. Some roles may have multiple privileges, and privileges may be assigned to more than one role.
- Create at least one user per role. This enables you to test them later.
- If only particular roles can create particular URIs, create a set of uri privileges too. I have workflow-designer-uri and workflow-instantiator-uri URI privileges. These are assigned to the roles of the same name.
- Use security-assert in your code – using the privilege URI (the one that usually has http:// in it, not the short name) within each function that should be executed only by those users with one or more privileges. The function takes an array of privilege names. Use this form here: http://docs.marklogic.com/xdmp:security-assert (There is a docs bug in the security guide which incorrectly uses the short name – only ever use the long name as in this link)
- Upload you modules and install your rest extensions
- Go through all your relevant MYAPP-modules database code XQY or SJS files and add BOTH a read AND execute permission for each role that can ‘see’ any part of each library module OR rest extension module (these are confusingly installed as /marklogic.rest.resource/MYEXTENSIONNAME/assets/resource.xqy
- Now thoroughly test your REST extensions using curl or some other tool with both admin calls (to ensure it functionally works) and calls using test users for each of the new roles and privileges you have created.
All should now be well. I may add another post as I go through security testing and discover more best practice.