Registering the MSG Driver issues with Reporting

0 Likes
With IDM 4.0, NetIQ introduced the Reporting module. This is something we have wanted for a long time, the ability to generate reports on IDM related stuff. What stuff is that? Well that depends, and is probably the topic for a series of articles about Reporting.

However, to set some basic understanding, let me try and summarize the moving parts.

Reporting uses a Web application, which you deploy like User App and SSPR in Tomcat, JBoss, or WebSphere. This is the front end that manages the user interface and acts as an intermediary between the various systems. These would be the files IDMRPT.war, IDMRPT-CORE.war, and easrestapi.war. They get deployed by your web app server.

There is a database that collects the events and stores it, this is the Event Audit Service server (EAS). This is basically a baby version of Sentinel RD (as to distinguish it from Sentinel 7, Sentinel LM, and other versions). This has collectors to eDirectory and other potential sources. Events from IDM get sent here by 'something' and stored. The Web app uses queries against this data to generate reports. (Maybe the web app calls a service on the DB that does the work, not sure, that is a subtle distinction, mostly with a difference at this level of discussion). This happens to use an instance of PostGreSQL as its database.

Finally you need a way to connect the IDM stuff to the Database, so the Web App can report on it. That is the Data Collection Service (DCS) and Managed System Gateway (MSG) drivers in the IDV. They perform two different tasks, so act differently.

The DCS driver is configured to event on stuff in the IDV, and send those events to the EAS server, where it is stored in a PostGress DB that is part of EAS.

The MSG Driver is configured to listen for incoming requests from Reporting (or the EAS server, not entirely sure) as a gateway driver to inject queries into other drivers in the driver set. If you ever see "Injecting XDS Command" in your trace file, this is some other driver injecting a query or other XDS event. You can do this yourself and it is very helpful. See Alekz's excellent article on how you would do that.

Query a Connected System from a Driver not Connected to that System

User App has been doing this through the User Application driver for a long time when it does Code map refreshes, it injects queries for valued entitlements, so they can show you the possible values when you assign statically assign that specific value of the entitlement to a Resource.

There are all sorts of interesting uses for this if you start thinking about it. For example, if your Active Directory has a value not synced to the IDV, you can get it on demand in the AD driver itself. But what if you have a database driver that needs to get that info, but you do not wish to sync it for some reason. You could have your DB driver inject the appropriate query into the AD driver and get the response you want back. (Sure in that example you could also have done an ECMA LDAP query or other ways, but this is just one simple example).

If you think about what I just said, it seems like somehow we need to bootstrap this all together and get a Web Application on Server1, a database/application on Server2, and two different IDM drivers running on possibly two more servers talking to each other in a coordinated fashion.

As you can imagine, you could have the install time handle all this, and just ask for all the info in each install so the pieces can connect. I still think that might have been the simpler way to do it. Sort of mutual handshake. Reporting WAR gets told where the IDV is, where the EAS is, and where the drivers are listening. The EAS gets told where Reporting is, where the IDV is, and where the drivers are listening. The drivers get told where the EAS is, where Reporting is running and pick IP's to listen on.

In some ways that is done, but a few of those steps are skipped. Rather the way this all gets folded together is that:
EAS - gets told where the Web app is during install.
Web App - gets told where EAS is during install
DCS driver - told where Web app is during configuration.
MSG driver - just listens.

When the DCS driver starts, it collects from the tree info about itself and the MSG driver. It then makes a call to the Reporting web application asking if it is registered (Based on its eDir object GUID, if you delete and reimport, same name, same associations, it has a different GUID so no joy there). If you select the GCV setting to register the MSG driver, it also sends the info on where the MSG driver is, and what IP it is listening on.

But there is a bug, I think in this issue. I was upgrading an existing IDM 4.02 system with no reporting to 4.5.2 with Reporting. I think we did everything right, but when we start the DCS driver it tries to register the DCS driver (so far so good) but also the MSG Driver (since I said yes to the GCV) and it fails, in the IMDRPT-CORE.war log (which is the web app server, Tomcat in this case, so catalina.out) as follows:


