I was reading the article How to Start an IDM Job from a Policy and I really liked the idea.
I had not considered using the dxcmd Java classes to start a Job but thought it was a great idea. I decided I could use this in my toolkit rules, but I wanted to improve upon it.
The biggest problem that the author left in the rule is that he hard coded the username and password for the user to login with. Obviously there are better ways to do it that are more secure, and satisfy one of my major issues, which is that I am lazy. As I go from site to site I do not want to have to type in passwords for this rule. That is way too much work. Heck, I don't want to have to type ANYTHING, other than just importing this rule into a driver somewhere. Lets see if that is possible.
The traditional way would probably be to use a Named password which is how the Authentication, Remote Loader, and Driver object passwords are stored encrypted in the driver configuration. There is a token to retrieve Named Passwords and you would set a local variable, say called PASSWORD and set it to the Named Password.
Again, that is fine and much more secure, but still requires me to enter a password for each installation of this rule. Does not satisfy the laziness quotient.
Instead I will use the trick I learned from Lothar Haeger from his truly excellent Password Notification driver (IDM 3.5 Password Notification Service Driver) for zero configuration authentication in policy. (PS: Lothar, that was a brilliant idea!).
I actually highly recommend downloading Lothar's driver, installing it in a test project, or a live tree, and read through the policy. I can almost guarantee that you will learn at least three tricks you can use in other projects. (Zero configuration authentication in policy, ECMA Script sample for LDAP searches, and driver heat beating. There is even more, but go see for yourself. I am confident you will learn at least something!).
Lothar's trick is a wonderful bit of insight into how Identity Manager works with eDirectory. To do an authenticated connection, we need a username (probably with a DN, depending how we want to authenticate), and a password. Probably should have enough trustee rights to do what you want to do.
Well we know at least one object in the tree that must have enough rights to do what we want to do... The driver object itself. After all, it can read and modify objects in the tree, after all that is what Identity Manager does.
How does the Driver object get sufficient rights to do the work it needs to do in the directory? If you have ever configured a driver in Identity Manager you will know the answer, you make the user a Security Equivalent to an object with sufficient rights.
That is nice, but how does it help us? Well it turns out, if you know how Group objects work in eDirectory, they are a great example, and explaining them should make this explanation pretty straightforward. Group membership is actually four attributes in eDirectory, two pairs of reciprocal attributes (Which by the way Identity Manager 3.6 just released, now allows you to say that any pair of DN syntax attributes you have created can be treated as reciprocal attributes and get all the benefits built into Identity Manager in regard to their handling.). The pairs are Group Membership on the User, listing the DN's of the groups they are a member of, and Members on the Group, listing the users who are members of the Group. If you just have these two attributes set, you are a member of the group, but you do not actually get any benefit of being a member, in regards to trustees, since that is controlled by the second pair of reciprocal attributes. Equivalent To Me, and Security Equals. It is Security Equals that is so interesting in this instance.
When you make a driver object Security Equivalent to an administrative user, an attribute, Security Equals gets the value of the DN of that object. Well that is just an attribute in eDirectory and we can trivially retrieve that at will. Even easier for the lazy folk among us, since it is on the Driver object, we can use the built in Global Configuration Value (GCV) dirxml.auto.driverdn that is automatically replaced with the driver DN that the rule is running in. (In other words, this would work in a Library as well, since each time it is evaluated the current driver running the rule expands the variable to point at itself!)
Well that gets us the DN of the user who has sufficient rights, but in backslash syntax (the way Identity Manager handles DN paths internally, or at least how they show up, who knows exactly how it stores it in memory) so we will have to use what I find to be the most frustrating token of them all at times, Parse DN. For some of my thoughts on this token you can read up at:
In this case, we want to specify convert from source to dot notation, and start at 1, to drop off the tree name. This will take a DN value that might look like: \ACME-TREE\ACME\USERS\ACTIVE\IDMUSER and Parse the DN to give us what we want, IDMUSER.ACTIVE.USERS.ACME which is the format we need to feed into the Java class.
So to recap, we will use the value of Security Equals (probably via the Source Attribute token, see: The different attribute options in Identity Manager for a discussion of Source Attribute and its friends) from the object referred to by the dirxml.auto.driverdn GCV. Store that in a local variable, and we will convert it via ParseDN in a moment.
Then we can read out the nspmDistributionPassword from the object whose DN we just retrieved. Know we have everything we need to login, and not a single thing is driver or tree specific yet! Hurray for the lazy people! Zero configuration needed so far.
We store those in variables, say USERNAME, then PASSWORD, and now we can replace them in the XPATH statement and have it almost completely zero configuration.
There is one more caveat to this though. The Universal Password policy has to be applied to the user, which is often NOT the case for the Admin user, which is probably the most common object people make a driver Security Equal to. However that is pretty easy to fix, just assign it to the Admin user as well. Probably a good idea, since you want Admin to have a strong password, probably stronger than regular users. Also you need to have enabled allow user to retrieve password in the policy. I did not test if you need to set allow Admin to retrieve the password yet or not, but usually that is set so that Identity Manager can get the password out as needed.
The final variable that might change that I cannot think of a good zero configuration model for is the DN of the Job itself...
I can think of a couple of ways to make it better. For example, we can assume you will always can it ToolkitRule inside the driver you want to run it from. In which case we can define another variable, JOB-NAME and build it as the string "ToolkitRule." (That is a period at the end of the name) followed by the driver DN in dot notation. Well we just had an example of how to do that with ParseDN so we use ParseDN again, this time on the dirxml.auto.driverdn GCV and we are ready to go.
Almost no work at all involved. This is my kind of policy!
Here is a nice sample of how you might do it.
<?xml version="1.0" encoding="UTF-8"?><policy xmlns:jcmd="http://www.novell.com/nxsl/java/http://www.novell.com/nxsl/java/com.novell.nds.dirxml.util.DxCommand">
<description>[acme] Start a Job from Policy (1030)</description>
<comment xml:space="preserve">Start a Job from policy example.</comment>
<if-op-attr mode="nocase" name="twcTestingVersion" op="changing-to">1030</if-op-attr>
<do-set-local-variable name="USERNAME" scope="policy">
<token-src-attr name="Security Equals">
<do-set-local-variable name="PASSWORD" scope="policy">
<do-set-local-variable name="USERNAME" scope="policy">
<token-parse-dn dest-dn-format="dot" start="1">
<do-set-local-variable name="JOB" scope="policy">
<token-parse-dn dest-dn-format="dot" start="1">
<do-set-local-variable name="START-JOB" scope="policy">
<token-xpath expression='jcmd:commandLine(" -user $USERNAME -password $PASSWORD -startjob $JOB")'/>
Note that I included the Policy node (like the original author did) since you need to define the name space for the Java class, and that is done in the Policy node. Which means just pasting the rule into an existing policy with rules already in it would require you to edit the policy node and add the text:
<policy xmlns:jcmd="<a href="http://www.novell.com/nxsl/java/http://www.novell.com/nxsl/java/com.novell.nds.dirxml.util.DxCommand">http://www.novell.com/nxsl/java/http://www.novell.com/nxsl/java/com.novell.nds.dirxml.util.DxCommand</a>">
Or you could just create a new policy object that only this rule uses.
It happens I like to use a trigger attribute to kick stuff off, in this case, the condition for this rule is acmeTestingRule is changing to 1030 then event. I started at 1024 (because I had used 42 already elsewhere) and this is my sixth toolkit rule in this driver, so I ended up at 1030. Pick your condition that will trigger it, perhaps a Location attribute changing to Candyland? It can be anything, just would be nice if it was unique and horribly unlikely to ever happen on its own.
Which is actually ironic, since I have been using Jobs to trigger rules, and now here I am using a rule to trigger a Job. However I can see times when I might want to do this, so it still has value.
The DxCommand class which contains the commandLine function is part of the dirxml_misc.jar file, which is part of every base Identity Manager install, so no worries about copying a file or restarting eDirectory for it to be available. Boy this caters to the lazy.
There you have it, a lazier mans way. Now that I have a toolkit rule that can call Dxcmd functions all ready to go, pretty much all I need to do is fiddle with the XPATH line:
jcmd:commandLine(" -user $USERNAME -password $PASSWORD -startjob $JOB")
and change definition of the -startjob $JOB part to be the function I want. Just run dxcmd from any Identity Manager installation you have with -? or -help to see the list of commands you can use. As Aaron writes in this article: How to Monitor an IDM Driver for Activity we could use it to monitor a drivers state from policy. That could be interesting. I am not sure of a practical use for this specific example to be done in policy at this moment, but give me some time. Maybe if you have some driver interdependencies, where if only one driver of a set is running bad things will happen, you could use this kind of rule to make sure that the other drivers are running before allowing the driver to start up.
That could be useful. More to follow later I think...
Disclaimer: As with everything else at Cool Solutions, this content is definitely not supported by Novell (so don't even think of calling Support if you try something and it blows up).
It was contributed by a community member and is published "as is." It seems to have worked for at least one person, and might work for you. But please be sure to test, test, test before you do anything drastic with it.