Making Fields in a PRD Reflect Trustee Rights (ACLs) – Part 1

0 Likes
over 3 years ago

Making your administrative trustee rights reflect in the behavior of a PRD form is possible, but there are quite a few moving parts to make it happen. The story of this implementation will include several important steps including:


    • Understanding how Trustee Rights (ACLs) work in eDirectory

 

    • Reviewing the client’s use case

 

    • Getting the rights to see the rights

 

    • Reading and interpreting the rights

 

    • Copying the rights in to the form

 

    • Understanding Name Spaces in eDirectory, LDAP and IDM

 

    • Implementing the form behavior




In part 1 of this article we will focus on the back-end of this challenge, in the directory and the workflow. Part 2 will focus on the form.

 

Background

 



Recently, one of my best clients came to me with a problem. They were using Identity Manager 4.0.2 and had implemented portlets to provide simplified delegated administration for some specific tasks. These portlets were pretty rudimentary, and required training for the admins to use. There were several defined for different levels of access.



The more significant challenge was that the portlets chosen were no longer supported after IDM 4.0.2 and their engine was already running IDM 4.6. I proposed replacing them with a series of PRDs, but as we began to investigate that, it became clear that the functionality overlapped so significantly that they needed was a single PRD that could provide all the functionality they require.

Access to the portlets was secured by two things, a group membership (which made the portlet available to the user) and the trustee rights (ACLs) that that user had within the identity vault.

As I started to develop the master PRD, requirements for enforcing the ACLs were brought up. The same ACLs would enforce access the same way. However, the different was that the portlets would remain unavailable if the user didn’t have rights. With a single PRD, users would see the entire PRD but not be able to use all fields.

We could have hard coded the group membership to a visibility list, but I am always looking for ways to develop strategically and administer in fewer places. So we decided that we should and could use the trustee assignments (ACLs) to control both whether each field is enabled and/or visible on the form.

 

The Details

 



“It all comes down to one simple thing, and that is: that it never comes down to one simple thing.”
– Rob Rawson



I have been working with eDirectory for a very long time, even before it was called eDirectory. The ACL model has had a few enhancements but it was so well conceived that for the most part it’s been the same since the technology first rolled out in the early 1990s.

A user’s rights are calculated based on their position in the directory and all the objects they are security equivalent to. Any of these object could be potentially granted rights anywhere in the directory. So to figure out what rights you might have to edit a target user, you need do:

Make a list (call it “AdminDNs” for example) starting with the administering user’s DN and adding any objects the admin is security equivalent to.


    • Iterate over the AdminDNs list (for each DN in AdminDNs)

 

    • Iterate over the target user DN ACLs looking for subjects in the AdminDNs list

 

    • Walk your way toward the top of the tree, looking as each object’s ACL for the subjects in the AdminDNs list which are flagged as “inheritable”





So this is all do-able, but it could be a lot of processing to happen for each form opening. Fortunately, the client relieved me of this by informing me of the following use case:


    • All users are stored in a single container named “Users” under the organization object in the tree

 

    • All administrative rights are granted by group membership

 

  • Rights are not granted to higher level containers and inherited. In other words, there are no rights inherited from the “o” or from the root of the tree.


Therefore, the algorithm became much simpler:

    • Read the admin’s Group Membership attribute

 

  • Iterate on the users container ACLs looking for the DNs of groups that the admin is a member of



 

Rights to Rights

 



The next issue was that ACLs are themselves stored in an attribute of the directory and you need ACL rights to read them (Egg? Chicken? Both. Neither.). To solve this, it is important to understand the Start activity in the workflow.

There are two ways you could possible initialize a form field in a PRD: You can build code that runs in a field onload event, or you can build code that runs in the start activity.

The form is restricted by what a browser can do plus the enhancements that the objects that the PRD provides (i.e., the IDVault object). Under the hood in the form, the IDVault object makes a SOAP call to a web service called VDX that provide directory access. The context for this is the same user that has logged in to user application. This means you have the same ACLs enforced on you.

In contrast, the Start activity runs at the server in the workflow engine. It’s access context is the UA Administrator object. Therefore, initializing a field in the start activity can access data that you might not have rights to access in the onload. This is handy when you want to use data in the directory to initialize a form. In this case, we are reading the ACLs.