2015-12-08 11:59:29,698 [http-bio-8443-exec-6] ERROR com.novell.idm.rpt.core.server.service.IDVManagerService- [RPT-CORE] Error registering the DCS driver with dn: cn=data collection service,cn=idm361,ou=services,o=acme, Idv address: 10.1.227.19, Reason: Manager system collector host/address is required

Hmm, so if I read that correctly it is saying that it cannot register the DCS driver, (with the provided DN, from the IDV Address) because a host/address is required. Hmm. We found that in the DCS driver, we could change the "idv-address" GCV and the error would return the same error, different host name. We made sure /etc/hosts on all the servers could resolve this IP to a DNS and reverse.

On a side note, when you start poking around, you will see a number of GCV's are duplicated in the driver configuration. If you are not aware, this uses an neat GCV type called gcv-ref, which is not really well documented. It is meant for this occasion. If a setting is in the driver configuration, it is easy for the Shim to read them. If the setting is in a GCV it is easy for Policy to read them. If you need to read them in both, it is lightly painful in the shim or policy to do it. Therefore it is just plain simpler to have the same variable names in both. But who wants to maintain two in dependant issues that need to stay in sync.

Thus what you do is define it as a GCV normally as a GCV. Whatever type you need. Then in the driver configuration XML, which is the same DTD as the GCV XML, you reference it as:

<gcv-ref driver-param-name="register-msgw-drv" name="drv.registration.msgw.register"/>

Thus there is a parameter in the driver configuration available, and a GCV depending on how and where you need to use the information. Clever. You will see this a lot in modern driver configs.

Back to our issue, none of that helped. So next, look at the trace, what is the DCS driver doing? Tried level 3, and 25, same basic trace. Trace says:

