I am wrapping a crazy busy week. Probably one of my most technically in-depth week in a really long time. So what kept me busy? Deep-diving into OpenAM’s Entitlement’s engine, learning about it’s REST interfaces and how to extend OpenAM to leverage custom service types. I’ll explain later since I know your thinking, “Tumy … dude, what the heck is a service type?”.
Alright, let’s jump into it …
Entitlements are policies or rules that state what you (or any user) can and can’t do. Sounds simple right? In Information Security entitlements usually define what resources a user can access, how they can access it, when they can access it and so on and so on. A resource can be a web url, a banking transaction, a database record, or frankly anything you might want to protect. Typically entitlements are expressed through XACML http://en.wikipedia.org/wiki/XACML. Entitlements are used in access control settings and used to define fine-grained authorization rules. This is starting to become too much of a Entitlements 101 class so let me just jump into the hand’s on stuff.
Ok, Forgerock … in their OpenAM product they have an Entitlements engine which is essentially a Policy Management Point and a Policy Decision Point (Google is your friend if you don’t know what those things are). Out of the box OpenAM supports a few different “service types” which are essentially a set of resources and their associated actions. For example a web url would potentially have the actions of “GET” and “POST”. There are a couple of other service types too (a banking example and a few others). But what happens when our resource is not a web URL and we want to have actions besides “GET” or “POST”. What we if we wanted to have a resources defined as database table names and we wanted to have actions such as “READ”, “UPDATE”, “DELETE”. (Update: Starting in OpenAM Version 11.2 some of these additional actions are available out of the box) We want to be able to create rules that we can either allow a user to read information from a specific table or deny their ability to read from a certain table. Ok, hopefully you get the idea … if you don’t email me and we can talk about it. OpenAM has a great set of command line tools that you can use to interface with the product, these tools have also been “web” enabled on a jsp page which is accessible through the admin console (it’s disabled by default though).
To create this new service type there are a few steps we need to take:
- Create a custom Application Type
- Create a custom Service Type
- Create a custom Application
- Create the policy, using the custom service type
4 easy steps.
The Custom Application Type is a few lines that get imported. Let’s assume that you have enabled the web ssoadmin.jsp and have accessed it here:
https://am.host:port/openam/ssoadm.jsp
You would see a page like this:
Image may be NSFW.
Clik here to view.
Do a quick search for “create-appl-type” and you then click on it.
Fill in the form that is displayed with this information:
Application Type Name: BTPoliyService
actions=READ=true
actions=UPDATE=true
actions=DELETE=true
actions=ADD-ACCESS=true
resourceComparator=com.sun.identity.entitlement.URLResourceName
saveIndexImpl=com.sun.identity.entitlement.util.ResourceNameIndexGenerator
searchIndexImpl=com.sun.identity.entitlement.util.ResourceNameSplitter
This creates the set of actions that will be available for your resources of this type. Save that and then you need to create the Custom Service Type. This is created by modifying an XML file and then importing that file into a form that is similar to the one we just saw.
The service type provides a little more detail on the actions and sets the True/False values that will be displayed in the policy manager.
<?xml version=”1.0″ encoding=”UTF-8″?><!DOCTYPE ServicesConfiguration SYSTEM “jar://com/sun/identity/sm/sms.dtd”><ServicesConfiguration><Service name=”BTPolicyService” version=”1.0″>
<Schema serviceHierarchy=”/DSAMEConfig/BTPolicyService” i18nFileName=”BTPolicyService” i18nKey=”BTPolicyService”>
<Global>
<AttributeSchema name=”serviceObjectClasses” type=”list” syntax=”string” i18nKey=”BTPolicyService”/>
</Global>
<Policy>
<AttributeSchema i18nKey=”READ” name=”READ” syntax=”boolean” type=”single” uitype=”radio” >
<IsResourceNameAllowed></IsResourceNameAllowed>
<BooleanValues>
<BooleanTrueValue>true</BooleanTrueValue>
<BooleanFalseValue>false</BooleanFalseValue>
</BooleanValues>
</AttributeSchema>
<AttributeSchema i18nKey=”DELETE” name=”DELETE” syntax=”boolean” type=”single” uitype=”radio” >
<IsResourceNameAllowed></IsResourceNameAllowed>
<BooleanValues>
<BooleanTrueValue>true</BooleanTrueValue>
<BooleanFalseValue>false</BooleanFalseValue>
</BooleanValues>
</AttributeSchema>
<AttributeSchema i18nKey=”UPDATE” name=”UPDATE” syntax=”boolean” type=”single” uitype=”radio” >
<IsResourceNameAllowed></IsResourceNameAllowed>
<BooleanValues>
<BooleanTrueValue>true</BooleanTrueValue>
<BooleanFalseValue>false</BooleanFalseValue>
</BooleanValues>
</AttributeSchema>
<AttributeSchema i18nKey=”ADD-ACCESS” name=”ADD-ACCESS” syntax=”boolean” type=”single” uitype=”radio” >
<IsResourceNameAllowed></IsResourceNameAllowed>
<BooleanValues>
<BooleanTrueValue>true</BooleanTrueValue>
<BooleanFalseValue>false</BooleanFalseValue>
</BooleanValues>
</AttributeSchema>
</Policy>
</Schema>
</Service>
</ServicesConfiguration>
In the above XML file, you should notice there are several spots where I have provided the name of the service “DatabaseTablePolicyService” and then the actions and their True/False values. In the ssoadm.jsp search for “create-svc” and then copy and paste this file into that form.
Next step and last step of the “extending” part of the process. So, in the ssoadm.jsp web page, search for “create-appl”. Click on this link and it will open a form very similar to the “create-appl-type” form. Enter the following information:
actions=READ=true
actions=UPDATE=true
actions=DELETE=true
actions=ADD-ACCESS=true
applicationType=BTPolicyService
resources= table://*
entitlementCombiner=com.sun.identity.entitlement.DenyOverride
resourceComparator=com.sun.identity.entitlement.URLResourceName
conditions=com.sun.identity.admin.model.DnsNameViewCondition
subjects=com.sun.identity.admin.model.IdRepoGroupViewSubject
subjects=com.sun.identity.admin.model.IdRepoRoleViewSubject
subjects=com.sun.identity.admin.model.IdRepoUserViewSubject
subjects=com.sun.identity.admin.model.VirtualViewSubject
subjects=com.sun.identity.admin.model.AttributeViewSubject
subjects=com.sun.identity.admin.model.OrViewSubject
subjects=com.sun.identity.admin.model.AndViewSubject
subjects=com.sun.identity.admin.model.NotViewSubject
conditions=dateRange
conditions=daysOfWeek
conditions=dnsName
conditions=ipRange
conditions=timeRange
conditions=timezone
conditions=or
conditions=and
conditions=not
Notice in the above file, that I add the application name and it matches the name we have used in the other configurations. I added the actions again and finally I actually define a resource. I personally like to describe the resource type in a URL style … I can use “table://” as my resource in the policy and that will help remind me later what type of resource that is. You don’t have to prefix your resources in your policy with that … it seems to be optional.
At this point you can jump back over to the OpenAM Admin console and create a policy based on this resource, as you can see in the following screenshot.
Image may be NSFW.
Clik here to view.
So, that’s pretty cool stuff … The entitlements engine is pretty robust, it’s fast and … it has a RESTful interface. I am going to do a deep-dive blog post on the RESTful services at some point but for now let’s just take a look at how you can evaluate an entitlement.
Evaluating a Privilege:
* ssoToken = Authenticated User’s Token
* iPlanetDirectoryPro = session cookie … admin users session token
* action = action user is attempting (GET, POST, READ, DELETE, etc)
* application = application type of policy (defaults to iPlanetAMWebAgentService)
* Subject (user attempting action … encoded session token)
curl -v -H “X-Query-Parameters: ssotoken:AQIC5wM2LY4SfczpL5a3M02ju3uyOd6iMj4zZvPZXB3BNQ4.*AAJTSQACMDE.*” -b “iPlanetDirectoryPro=”AQIC5wM2LY4SfcxcPg_yUwYu-iQPHH663tv9AnoEEr6j_2k.*AAJTSQACMDE.*”” “http://am.host:port/openam/ws/1/entitlement/entitlement?action=READ&resource=table://my_table_name&application=BTPolicyService&subject=4l18suAL/hXNCfzykwIlbV0WbtM%3D”
This will return a JSON formatted object:
{
“statusCode”:200,
“body”:{
“actionsValues”:{READ:”true”, UPDATE:”false”, DELETE:”true”, ADD-ACCESS:”false”},
“resourceName”:”table://my_table_name”},
“statusMessage”:”OK”
}
You can create a policy that would return attributes, from the user’s identity record, along with this JSON object. There are also RESTful services that will just return an allow or deny, which is great if you don’t need as much information back.
So, that was real high level and really basic but I hope that I gave you some ideas for the potential of this engine. Let me know if you have any questions or want to chat about. Also, I am available on a consulting basis to help design or implement this in your environment.
Acknowledgements:
- There were a bunch of people at ForgeRock that help me out at various points through this. You guys know who you are … I’ll leave your names out so that you don’t get bombarded with requests.
- Also, there were a few non-ForgeRock guys that went through this last year and gave me some pointers along the way. Thanks!
- And finally … to the guys that did this first at Sun. Thanks for building this stuff and documenting it. I am thankful that those web pages that you created haven’t vanished yet.