Incapture Technologies

Inside the Cloud

Incapture Technologies Blog

 

Entitlements in Practice

Published:
June 21, 2016
Author:

Building from an earlier blog post which provides conceptual grounding on entitlements, this post provides some practical examples of how to implement entitlements in Rapture.

Overview

Entitlements in Rapture allow administrators to clearly define who can access what in Rapture.  It is a permissioning system based on users, groups, and entitlements.  API calls made to Rapture are protected by entitlements that are defined at compile-time.  A defined entitlement is associated with a number of groups of users, and this association can be made at run-time.

Concepts/Terminology

User – A user represents a person who is making calls to Rapture or an application that is making calls to Rapture. A user is a single entity with a username/password who needs access to Rapture.
Group – A group represents a collection of users.
Entitlement – An entitlement is a named permission that has associated with it 0 or more groups. If an entitlement has no groups associated with it, it is essentially open and any defined user in Rapture can access it. If an entitlement has at least 1 group associated with it, any user wishing to access the resource protected by this entitlement, must be a member of one of the associated groups.

Example

The use of entitlements is best explained by using a simple example.

User “bob” is a defined user in Rapture.  He writes a Reflex script to update the description associated with his username in Rapture.  Thus, he wants to use the updateMyDescription API call.

#user.updateMyDescription("My name is Bob");

He is successful.  What happened underneath the hood?

Let’s first examine how updateMyDescription is defined in the user.api file in the RaptureNew/ApiGen project.  Every API call in Rapture has a defined entitlement associated with it.

[Update the current description for a user.]
@entitle=/user/write/$u
@public RaptureUser updateMyDescription(String description);

The entitlement string for the updateMyDescription call is defined as “/user/write”.  Entitlements are always defined as hierarchical slashed strings with an optional wildcard.  This means if a user has permissions for /user he will be permissioned for entitlements /user/read and /user/write/ as well.  If a user has permission for /user/xxx, that does not mean has has permissions for /user/yyy, but he does have permissions for /user/xxx/yyy.

On startup, a brand new Rapture instance always creates every single entitlement possible (by scanning every single *.api file) and initializes it as empty.  This means any defined user has permissions to all entitlements on startup of a clean brand-new Rapture instance.  Using the Entitlements API, users can then be added to groups, and groups can then be associated with particular entitlements to control access.  These definitions and associations are persisted to the configuration repository.

Back to our example.  Assuming that “bob” executed that api call against a brand new instance of Rapture, the entitlement of “/user/write” would have had 0 groups associated with it.  The entitlement check would have passed, since remember, an entitlement with 0 associated groups is wide-open to all defined users in Rapture.  How do we make it not pass?  We have to use the Entitlements API to associate a group of users with the entitlement “/user/write”.

#entitlement.addEntitlementGroup("groupThatHasAccessToUserWrite");
#entitlement.addUserToEntitlementGroup("groupThatHasAccessToUserWrite", "alice");
#entitlement.addGroupToEntitlement("/user/write", "groupThatHasAccessToUserWrite");

Notice above that only the user “alice” has been assigned to the group “groupThatHasAccessToUserWrite”.  That group was associated with the “/user/write” entitlement.  User “bob” is not a member of that group.  Therefore, if Bob were to execute his call again after the above changes were made, it would fail.  In order for Bob to be able to make that call, he would have to be added to that group using the Entitlements API.

Dynamic Entitlements

Dynamic entitlements are entitlements with a wildcard in the string, such as /user/put/$d.  The wildcard is substituted at runtime based on the argument(s) of the API call that is made.  This allows Rapture to define entitlements that are based on the actual arguments of the API call being made.  Here is a table showing the currently defined substitutions:

Wildcard
Substituted With
$d documentPath
$a authority
$f full path (i.e. authority/documentPath)
$u current_user

Another Example

User “bob” wants to read a document out of Rapture.  Thus, he writes a Reflex script to use the getContent API call, which has the following definition:

[Retrieve the content for a document.]
@entitle=/data/read/$f(docURI)
@public String getContent(String docURI);

Bob’s Reflex script:

#user.getContent("//myauthority/alicesDocs/doc");

The $f in this entitlement gets substituted such that Bob’s entitlement request looks like the following:

“/data/read/myAuthority/alicesDocs/doc”

The entitlement system will check if Bob is member of the group associated with that entitlement.  For the sake of this example, let’s assume that Alice had previously created an entitlement “/data/read/myAuthority/alicesDocs/doc” with a group with just her username included.  She basically wanted an area that she can keep private.  This means Bob’s call will fail.  He is not a member of the group associated with the entitlement “/data/read/myAuthority/alicesDocs/doc”.

The wildcard substitutions defined above are based on the Rapture URI argument that is passed into the call.  The values of documentPath, partition, and authority are all components of a RaptureURI object.  At this point, it only makes sense to use dynamic entitlements with API calls that have a RaptureURI string as an argument.


Subscribe for updates