The mechanism I put together was to read and filter the ACLs within the start activity and transmit that data into a hidden multi-valued field in the form which could be used to control the form’s status for each field. There were two fields: Editable and Visible.



The function permisables() is used to produce the list of attributes which are permissable based on a particular set of ACL rights. The set of rights is a bitmap based on the calculation in the third parameter. The values here are:

ACL rights:

* 1     Compare
* 2     Read
* 4     Write
* 8     Add Self
* 16    (unused)
* 32    Supervisor
* 64    Inheritance Control


We also look at “All Attribute Rights”. This is actually a misnomer; this ACL provides rights to a specific set of attributes which are considered the default attributes for a particular object class. In practice this works well with base schema but schema extensions do not usually get included under All Attribute Rights.
Additionally, we actually don’t necessarily want to use to map this right as-is to the PRD, because there are some fields that, because of a business decision, the client doesn’t want to enable, even if all attribute rights are granted. When we look later at how this ACL list gets utilized in the form, you will see a mechanism for these exceptions.

In addition, we also look at “entry rights” to determine whether the administrator may create users or just edit them.

The code for “permisables()” and “entryRights()” is as follows”:


function entryRights(IDVault,initiator, dn)
{
var protectedName=3
var trustee=2
var scope=1
var privileges=0
var ADD = 2
var BROWSE = 1
var ENTRY_RIGHTS = "[Entry Rights]"

print("Checking Entry Rights");

var rights = 0;

ACLs = getObject(IDVault, dn, 'OU', 'ACL');
groups = getObject(IDVault, initiator , 'user', 'group');

if (!undef(groups) && (!undef(ACLs)))
{
for (var i =0; i < groups.size(); i )
{
var group = groups.get(i).toString();

for (var j =0; j < ACLs.size(); j )
{
var ACL = ACLs.get(j).toString().split("#");

if (ACL[trustee] == group)
{
print(" Check " ACL);
/* ACL rights:
*
* 1 Browse
* 2 Add
* 4 Delete
* 8 Rename
* 16 Supervisor
* 32 (unused)
* 64 Inheritance Control
*
* Values are different for [Attribute Rights]
*/

// bitwise and with 4 32

if (ACL[protectedName] == ENTRY_RIGHTS)
{
if (ACL[privileges] & BROWSE) print(" --found BROWSE rights");
if (ACL[privileges] & ADD) print(" --found ADD rights");

rights = ACL[privileges] | rights;
}
}
}
}
}

if ((rights & ADD) != 0)
{
return true;
}
else
{
if ((rights & BROWSE) != 0)
{
return false;
}
else
{
return null;
}
}
}

function permisables(IDVault,initiator,privMask,dn)
{
var protectedName=3
var trustee=2
var scope=1
var privileges=0
print("Checking for privMask " privMask.toString());
var value = new java.util.Vector();

ACLs = getObject(IDVault, dn, 'OU', 'ACL');
groups = getObject(IDVault, initiator , 'user', 'group');

if (!undef(groups) && (!undef(ACLs)))
{
for (var i =0; i < groups.size(); i )
{
var group = groups.get(i).toString();

for (var j =0; j < ACLs.size(); j )
{
var ACL = ACLs.get(j).toString().split("#");

if (ACL[trustee] == group)
{
print(" Found " ACL);
/* ACL rights:
*
* 1 Compare
* 2 Read
* 4 Write
* 8 Add Self
* 16 (unused)
* 32 Supervisor
* 64 Inheritance Control
*
* Values are different for [Entry Rights]
*/

// bitwise and with 4 32
var rights = ACL[privileges] & privMask;
if (rights != 0)
{
if (value.indexOf(ACL[protectedName]) == -1)
{
print("Adding " ACL[protectedName] " to list");
value.add(ACL[protectedName]);
}
}
}
}
}
}
return value;
}



In part 2 of this article, we will focus on how to use the ACL information we have now retrieved within the PRD form.


Labels:

How To-Best Practice
Collateral
Comment List
Anonymous
Related Discussions
Recommended