[12/08/15 15:21:02.517]:dcs ST:DCSSubscriberShim: DCSREGTRACE: msgw-drv-ssl value: false
[12/08/15 15:21:02.517]:dcs ST:DCSSubscriberShim: DCSREGTRACE: msgw-drv-use-keystore value: false
[12/08/15 15:21:02.517]:dcs ST:DCSSubscriberShim: pIT: Trying RESTConnection...
[12/08/15 15:21:02.517]:dcs ST:DCSSubscriberShim: RTD:: Config param DriverGUID: 500A4DB3-44BE-4415-3499-B34D0A50BE44
[12/08/15 15:21:02.518]:dcs ST:DCSSubscriberShim: RTD:: Attempting a GET using driver GUID :https://www.sdev.acme.com:443/IDMRPT-CORE/rpt/idvs/guid/500A4DB3-44BE-4415-3499-B34D0A50BE44
[12/08/15 15:21:02.711]:dcs ST:DCSSubscriberShim: RTD:: Response Status is :200
[12/08/15 15:21:02.711]:dcs ST:DCSSubscriberShim: RTD:: This driver is not registered with the DCS.
[12/08/15 15:21:02.711]:dcs ST:DCSSubscriberShim: RTD:: Attempting to Register the current driver to DCS
[12/08/15 15:21:02.712]:dcs ST:DCSSubscriberShim: formEventJSON: key value: DriverGUID
[12/08/15 15:21:02.712]:dcs ST:DCSSubscriberShim: formEventJSON: key value: IdvName
[12/08/15 15:21:02.712]:dcs ST:DCSSubscriberShim: formEventJSON: key value: DriverDn
[12/08/15 15:21:02.712]:dcs ST:DCSSubscriberShim: formEventJSON: key value: IdvGUID
[12/08/15 15:21:02.712]:dcs ST:DCSSubscriberShim: formEventJSON: key value: IdvAddress
[12/08/15 15:21:02.713]:dcs ST:DCSSubscriberShim: formEventJSON: key value: IdvDescription
[12/08/15 15:21:02.713]:dcs ST:DCSSubscriberShim: formEventJSON: key value: CollectorPassword
[12/08/15 15:21:02.713]:dcs ST:DCSSubscriberShim: formEventJSON: key value: CollectorAccount
[12/08/15 15:21:02.713]:dcs ST:DCSSubscriberShim: formEventJSON: key value: IDMEdition
[12/08/15 15:21:02.714]:dcs ST:DCSSubscriberShim: formEventJSON: key value: CollectorEnabled
[12/08/15 15:21:02.714]:dcs ST:DCSSubscriberShim: formEventJSON: key value: DriverScope
[12/08/15 15:21:02.714]:dcs ST:DCSSubscriberShim: formEventJSON: key value: DriverSetGUID
[12/08/15 15:21:02.714]:dcs ST:DCSSubscriberShim: formEventJSON: key value: DriverName
[12/08/15 15:21:02.714]:dcs ST:DCSSubscriberShim: JSON Trace suppressed for security reasons
[12/08/15 15:21:02.837]:dcs ST:DCSSubscriberShim: RTD:: Response JSON data returned from POST: {"Fault":{"Code":{"Value":"Sender","Subcode":{"Value":"InternalExceptionOccured"}},"Reason":{"Text":"com.novell.
idm.rpt.core.server.spi.exception.IDVException: com.novell.idm.rpt.core.server.spi.exception.IDVException"}}}
[12/08/15 15:21:02.838]:dcs ST:DCSSubscriberShim: RTD:: Response status: 489
[12/08/15 15:21:02.838]:dcs ST:DCSSubscriberShim: RTD:: The data collection service could not process the POST call. Reason: com.novell.idm.rpt.core.server.spi.exception.IDVException: com.novell.idm.rpt.core .server.spi.exception.IDVException
[12/08/15 15:21:02.838]:dcs ST:DCSSubscriberShim: REST error type: R


Now lets pick that apart:

[12/08/15 15:21:02.517]:dcs ST:DCSSubscriberShim: pIT: Trying RESTConnection...
[12/08/15 15:21:02.517]:dcs ST:DCSSubscriberShim: RTD:: Config param DriverGUID: 500A4DB3-44BE-4415-3499-B34D0A50BE44
[12/08/15 15:21:02.518]:dcs ST:DCSSubscriberShim: RTD:: Attempting a GET using driver GUID :https://www.sdev.acme.com:443/IDMRPT-CORE/rpt/idvs/guid/500A4DB3-44BE-4415-3499-B34D0A50BE44
[12/08/15 15:21:02.711]:dcs ST:DCSSubscriberShim: RTD:: Response Status is :200
[12/08/15 15:21:02.711]:dcs ST:DCSSubscriberShim: RTD:: This driver is not registered with the DCS.


So the first thing it does is using the GUID of the DirXML-Driver object, try a REST call to get the info about this DCS driver. Gets back a response that this driver does not exist. Ok, this tells us several things.
The URL we are using for our REST Endpoint works, does not have a DNS problem, does not have a certificate problem, nor a firewall problem. Thus this is an incredibly useful non-error message.

[12/08/15 15:21:02.711]:dcs ST:DCSSubscriberShim: RTD:: Attempting to Register the current driver to DCS


Ok, so this is the part I care about. Next it tells us the key values it is trying to getting in JSON format.

Notice that there is no manager address. There is an IdvAddress, which as noted above when I change it, changes in the error message, so I know I have the correct field.

The line that is maddening is:
[12/08/15 15:21:02.714]:dcs ST:DCSSubscriberShim:  JSON Trace suppressed for security reasons


Drat! Yes, there is a password, but I would prefer that at a sufficiently high enough trace level they should override that and just plain show it. (Enhancement request? Heck I would accept even only at a ridiculous odd level, like 42, if they wanted to make it harder to figure out).

To keep the interesting stuff together, here is how it looks when you sort of succeed:
[12/08/15 16:02:03.808]:dcs ST:DCSSubscriberShim:  Current JSON Data is :--------->
[12/08/15 16:02:03.809]:dcs ST:DCSSubscriberShim: {"DriverGUID":"500A4DB3-44BE-4415-3499-B34D0A50BE44","IdvName":"ACME-DEV-IDV","DriverDn":"cn=data collection service,cn=idm361,ou=services,o=acme","IdvGUID":"DF2E8E19-08F8-0c4d-93A8-DF2E8E1908F8","IdvAddress":"10.1.227.19","IdvDescription":"Acme dev IDV","IDMEdition":"Advanced","CollectorEnabled":"false","DriverScope":[{"BaseDn":"\/"}],"DriverSetGUID":"4661433F-A640-104a-8C99-4661433FA640","DriverName":"Data Collection Service"}
[12/08/15 16:02:04.114]:dcs ST:DCSSubscriberShim: RTD:: Response JSON data returned from POST: {"Status":"OK","UUID":"9caed06a03a4481697f3f69dbdd50fb5"}
[12/08/15 16:02:04.115]:dcs ST:DCSSubscriberShim: RTD:: Response status: 200
[12/08/15 16:02:04.115]:dcs ST:DCSSubscriberShim: RTD:: DCS Driver UUID = 9caed06a03a4481697f3f69dbdd50fb5
[12/08/15 16:02:04.115]:dcs ST:DCSSubscriberShim: RTD:: Status 200:Success ------------------------> Driver Registed to DCS


I will explain how I got success later but that JSON formats nicer as:

{
"DriverGUID":"500A4DB3-44BE-4415-3499-B34D0A50BE44",
"IdvName":"ACME-DEV-IDV",
"DriverDn":"cn=data collection service,cn=idm361,ou=services,o=acme",
"IdvGUID":"DF2E8E19-08F8-0c4d-93A8-DF2E8E1908F8",
"IdvAddress":"10.1.227.19",
"IdvDescription":"Acme dev IDV",
"IDMEdition":"Advanced",
"CollectorEnabled":"false",
"DriverScope":[
{
"BaseDn":"\/"
}
],
"DriverSetGUID":"4661433F-A640-104a-8C99-4661433FA640",
"DriverName":"Data Collection Service"
}



Hmm, now that I look at that I wonder, why an empty BaseDN, I was pretty sure I had set one. Oh well.

Now why did I get it to work and show the values, and other times not get it to work and not show the values? Well if you look at the list of attributes above, the formEventJSON lines, they differ in three attributes.

[12/08/15 15:21:02.713]:dcs ST:DCSSubscriberShim: formEventJSON: key value: CollectorPassword
[12/08/15 15:21:02.713]:dcs ST:DCSSubscriberShim: formEventJSON: key value: CollectorAccount
[12/08/15 15:21:02.714]:dcs ST:DCSSubscriberShim: formEventJSON: key value: CollectorEnabled


The change I made to get it to work was to disable the GCV drv.registration.msgw.register which is called Register Managed Service Gateway. You will recall in my preamble, I discussed how DCS writes to the DB to define the IDV that is connecting, and then it writes the MSG driver connection info so EAS/Reporting can reach out and get data. This turns off sending information about the MSG driver and just registers the DCS, which then completed to succession. I assume this follows a different code path that does not require the missing data and thus succeeds.

I would send the MSG info, which includes a username and password, so the shim trace hid the output. When not registering the MSG driver it works.

The bug that I think is here, is because there is no collector IP sent in the JSON, and if you look in the RPT WAR once it deploys you will see that they check for the collector address, and if it is missing they set it to the IDV address which makes a lot of sense. Except that just before that, they validate the collector address, and if it is missing throw the error 489 we got above. Thus I think the bug is they got the ordering wrong in the Reporting WAR. The fix looks pretty easy.

Now why did this not get caught before? I think if you are just upgrading you would be fine. But as I look at 4.5 and 4.5 SP1 it looks like similar issues.

A publisher channel event on my DCS driver reports:
<product build="20141001_0729" instance="Data Collection Service" version="4.0.0.6">


So that is an older driver shim, but when I look at the patch of 4.0.06 for IDM 4.5, I see the text:
"NOTE: This patch is not needed on IDM 4.5 because this patch contains the same files which were shipped with IDM 4.5 Standard and Advanced Editions."


So this should be the 4.5.2 version. I double checked and the SP1 and SP2 patches do not include a newer version of that the dcsshim.jar, nor an RPM package to update it.

I am not quite sure how to get this fixed, so I will open an SR about it, but you can at least work around it to the point of getting the bare minimums of Reporting working if you run into this issue.

Labels:

How To-Best Practice
Comment List
Related
Recommended