Cybersecurity
DevOps Cloud (ADM)
IT Operations Cloud
Structured Global Configuration Variables:
With the release of Identity Manager 3.6.1 very few features were added. Mostly it was bug fixes, updated drivers, and what not. However, at least one new feature that showed up is Structured Global Configuration Variables (GCV). This update affected both the engine, which has to support it, and Designer which has to allow us to work with it. To be honest I assume iManager got updated snapins to support it, but since I so rarely ever use iManager anymore for managing Identity Manager I have no idea if it does or does not. It must, but I have never tried. Designer is just such a better interface for working with Policy that I now find iManager painful to work with. Which is actually sad, as it turns out that iManager is an astonishingly capable web application. Consider the things you can do in the iManager UI and it is quite impressive.
GCVs are great, and I love using them, in so many different ways. I recently wrote a series of articles talking about the different kinds of GCVs you can create. There are string, DN, integer, list, enum, and other types. You can read more in these articles:
On top of that, I have another couple of articles on the topic of GCV usage that may be of interest:
I really am a fan of GCVs and recently needed to use Structured GCVs for the first time.
I knew about them, but had not really looked into the possibilities.
The initial use case for them is in the SAP UM driver, which in the 3.6.1 release changed approaches. In SAP each module is a separate system, and can potentially have its own authentication store. I think the reasoning is based around the notion of allowing them to run independent of any other module, even though they greatly benefit when integrated together.
To make this sillier, SAP itself has a module called CUA, Central User Administration, to try and push users to the various modules you have installed, to make this easier. However, since it is SAP, there has to be a twist, which is that CUA does not push passwords, only other account info.
Thus in a typical IDM and SAP implementation, you could build one driver per module to sync users and passwords, or you could do a single full featured driver to CUA, and then stripped down simple drivers for passwords only, one per module. These drivers could basically be clones of each other, since all that would differ is connection information, making sure to point each one at the correct SAP module.
With IDM 3.6.1 Novell added a fan out capability to the SAP UM driver, so that you can continue to run in the previous mode or in a new approach, where one driver talks to many SAP modules. Which makes management of a single driver instead of potentially a dozen drivers a lot easier.
To manage that, they needed a way to store a number of config parameters, without having to define InstancePort1, InstancePort2, and matching InstanceIP1 and InstanceIP2. Enter Structured GCV's.
First you define the separators between values within each instance, and then between instances. Then you define a template that can consist of components made up of any of the available GCV types.
For example, recently in a SOAP driver, I needed to filter out certain attributes from any add or modify docs, that required approvals via a workflow. I made a structured GCV that had three components. A string, for the class name, a List for the list of attributes in that object class, and finally the DN of the workflow I needed to use in the call of Start Workflow. Kind of like how structured attribute syntaxes are available in eDirectory. (Path syntax is my favorite. A 32 bit Integer, perfect for time stamps, a DN and a string to hold whatever else you need).
These are still new to me, and I am still exploring possibilities with them. Like how to actually use them in Policy. One thing I have noticed is that now that they are available, they are being used in more places. While they were originally designed for a use case coming from the SAP UM driver, they really are a useful construct and the SAP HR CMP driver, which is different from the standard SAP HR driver uses them in a really interesting way. I have been working through that driver in this series of articles:
Part 5 of that series, discusses the case of how they read the data out of the GCV. They use the Document token to read back the raw XML from the attribute of the Driver object that stores ALL the GCV values. Then parse out what they want from it. Heck that was such an interesting approach I had to write an additional article explaining how the Parse DN token they use there works.
Anyway, that is definitely one approach to using these tokens. I still wondered if there was a better way. It does seem like a lot of work, the way its used. There must be a better way to handle it. So I started experimenting.
For my first approach I was thinking of using the Split token based on the separator character between instances, to get a nodeset, then splitting the values inside it, by the value separator. Wow that was a dense statement. Ok, basically when you define your Structured GCV template you can specify two different separator types. One to delimit between instances of the GCV. I.e. As you add a second and third set of values, you need to separate between those instances. The second type is to delimit between the values inside each GCV instance.
Just to make life fun, my specific example had 3 components inside the template, of which one was a List GCV which itself needs a delimiter, and one of my components was a DN, which I needed in LDAP format, which of course is itself delimited by commas. I was running out of delimiting characters that were not valid in the other fields! Need at least 3, and cannot use commas, well not easily anyway.
I started working through that, and I realized something really cool. The result you get, with a set local variable to a global configuration value of this Structured GCV, depends on how you specify the local variable!!
If you use it in a string context, in other words, set your local variable of type String, instead of nodeset, you get a string back. If you set it as a node set, you get the nodeset of the GCV.
Lets start with seeing what I am talking about.
Look at the picture of the GCV view. In the upper right hand corner, you see a sign. That is how you create a new instance, using the template. Actually, if you want to edit the configuration of the structured GCV, the line with the sign is the line to select to actual GCV definition. If you click on the squares down below, which represent an Instance of the GCV, then you get to edit the instance, not the actual GCV definition. A little confusing in the UI, but once you get it, actually it is quite consistent.
The XML of that looks something like this:
<definition display-name="Example of a structured attribute" instance-separator=":" name="structured-example" type="structured" value-separator=";">
<template>
<definition display-name="Class name in example" name="structured-example-class" type="string">
<description/>
</definition>
<definition display-name="List of attributes" item-separator="|" name="structured-example-attrlist" type="list">
<description/>
</definition>
<definition display-name="Workflow DN" dn-space="dirxml" dn-type="ldap" name="structured-example-workflow" type="dn">
<description/>
</definition>
</template>
<value>
<instance>
<definition display-name="Class name in example" name="structured-example-class" type="string">
<description/>
<value>User</value>
</definition>
<definition display-name="List of attributes" item-separator="|" name="structured-example-attrlist" type="list">
<description/>
<value>
<item>Surname</item>
<item>GivenName</item>
</value>
</definition>
<definition display-name="Workflow DN" dn-space="dirxml" dn-type="ldap" name="structured-example-workflow" type="dn">
<description/>
<value>cn=Workflow1,ou=acme,dc=com</value>
</definition>
</instance>
<instance>
<definition display-name="Class name in example" name="structured-example-class" type="string">
<description/>
<value>Group</value>
</definition>
<definition display-name="List of attributes" item-separator="|" name="structured-example-attrlist" type="list">
<description/>
<value>
<item>Member</item>
<item>Equivalent To Me</item>
</value>
</definition>
<definition display-name="Workflow DN" dn-space="dirxml" dn-type="ldap" name="structured-example-workflow" type="dn">
<description/>
<value>cn=Workflow2,ou=acme,dc=com</value>
</definition>
</instance>
</value>
<description/>
</definition>
You can see in the original definition node that the delimiters are specified, and I used colon (:) to separate instances, and semi colon (:) to separate values inside the instance.
Next you get a <template> node, that is where you would find the GCV definitions for the GCVs that make up the structured attribute. You can see I defined:
Then I defined two instances of this structured GCV, one for User and one for Group class. Each has a couple of attributes in the List, and a workflow DN in LDAP format as expected.
Back to the original point of what you get when you try to use the GCV value.
If you set it to a string, it will consist of something like:
User;Surname|GivenName;cn=Workflow1,ou=acme,dc=com:Group;Member|Equivalent To Me;cn=Workflow2,ou=acme,dc=com
You can parse that the way I described as two instances, since there is an instance separator of a colon:
User;Surname|GivenName;cn=Workflow1,ou=acme,dc=com
Group;Member|Equivalent To Me;cn=Workflow2,ou=acme,dc=com
Then you need to break it up by semi colons, to get the individual components, which would get you:
User
Surname|GivenName
cn=Workflow1,ou=acme,dc=com
Group
Member|Equivalent To Me
cn=Workflow2,ou=acme,dc=com
Then you need to split up the List attribute in the middle, based on the pipe (|) separator, since it internally has two values.
User
Surname
GivenName
cn=Workflow1,ou=acme,dc=com
Group
Member
Equivalent To Me
cn=Workflow2,ou=acme,dc=com
Well, I thought about using the split token to get that into a proper nodeset, and probably could have figured that out. I could see why the SAP HR CMP driver used the Document token approach! Way easier way to get the XML of interest.
But then I took a chance and said, what the heck, I wonder what happens if you define the local variable as a node set. I wonder what the node set would look like.
Well guess what? Way easier! Set local variable as a node set and use the XML Serialize token on the GCV token to show the node set in trace and you get:
<instance>
<definition display-name="Class name in example" name="structured-example-class" type="string">
<description></description>
<value xml:space="preserve">User</value>
</definition>
<definition display-name="List of attributes" item-separator="|" name="structured-example-attrlist" type="list">
<description></description>
<value>
<item xml:space="preserve">Surname</item>
<item xml:space="preserve">GivenName</item>
</value>
</definition>
<definition display-name="Workflow DN" dn-space="dirxml" dn-type="ldap" name="structured-example-workflow" type="dn">
<description></description>
<value>cn=Workflow1,ou=acme,dc=com</value>
</definition>
</instance><instance>
<definition display-name="Class name in example" name="structured-example-class" type="string">
<description></description>
<value xml:space="preserve">Group</value>
</definition>
<definition display-name="List of attributes" item-separator="|" name="structured-example-attrlist" type="list">
<description></description>
<value>
<item xml:space="preserve">Member</item>
<item xml:space="preserve">Equivalent To Me</item>
</value>
</definition>
<definition display-name="Workflow DN" dn-space="dirxml" dn-type="ldap" name="structured-example-workflow" type="dn">
<description></description>
<value>cn=Workflow2,ou=acme,dc=com</value>
</definition>
</instance>
Awesome, this is basically the XML from the GCV definition, that we might have used the Document token to get, but ready to roll in an easy to use GCV token call.
So now I can use XPATH on it to get whatever I want.
Lets see, get the object class of the current operation into a variable, say CLASS. Then for each through the local variable node set, and we will loop twice, once for each instance node.
Then we can do an IF with the condition of XPATH is true $current-node/definition[@name="structured-example-class"]=$CLASS and we will know if this instance applies to our current document.
Now we can use the node set of $current-node/definition[@name="structured-example-attrlist"] to compare to the attributes in the current document, and do stuff with them. My initial approach was to loop through the node set of .//@attr-name and compare local variable current-node to the variable holding the List attribute, since that will loop through any node with an XML attribute of attr-name, which works on add, modify or query responses (instance) docs with one test. What is also great is that comparing a local variable to a node set with several values, returns true if it matches ANY of the values, and false if it matches none. This is great, as you can test if your value matches ANY of the values in the list.
This way it is easy to pick out the attributes of interest from the document.
That works, and may or may not be most efficient.
However a colleague took a swing at the same issue, and came up with a cuter approach, that is more efficient. He just tested an XPATH compare, which in a nodeset compare, applies against the entire document, with a single test.
Now as it happens, in our example if we matched the attribute, we were stripping it out, so a much simpler test with an XPATH to detect it, and then a strip by XPATH and done. Much simpler.
Anyway, you can see a lot of power in this type of GCV and lots of interesting options involved in using it. Always nice getting a shiny new toy to play with!