Link to slides for a related presentation, A Practical Guide To Role Engineering, JavaOne conference, October 27, 2015.
Link to GitHub project corresponding to this topic: role-engineering-sample
The Role engineering process takes us from a human readable policy syntax to what is loaded into an rbac engine and used by a given application or system.
Here we follow the ANSI RBAC (INCITS 359) spec which prescribes methods like:
- addRole, addInheritance, createDsdSet, addPermission, grantPermission for policy adds
- createSession and checkAccess for policy enforcement
This tutorial demonstrates role engineering techniques using standard rbac as applied to a sample set of security use cases.
There is a corresponding github project, written in Java that uses Apache Fortress to show how:
1. Define Security Use Cases for the Application
sample use case:
First we’ll describe the policies in a way humans can understand by writing them down as use cases translated from the diagram.
Use case definitions:
[ legend: red – roles | blue – objects | green – operations ]
use case #1 : User must authenticate before landing on the home page.
Every set of security use cases necessarily contains a logon step. With rbac, it implies a call to the createSession api, where credentials are checked and roles activated.
use case #2 : User must be a Buyer before placing bid on auction or buying an item.
A role named ‘Buyers’ is granted rights to place bids and purchase auction items. This use case requires a call to the checkAccess api which we’ll discuss later.
use case #3 : User must be a Seller to create an auction or ship an item purchased.
We add role ‘Sellers’, and grant the authority to create an auction and ship an item that has just been sold.
use case #4 : All Users may create an account and search items.
Another role, named ‘Users’, is granted the rights to create a new account and search a list of items up for auction. It will be a base role that Buyers and Sellers both extend.
use case #5 : A particular user may be a Buyer, or a Seller, but never both simultaneously.
An interesting scenario to consider. Perhaps a conflict of interest due to how they collide. Not to worry, document and move on.
2. Define the Roles in the App
The use cases must now be converted into entity lists. Though still human readable, the new data formats are aligned with RBAC.
Create a list of Role names. Use names pulled from use cases 2, 3, and 4.
- role name: “Users” description: “Basic rights for all buyers and sellers”
- role name: “Buyers” description: “May bid on and purchase items”
- role name: “Sellers” description: “May setup auctions and ship items”
Buyers and Sellers inherit from Users as described in use case #4.
Add Role Inheritance Relationships
- child name: “Buyers” parent name: “Users“
- child name: “Sellers” parent name: “Users“
Don’t forget the role combination rule in use case #5:
Role Activation Constraint
- role name: “Buyers“
- role name: “Sellers“
- type: “DYNAMIC“
- cardinality: “2“
3. Define the Resources and Operations
RBAC Permissions are mappings between objects and operations. Here we list the perms described in use cases 2, 3 and 4.
- object name: “Item” description: “This is a product that is available for purchase”
- operation name: “search” description: “Search through list of items”
- operation name: “bid” description: “Place a bid on a given product”
- operation name: “buy” description: “Purchase a given product”
- operation name: “ship” description: “Ships a given product after sale”
- object name: “Auction” description: “Controls a particular online auction”
- operation name: “create” description: “May start a new auction”
- object name: “Account” description: “Each user must have one of these”
- operation name: “create” description: “Ability to setup a new account”
4. Map the Roles to the Resources and Operations
Get the list of grants. Again, these mappings naturally derive from the use cases.
Grant Permissions to Roles:
- role: “Buyers” object name: “Item” oper: “bid“
- role: “Buyers” object name: “Item” oper: “buy“
- role: “Sellers” object name: “Item” oper: “ship“
- role: “Sellers” object name: “Auction” oper: “create“
- role: “Users” object name: “Item” oper: “search“
- role: “Users” object name: “Account” oper: “create“
5. Create the RBAC policy load file
Hand to the analyst, trained in the particulars of the RBAC engine, the entity lists created in steps 2, 3 and 4. That info will be hand keyed into graphical interface screen, or (better yet) translated to machine readable syntax and loaded automatically by recurrent batch job.
role-engineering-sample-security-policy.xml – download from github.
... <addrole> <role name="Role_Users" description=“Base Role for Buyers and Sellers"/> <role name="Role_Buyers" description="May bid on and purchase products"/> <role name="Role_Sellers" description="May start auctions and ship items"/> </addrole> <addroleinheritance> <relationship child="Role_Buyers" parent="Role_Users"/> <relationship child="Role_Sellers" parent="Role_Users"/> </addroleinheritance> <addpermgrant> <permgrant objName="SellersPage" opName="link" roleNm="Role_Sellers"/> <permgrant objName="BuyersPage" opName="link" roleNm="Role_Buyers"/> <permgrant objName="Item" opName="bid" roleNm="Role_Buyers"/> <permgrant objName="Item" opName="buy" roleNm="Role_Buyers"/> <permgrant objName="Item" opName="ship" roleNm="Role_Sellers"/> <permgrant objName="Auction" opName="create" roleNm="Role_Sellers"/> <permgrant objName="Item" opName="search" roleNm="Role_Users"/> <permgrant objName="Account" opName="create" roleNm="Role_Users"/> </addpermgrant> <addsdset> <sdset name="BuySel" setmembers="Role_Buyers,Role_Sellers" cardinality="2“ setType="DYNAMIC" description="Cannot activate both at once."/> </addsdset> <addpermobj> <permobj objName="Item" description=“..." ou="p1" /> <permobj objName="Auction" description=“..." ou="p1" /> <permobj objName="Account" description=“..." ou="p1" /> </addpermobj> <addpermop> <permop objName="Item" opName="bid" description="Bid on a given product"/> <permop objName="Item" opName="buy" description="Purchase a given product"/> <permop objName="Item" opName="ship" description="Place a product up for sale"/> <permop objName="Item" opName="search" description="Search through item list"/> <permop objName="Auction" opName="create" description="May start a new auction"/> <permop objName="Account" opName="create" description="Ability to add a new account"/> </addpermop> ...
At the completion of this step, the RBAC policy is loaded into the engine and ready for use.
6. Add Permission Checks to Application
It’s time to get the developers involved because there will be code that looks (something) like this:
RbacSession session = getSession(); Permission permission = new Permission( "Item", "bid" ); return accessMgr.checkAccess( session, permission );
How to instrument the checks is up to you. Obviously you won’t hard code the perms. Observe proper isolation to decouple your app from the details of the underlying security system. Favor declarative checks over programmatic. The usual concerns.
A previous post offers ideas, if willing to get dirty hands 🙂
Apache Fortress End-to-End Security Tutorial
7. Assign Roles to the Users
Before users may access the app, they must be assigned one or more of the corresponding roles. These relationships may be recorded into the RBAC datastore with a batch script (as below), but often times performed by GUI, e.g. during application enrollment.
Sample user to role assignment policy file
... <adduserrole> <userrole userId="johndoe" name="Role_Buyers"/> <userrole userId="johndoe" name="Role_Sellers"/> <userrole userId="johndoe" name="Super_Users"/> <userrole userId="ssmith" name="Role_Buyers"/> <userrole userId="rtaylor" name="Role_Sellers"/> </adduserrole> ...
The following diagram depicts the role to role and user to role relationships defined by this policy.
RBAC Extra Credit
A. What happens when johndoe signs on?
(Will both roles be activated into the RBAC session?)
No, one of the roles must be discarded due to SoD constraint.
begin johndoe logon trace using fortress console
Enter userId: johndoe name :Sellers msg :validate userId [johndoe] failed activation of assignedRole [Sellers] validates DSD Set Name:BuySel Cardinality:2
RBAC allows the caller to select one or more roles during createSession. So we may call with johndoe passing either of their assigned roles in the argument list. This process is called selective role activation. Thus John Doe may be a Buyer during one session and Seller the next, never both at once.
more on createSession:
Session createSession(User user, boolean isTrusted) throws SecurityException
The following attributes may be set when calling this method
User.roles– This is where you list role names for activation. Default is all assigned roles will be attempted.
B. What if we want to prevent someone from being assigned both roles?
Use Static Separation of Duties instead
... <addsdset> <sdset name="BuySel" setmembers="Role_Buyers,Role_Sellers" cardinality="2“ setType="STATIC" description="Cannot assign both to one user." /> </addsdset> ...
What happens now when we try to assign a user both roles?
begin assignUser trace in fortress console
Enter userId: janedoe Enter role name: sellers ERROR: assignUser failed SSD check, rc=5088 Role [sellers], SSD Set Name [buysel2], Cardinality:2
Remember, constraints applied at role…
- assignment time: are Static Separation of Duties (SSD)
- activation time: are Dynamic Separation of Duties (DSD)
C. What perms will a Buyer get?
When a user activates the Buyers role what perms will they have?
begin ssmith perm trace using fortress console
**perm:1*** object name [Account] operation name [create] **perm:2*** object name [Item] operation name [search] **perm:3*** object name [Item] operation name [buy] **perm:4*** object name [Item] operation name [bid]
D. What about a Seller?
When a user activates the Sellers role what perms will they have?
begin rtaylor perm trace using fortress console
**perm:1*** object name [Account] operation name [create] **perm:2*** object name [Item] operation name [search] **perm:3*** object name [Auction] operation name [create] **perm:4*** object name [Item] operation name [ship]
E. Why do Buyers and Sellers have common perms?
Notice that Buyers and Sellers both have access rights to Account.create and Item.search. The reason is both extend a common base role: Users.
F. The above use case is overly simplistic. Can we do something more realistic?
The Apache Fortress End-to-End Security Tutorial delves into fine-grained access control of data tied to customers. It demonstrates how to implement a complicated set of requirements, verified with automated selenium test cases.
Not sure if this blog topic is still alive, but I’ll give it a try.
First, very nicely done on this write-up of how to apply RBAC to a system…thanks.
Any thought on how one might go about using this model to populate “instance” data like the following:
-I have a notion of “Account” like “Spacely Sprockets” and “Cogswell Cogs”
-I have a notion of a “Team Member” Role which controls permissions for what can be done on an Account
-User “John” has the “Team Member” Role for the “Spacely Sprockets” Account
-User “Bart” has the “Team Member” Role for the “Cogswell Cogs” Account
In this case, the permissions of the “Team Member” Role is intended to be the same i.e. I want to manage “Team Member” permissions in one place…however…what would be the right way to tie a generic Role to a specific Object (Account???). I was thinking:
-“Spacely Sprockets” and “Cogswell Cogs” are objects that represent the Accounts
-“Spacely Sprockets Team Member” and “Cogswell Cogs Team Member” are Roles which tie specifically to their associated Account counterparts…but actual activity permissions are NOT controlled with these.
Then a runtime permissions check might go something:
-“John” logs in and his Session is associated with the “Team Member” Role
-“John” attempts to update the “Spacely Sprockets” Account
-We first check that “John” is associated to the “Spacely Sprockets Team Member” Role
-We then check if the “Team Member” Role has “Update” permissions on the “Account” Object
In this approach, we would create specific “instance” team member roles for each account.
Does this approach sound right?
Hi John. I think your approach is fine, assuming you don’t have a lot of accounts. One of the problems with RBAC is associating the permissions with instance data, like accounts. An alternate approach I’ve used is to associate the account with a specific object id on the permissions.
Spacely Sprockets and Cogswell Cogs could be represented like:
objectid: Spaceley Sprockets
operations: add, update, delete
roles: TeamSpacely, SuperAdmin
objectid: Cogswell Cogs
operation: add, update
roles: TeamCogs, SuperAdmin
When you invoke the checkAccess function for either you will pass all of the args for perm, including object name, object id and operation.
Permission spaceyPerm = new Permission(“Perm1”, “Spaceley Sprockets”, “add”);
boolean result = checkAccess(session, spaceyPerm);
In this scenario John would get true and Bart would be false. No extra role check required.
Thanks so much for the quick reply, very helpful!!!
Let me test my understanding of the model you described.
In the model you described, “TeamSpacely” and “TeamCogs” are separate Roles with separate operation permissions and these Roles would be managed separately, is that right?
The model I was targeting was that the Role of “Team Member” was something that I wanted to manage globally and it would therefore effect all “Accounts”…if I said that “Team Member” had “add, update, delete” operation permissions, then that would effect all Accounts.
That’s why I was going down the thought of the “double” role model…”Team Member” was the actual/global Role definition that specifies/controls the operation permissions on Accounts…and “Spacely Sprockets Team Member” and “Cogswell Cogs Team Member” where used to control (for example) that “John” is indeed a “Team Member on the Spacely Sprockets Account”
Does that make sense?
John, yes, it makes sense. Should work just fine.
Cool, thanks very much for taking the time to provide input on this