With Novell Identity Manager 4.0 there are a number of new features available. You can read more about those features in these articles:
There are four new drivers, two are for new connected system supported (Salesforce.com and Sharepoint) and two are used as service drivers that are needed for the Reporting module.
These two drivers are the Managed System Gateway (MSG) driver, and Data Collection Service (DCS) driver, the first of which you can read about in this series of articles:
The Data Collection Service driver, is the second half of that pairing, and will be the topic of this series. Both these drivers are meant to enable the Reporting module to get enough information about the system to report upon it. The MSG driver is focused more on providing information about how the drivers are configured, heck it even tries to infer the matching rule criteria by reading the rules out of the objects, and the DCS driver is focused more on collecting events about objects for storage in the Reporting database.
In the first article Data Collection Service Driver Walkthrough – Part 1 I started looking at how it builds a cache variable and got through most of the work it does to get the correct IP Address of the server running the Managed System Gateway driver.
This is best understood if you are reading through the policy in Designer with me, you can find this in the NOVLIDMDCSB-itp-IntRegistrationCache. I have yet to find a useful way to show the policy builder view, except via a screen shot, which is hard to read and not editable to better understand the tokens in use, so I ask that you import this driver into your Designer 4.0 test project, and follow along.
After it gets the IP address through the various possible cases (via the override configuration value, via a simple configuration setting, via the DirXML-ShimAuthServer attribute and if its a remote loader instance, from the hostname= part of the REMOTE string) the next thing we need is a port. Again, because there is an override value allowed, have to test for that first, and if not use the configuration value.
The same steps and tests are performed for the https port, and the context. Check for an override value, otherwise use the values in the Managed System Gateway (MSG) driver.
The value for the certificate used starts out the same way by checking the override configuration value first, but if it is not set, does some extra work. If this shim is running local (i.e. in the eDirectory instance, as opposed to running via a Remote Loader) It uses ParseDN to get the parent container of the current running server for the dirxml.auto.localserverdn (a new Global Configuration Variable (GCV) in IDM 4 for the server DN in LDAP format for the server the driver is currently running on), then it takes the name of the key material object (KMO) provided in the configuration and appends space dash space (” – “) followed by the server name (also retrieved with ParseDN on the dirxml.auto.localserverdn). Then it makes an assumption that is not really safe. It assumes that the KMO object is in the same container as the server object. This is very often the case, but only because it is the easiest case. There is nothing that requires the certificate to be created in the same container as the server. However I concede it is pretty rare to NOT have the certificate object co-residing with the NCP Server object in eDirectory.
This comes up, because the policy reads back the actual certificate (public key from NDSOKI:Public Key Certificate attribute) from the NDSPKI:Key Material object, named based on the logic above. Server name, space dash space, container the server resides in.
Then it does something odd, in looking at the configuration value for SSL, it does a test for the value of ssl to be an underscore character. Well first it does a regular expression equals (which shows as match=) to see if it has a value by doing a regex test for .* (period asterisk) which means any number of characters, and then it checks to see if it is equal to underscore (_). This confused me for a moment, so I went and looked at the GCV for the SSL setting. It has three values, http, https, and discover. Now it turns out that it is not a list GCV, rather it is a an enum GCV, which presents a choice of a list of pretty names, and when you select you, you get a value (might be the same, might be different) for the actual value. In this case, the item discover returns an underscore character.
So if it is empty or an underscore, then it sets the ssl variable to the following XPATH, which at first did not make sense to me:
This looks like a node test, and will return true or false as a boolean. Usually we want to select in a set local variable context. But as I read further down I realized what they are doing. The enum GCV just above, that returned _ for discover, is storing true if you select https, and false if you select http. So this does do a node test, looking for any <definition name=’allow-http’> node whose <value> nodes string value is false. Which would return true or false if it matched. By casting it as a string with the string() function, this now returns the literal string, instead of a boolean value.
Next the cache variable starts to get built up, node by node, element by element. In the first article we noted the variable was initialized with a <cache/> node at the top. Now various parts of the cache variable are getting added. I do not happen to have any trace sample handy, so I built some of the XML below by hand, from reading the policy. (Not as hard as it sounds, but a little tedious)
<cache> <instance class-name="__DCS_REGISTRATION__" src-dn="driverDn"> <association>GUID Value</association> <attr attr-name="msgw-drv-address"> <value type="string">IP Address</value> </attr> <attr attr-name="msgw-drv-port"> <value></value> </attr> <attr attr-name="msgw-drv-context"> <value type="string"></value> </attr> </instance> </cache>
Then there is a bit of logic to handle the Remote versus local case that was derived earlier, and thus you would end up with a different document depending on how your driver is configured. If the driver is running local with SSL, you get an <attr attr-name=’msgw-drv-cert’> node with some data, which is actually a pretty cool node, since it is flagged as is-sensitive=”true” which means it is treated like a password in DStrace, so that it is shown only as <–content surpressed–> instead of the actual data. This is the type=’octet’ of the actual public key of the Certificate being used by the driver that was retrieved earlier.
Then you an ssl=”true” or “false” attribute is added, If ssl is true and the driver is running remote a bunch of other nodes get added as well. To connect remote over SSL you still need to specify a keystore with the trusted root certificates. This is important and often confusing in IDM and SSL in general.
HTTPS and LDAPS use asymmetric key encryption, which is quite slow and CPU intensive for the bare minimum. That is they use it to exchange the symmetric key that they will actually use the encrypt the conversation. If you can get that key, that both sides have to agree upon, then the entire conversation is compromised. So how do you exchange that key between both parties in a secure way? That is what the asymmetric encryption is used for. It is slow and expensive, so use it to exchange a short small key, and use that for the rest of the encryption.
So why the keystore? At first glance you would think it would be to store the private key of the SSL certificate so you could compare or use it. But in fact, usually it is all about getting the Certificate Authorities trusted root public key certificate included. Using that certificate you can validate any other public key that it signed. Well how do you know to trust that Root CA? Well in the case of Verisign, Thwate, and others they paid Microsoft and Mozilla many millions of dollars (I last heard it was something like $15 million US but I cannot back that up as fact) to include their trusted root CA public keys in the default browsers of the world.
Anything in that list is trusted. Well in IDM you often use the eDirectory tree CA and I have yet to meet anyone ever who actually bought a certificate for their tree CA that is itself signed. You could, but they are expensive. So your CA is implicitly untrusted and we need to fix that issue. How to fix it? Include it in a keystore that you trust. For Windows this is part of Internet Explorer, Mozilla has its own. Java uses JKS Keystore files. .NET uses its own keystore type. Unix applications that are not Java based, seem to often use the Netscape Security Service (NSS, no relation to Novell’s file system of the same initials) libraries. These are applications that are looking for a cert7.db file, which is a specific format that the old Netscape Navigator used to store its certificates in. The new format is cert8.db and the bad news is that Mozilla updated the NSS toolkit that can make a cert7.db file to only support the newer cert8.db format. Thus if you really still need cert7.db files, you need to find either a copy of Netscape 4.7 that you can make work, import the certificate into your profiles key storage and then copy out that cert7.db file. Or else you need to find the NSS kit before version 3.3 and try and keep it running as long as possible. Or else campaign to get the application updated to the newer more modern libraries.
Thus we need to specify the keystore file, and password since IDM is mostly Java based, to make an SSL connection successfully. Thus the Remote Loaders on Windows expect the Trusted Root exported base 64 encoded (.B64 format) in a file. The Unix remote loaders expect it in a PEM file (aka DER format, the binary version that gets base 64 encoded to make a .b64 file). The Omnibond remote loaders are clever and do all this work for you, when you just specify an LDAP server in your tree, it does a StartTLS command, gets the trusted root CA’s certificate as part of that transaction and adds it into the keystore for you. (Though actually, I think they just store it as a PEM file, but I am not certain).
I ran into a case with Cognos from IBM, which officially supports using LDAP for authentication, and the well meaning Cognos admin was trying to get it working. He read the IBM docs which said, either do the first or second step, but did not make a clear delineation where step one ended and step two began. The first step was to import the trusted root certificate into a cert7.db file except that as I mentioned above it is really hard to make a cert7.db format file now. Of course IBM was good enough in the later Cognos builds to start using the cert8.db format, so it was actually possible. That went fine and had he stopped there all would have been well. But he continued and imported the specific server certificate, which is not a great plan, since those regularly (two years by default) expire. It turns out to make it even worse, he was behind a LDAP load balancer, so he would get a different LDAP server every authentication attempt, and only one would work. Cognos was coded nicely to keep trying on an SSL error, so it would keep trying till it succeeded, and sometimes it failed after too many attempts, but often it was slow.
Once we finally cleared up the details, and he imported just the Trusted Root, which means all certificates that are signed by it are accepted which was much better and faster.
In the Remote case, there will be more <attr> nodes in the <cache> variable.
<attr attr-name="msgw-drv-keystore-filename"> <value type="string">/opt/novell/idm/driver/idm.keystore</value> </attr> <attr attr-name="msgw-drv-keystore-password" is-sensitive="true"> <value type="string"><--content suppressed--></value> </attr> <attr attr-name="msgw-drv-keystore-alias"> <value type="string">myKey</value> </attr> <attr attr-name="msgw-drv-use-keystore"> <value type="string">true</value> </attr>
So an example of the combined document might look something close to this:
<cache> <instance class-name="__DCS_REGISTRATION__" src-dn="driverDn"> <association>GUID Value</association> <attr attr-name="msgw-drv-address"> <value type="string">IP Address</value> </attr> <attr attr-name="msgw-drv-port"> <value></value> </attr> <attr attr-name="msgw-drv-context"> <value type="string"></value> </attr> <attr attr-name="msgw-drv-keystore-filename"> <value type="string">/opt/novell/idm/driver/idm.keystore</value> </attr> <attr attr-name="msgw-drv-keystore-password" is-sensitive="true"> <value type="string"><--content suppressed--></value> </attr> <attr attr-name="msgw-drv-keystore-alias"> <value type="string">myKey</value> </attr> <attr attr-name="msgw-drv-use-keystore"> <value type="string">true</value> </attr> </instance> </cache>
Bear in mind there are several possible documents that would be generated depending on how you are running your drivers. Remote or local, with or without SSL, that would affect exactly what nodes would be in the document. However this gives you a pretty good idea of what to expect to see in the variable, which makes looking at rules that use it much easier to visualize and understand.
This data will be queried for elsewhere in the driver, and the results read out of this cache. I will cover the rules those rules a little later in this series. The first part of this up in the next policy object to be looked at, so not too long too wait. You can look back at the Managed System Gateway driver series of articles to see how queries out of this cache are handled, as it is basically the same.
Then we should look at the filter, since there is a fairly large set of objects and attributes that this driver lets through.
Disclaimer: As with everything else at NetIQ Cool Solutions, this content is definitely not supported by NetIQ, so Customer Support will not be able to help you if it has any adverse effect on your environment. It just worked for at least one person, and perhaps it will be useful for you too. Be sure to test in a non-production environment.