Novell Identity Manager with the Role Based Provisioning Module support an interesting notion called workflows. You can read more about where all the associated bits and pieces for Workflows reside, in this series of articles:
- Introduction to Workflows and PRDs in Identity Manager – Part 1
- Introduction to Workflows and PRDs in Identity Manager – Part 2
The user interface is somewhat hard to use, as there are important things and widgets you need, here there, and everywhere. I wish the UI could be cleaned up, but darned if I know how you would do it. It is a very complex product that needs a lot of stuff shown.
With the addition of the Roles Based Provisioning Model (well ok, it started with the Provisioning version of the User Application, way back in Identity Manager 3, but that’s just a detail), there are really two sides of the house in Identity Manager now. There is the engine side with DirXML Script and Policy, then there is the Provisioning side. They are quite disconnected, with a few inter-connect points. There is the Start Workflow token and some Role management (Add or Remove tokens) on the engine side, along with Roles and Resources being enforced by the Roles and Resources driver. On the Provisioning side there is the ability to read and write to eDirectory through the DAL (Directory Abstraction Layer). There are a number of activities that can do other ‘stuff’ of interest. Additionally there is a SOAP interface into the various Provisioning actions.
While there is a Start Workflow token, at times it would be pretty useful to have a Stop Workflow token. Well, can’t have everything built in, but there is enough functionality to do what is needed. Consider this notion, you call a Start Workflow, passing in the request ID of a workflow, and it makes a SOAP call to cancel that running workflow. Thus you have a Stop workflow event, using the Start Workflow token. The same can be considered for Approving a workflow. It would be nice to have such a token, but until that is available it is pretty straightforward to make a workflow that when passed the request ID will approve the workflow.
To do this, we were able to make a no approval workflow, that when called with the request ID of the running workflow as a parameter, can use an Integration Activity (which makes a SOAP call in a Workflow) will terminate a running workflow. Later we did much the same for Approving a workflow based on the request ID of the running workflow, but that is a story for another article.
Currently, you can use the User Application, log in as a user with the various flows assigned and stop them one by one, by either approving or denying them. Or else you can use iManager with the newer Identity Manager plugins, and cancel workflows. However it is pretty hard in iManager to find the one you are interested in, since not much data is shown to allow you to select. To get to the iManager Workflow view, select Workflows from the left hand side, and you will have to select which User Application driver you are working with since there can be many in a single tree. Then provide credentials of a User App Administrator account (I think this needs the User Application Administrator security level, set by configupdate.sh initially, and via the Administration tab in User Application. I do not think this permission is controlled by the Roles model in RBPM yet. If it were, you would probably need to be a Provisioning Admin to do this task).
The easiest way to find your running workflow is to use a Filter of Status equal to Running. Then look for some detail in the skimpy data presented to find it. You might have to use the Actions menu and select Show Request ID to find it, if all else fails. After all, who does not enjoy hunting down a single object amongst hundreds or thousands of object, using a GUID?
Thus you can see the utility of building a workflow to do this for you in policy. The first thing you would need to do though is modify any workflows you have, to do an Integration Activity (not the SOAP kind) to write back the requestID to some attribute on the User object. Now if you really only have one simple workflow, then a single valued attribute should work. If you have more than one type of workflow you need this to work for, then you probably might want to either track running workflows by workflow type on the user, or else just list all requestID’s in a multivalued attribute. The problem with the latter approach is you might not know which requestID represents the workflow you wish to cancel.
You could use a custom attribute, using path syntax, to store this information. Path syntax has three components. A 32 bit integer which is perfect for holding a CTIME timestamp (CTIME is a count of seconds since Jan 1, 1970 and has a major issue as it runs out of seconds (2 billion of them) sometime in 2037! Y2K37 yay!) so you can know when this was started. There is a DN component, which you can populate with the DN of the workflow, and finally a string component that you could store the request ID in. Make it multivalued and now you can have a record of all running workflows. You should probably make sure to REMOVE it as well, when your workflow completes. Though I do not know how I might do that offhand, for a path syntax attribute. Let your ECMA mojo run wild on that one!
Assume you have that all figured out, and you have stored the request ID, somewhere which you can get in workflow with the ECMA function call
Next up you need to setup a single step, no approval workflow, and between the Start and Finish node, you need to drag in an Integration activity from the palette.
Now to use this, you need to provide a WSDL (Web Services Description Language) file that contains the XML based definitions for what the web service offers. This is actually a pretty cool action, and it about all that is identifiably left of the Silverstream Composer product that Novell acquired way back when. In fact, the other piece is actually the part Novell uses to compile the User Application driver to a JAR file. The Composer tool would generate driver shims, that did what you defined in their Designer tool. It was NOT a pretty UI, and you can see much of its complexity in the PRD’s and specifically in this Integration Activity. Composer had the ability to do XML data mapping graphically (seemingly a perfect fit for Novell’s IDM product line) and had a stack of other classes for converting non-traditional data into XML. Some of those were screen scrapers for old green screen style apps. We used it for a TN3270 mainframe application that runs as a screen scraper. It also could screen scrape an HTML interface which is pretty cool. Though I imagine today’s AJAX and Web 2.0 interfaces would befuddle its ability to scrape.
To get the WSDL from User Application, you login as a User Application administrator, and on the Administration tab (If you do not see the tab, you are NOT an Administrator) and there are 5 different WSDL’s available. You need the Provisioning one, but as long as you are there you might as well get them all. This way you can play with other features as the whim strikes you.
The Integration activity requires you to select a WSDL file, and once you do, you get to pick the function call you wish to use from it. Notice that all you get to do per Integration Activity is one function call. Once you have done this, you right click on the Integration Activity in the Workflow view of the PRD, and a new menu item appears, called Edit Integration Activity. This opens a new tab on the bottom of the screen, called Integration. Once you are in this view it is quite a powerful SOAP tool, and you can do most of your needed testing. There is a “Run” button so you could test the work you have configured in this view. However, if you are not sure what function you need to call, it may be easier to use an external SOAP tool like soapUI (www.soapui.com) instead. With soapUI you can open the WSDL file, see all the functions available, try them out, not being limited to a single function at a time and fiddle around until you have a better idea of what you would like to do. Some WSDLs seem to be better documented internally and externally than others. Having spent a lot of time in the Salesforce.com WSDL, then moving to the User Application WSDL it was somewhat jarring of a difference. I have looked at some other WSDLs and they seem to vary as well. So while the User Application WSDL is not the greatest, it is sufficient.
Now we are at the point of deciding on which function in the WSDL to use. The User Application WSDL in some ways is nicer, in that it has the functionality segmented into 4 different WSDL files, however, that is also a down side as it is easier to manage and work in a single file.
But since this is a provisioning issue, lets assume the function we need is in the Provisioning WSDL. You can see the documentation for the User Application WSDL at: VI Web Service Reference
Here I will be critical and say, the documentation could be a whole lot better. I still find too much ambiguity when I read it. To me, docs should be crystal clear and the authoritative source. When I read it and am unsure of how something works after reading the documentation I consider that inadequate.
Looks like the function we need is called terminateRequest, which thankfully is well named. Opening soapUI, since it is a better exploration tool, lets start testing the function.
The WSDL when looked at in soapUI defines the call as:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://www.novell.com/provisioning/service"> <soapenv:Header/> <soapenv:Body> <ser:terminateRequest> <!--Optional:--> <ser:arg0> 30f1e2ae98ce4f91829df1af5bac6cb4</ser:arg0> <ser:TerminationType>RETRACT</ser:TerminationType> <!--Optional:--> </ser:terminateRequest> </soapenv:Body> </soapenv:Envelope>
The ‘well named’ arg0 (yes I find this naming model, VERY annoying and it is endemic throughout the WSDL) is meant to hold the request ID value. The better named TerminationType can be RETRACT or ERROR. Those values were found in the documentation, which was very helpful.
Next up is the question of how do you login? Well there seem to be a couple of approaches to how web services in general expect authentication. The Salesforce.com approach (since I spent so much time in it recently) is to use a Login function, which returns a session ID of some kind, which is usable for the next 24 hours, and is provided in all ensuing function calls, that provides proof of authentication.
The other major approach is to use standard web based authentication. (I am not sure if this is called Basic auth or something else, but since this is the default in how the SOAP driver works, and the Integration Activity it is good enough to use). In soapUI, there is a little teeny tiny tab at the bottom of the window called Auth, in which a username and password can be provided. In the Integration Activity, you right click on the actual function call line, which is under the Try, then Execute block.
It shows up as WS Interchange: provisioning viaService ProvisioningService at Endpoint location http://IpOfYourWebService/ using Connection 1.
From the context menu select Edit action, on the first tab, you can change the URL of the endpoint. Which is something you would have to do if you were staging this from development to production. Then on the third tab, Connection, you can specify a User ID: and Password: line. This is the same credentials you would use to login to the User Application web interface, as a human. So it is not dotted notation, nor an LDAP DN, rather it should be the simple username, unless your provisioning administrator account is outside the search scope of the User Application for logins. In that case, you might need to use the full LDAP DN. You can watch the login results in the server.log for the User Application to see if it fails or succeeds to login, in order to debug the correct credentials to use.
Now that we have the basic window open, authentication stuff setup and ready to go, it seems like this is a good place to pause and break for part 2, where we will start to work through some of the samples.