IBM Security Verify

 View Only

IBM Tivoli Directory Integrator Proxy Workflow extension for IBM Security Identity Manager

By Konstantin Chistyakov posted Wed October 16, 2019 01:00 PM

  

By Konstantin Chistyakov and Franz Wolfhagen

IBM Tivoli Directory integrator (ITDI) has been known as a flexible and feature rich integration tool for several decades now. ITDI has facilitated numerous different implementations. Some of them a pretty straight forward and some of them are very complicated and interesting in their approach. The purpose of this post is to recap one of the old implementations and think about how this idea can be reused in the modern-day system context.

ITDI provides com.ibm.di.api.remote package which consists of interfaces designed for handling TDI Assembly Lines remotely. An Assembly Line is a set of connected components glued together to move the data between integration source and destination. The components may be connectors, attribute maps, scripts etc. The data flowing through these components is represented as an Entry object. Entries carry attributes with values and can be represented as Lists or Maps in the scripting or programming languages.

The Remote API ITDI package can be used to call remote Assembly Lines within the source application and retrieve data from or push data to the target application. One of the interesting uses of this package is creating a proxy service to make synchronous calls to different target systems. The main use case for such a service would be to simplify and standardize integrations with different target systems. Proxy would eliminate the need to instantiate each Assembly Line separately by providing source application with a single point of integration for all target applications that are using synchronous calls. Although there might be many different applications for this proxy, the one that we will be looking into is calling a remote ITDI Assembly Line through a proxy from IBM Security Identity Manager (ISIM) Workflow.

IBM Security Identity Manager, previously known as IBM Tivoli Identity Manager, is a well-known Identity Management tool with emphasis on provisioning and identity lifecycle. ISIM has powerful workflow engine, which can be used in every stage of Identity Lifecycle from creation to deletion. Workflows can be used to build identities, fill the missing identity data, verify existing identity data from external sources and in many other use cases. External applications are represented in ISIM workflow engine by com.ibm.itim.workflow.application interface. In order to utilize this interface, the workflow extension needs to be developed and registered as a separate shared library with WebSphere Application Server (WAS), which runs the ISIM application. ITDI server and configuration details can be placed in the property file, which will be read by the workflow extension. The overall high-level architecture of the solution looks like this:

ISIM workflow will provide the extension (instance of workflow application interface) with dataset, workflow context and Assembly Line to call. Extension then will perform data transformation, read property file and call remote Assembly Line through the instance of ITDI remote assembly line handler interface. Assembly Line will make a call to the target application and get the return message. This message will be passed to extension as a return object. Extension will pass the return object as a Map back to the workflow engine.

There are many ways to write this extension, but in at the bare minimum you will need the following ISIM API classes:

  • ibm.itim.common.AttributeValue
  • ibm.itim.workflow.application.WorkflowApplication
  • ibm.itim.workflow.application.WorkflowExecutionContext
  • ibm.itim.workflow.model.ActivityResult

This list does not include classes needed to perform logging, such as for instance com.ibm.itim.logging.SystemLog. To work with ITDI Assembly Lines the following classes needs to be imported in the extension:

  • ibm.di.api.DIException
  • ibm.di.api.remote.AssemblyLineHandler
  • ibm.di.api.remote.ConfigInstance
  • ibm.di.api.remote.Session
  • ibm.di.api.remote.SessionFactory
  • ibm.di.entry.Entry

In addition to these classes you will also need classes from java.io package to read property file, classes from java.rmi package to handle Remote Method Invocation (RMI) calls to ITDI server and classes from java.util package to handle List and Map datasets.

Extension development will start by implementing WorkflowApplication interface, something like this:

public class TDIProxyExtension implements WorkflowApplication {

Inside the extension you will need to instantiate context for the workflow, setup and read property file, provide methods for data conversion, handle errors and create session object and call external Assembly Line. Property file must have RMI details of the ITDI server, which are IP address, port and the name of the configuration file (XML), which contain the configuration of the Assembly Line. The name of the Assembly Line to run will come from the workflow. Magic will happen in the method which will be running the Assembly line. This method takes as an input the name of the Assembly Line to run from the configuration file and dataset from the workflow in the List format. Method should be defined in the similar way as in this example:

public ActivityResult runAL(String configName, List data) {

This method will take the data from the workflow in the List form and transform it to the Entry object, so an Assembly Line can process it. The data transformation can be done with the help of methods like the following one:

private Entry list2entry(List<AttributeValue> avs) {
        Entry entry = new Entry();
        // Convert the List to an entry
        for (Iterator<AttributeValue> i = avs.iterator(); i.hasNext();) {
            AttributeValue av = i.next();
            entry.newAttribute(av.getName());
            for (Iterator<Object> x = av.getValues().iterator(); x.hasNext();) {
                Object val = x.next();
                entry.getAttribute(av.getName()).addValue(val);
            }
        }
        return entry;
}

Next steps will be to get the ITDI server details and initiate the session with the server. Session can be initiated as shown in the following example:

private Session getSession(String server, int port)
            throws NotBoundException, MalformedURLException, RemoteException,
            DIException {
        l("Obtaining a sessionfactory");
        SessionFactory sessionFactory = (SessionFactory) Naming.lookup("rmi://"
                + server + ":" + port + "/SessionFactory");
        l("Creating Session");
        return sessionFactory.createSession();
}

When the session is successfully initiated, extension can start and instance of the Assembly Line as shown in the following code:

ConfigInstance configInstance = session.getConfigInstance(configUID);
// Starting AssemblyLine ALName in Manual mode
AssemblyLineHandler assemblyLineHandler = configInstance.startAssemblyLineManual(ALName, null);
// Running an iteration
result = assemblyLineHandler.executeCycle(entry);
// Closing AssemblyLine
assemblyLineHandler.close();

Where session is the session object defined by the previous method and configUID is the unique ID of the running configuration in ITDI server. Result entry will be transformed to Map object and returned to the workflow. Next step will be to either pack developed extension to the java JAR file manually or export it from IDE if it was used for developing the extension.

When extension is ready for testing it needs to be registered with Application Server, ISIM application and in TDI environment. Example of calling workflow also needs to be configured in ISIM. First step would be to add ITDI proxy extension to the ISIM application. That means extension JAR file, for instance TDIProxyExtension.jar, needs to be added to <ITIM_HOME>/custom directory on ISIM host. One must also ensure that new JAR is added to WAS shared library. Related property file needs to be added to <ITIM_HOME>/data directory. Here is an example of such file:

#Config file for the TDI Proxy Extension
#Hostname/address of the machine running the TDI server
rmiServer   = 10.100.100.25
#RMI Port on the TDI Server
rmiPort     = 1099
#The TDI Config file to run - path is local to the TDI Server, NOT the ITIM machine
configFile  = C:/Program Files/IBM/TDI/V7.0/remoteTest.xml
#Some unique ID to identify the running config on the TDI server. This must be unique for the server
#Config instances running.
configUID   = ITIM_TDI_Extension

In the ISIM environment workflowextensions.xml and scriptframework.properties configuration files need to be reconfigured to support the new extension. Also, ITDI API JAR files needs to be added to the <ITIM_HOME>/lib directory. Here is an example of workflowextensions.xml configuration for the new extension:

<ACTIVITY ACTIVITYID="TDIProxyExtension" LIMIT="0">
 <IMPLEMENTATION_TYPE>
  <APPLICATION CLASS_NAME="com.ibm.examples.tdiproxyextension.TDIProxyExtension" METHOD_NAME="runAL"/>
 </IMPLEMENTATION_TYPE>
  <PARAMETERS>
    <IN_PARAMETERS  PARAM_ID="alName"   TYPE="String"/>
    <IN_PARAMETERS  PARAM_ID="data"     TYPE="List"/>
    <OUT_PARAMETERS PARAM_ID="dataOut"  TYPE="Map"/>
  </PARAMETERS>
</ACTIVITY>

Important note that class name specified here should be the same as in the extension JAR file and runAL method must be found within TDIProxyExtension class. To enable support for the extension in the ISIM workflow engine add the following rows to the scriptframework.properties file:

ITIM.java.access.lang=java.lang.*
ITIM.java.access.util=java.util.*
ITIM.java.access.itimcommon = com.ibm.itim.common.*

The following ITDI API files need to be added to <ISIM_HOME>/lib directory:

  • jars/common/diserverapi.jar
  • jars/common/diserverapirmi.jar
  • jars/common/miconfig.jar
  • jars/common/miserver.jar
  • jars/common/mmconfig.jar
  • jars/common/tdiresource.jar
  • jars/3rdparty/others/log4j-1.2.15.jar
  • jars/3rdparty/IBM/icu4j_4_2.jar
  • jars/3rdparty/IBM/ITLMToolkit.jar
  • jars/3rdparty/IBM/jlog.jar

In addition to that diserverapirmi.jar file needs to be added to the same shared library as the extension JAR file. This will enable extension to user ITDI remote AL Handler interface. After that new extension should be available and ready to use in the ISIM workflows.

To test the implementation a simple Assembly Line can be setup on the ITDI side. This Assembly Line can for instance receive the certain attributes from the workflow then modify them and send attributes back to the workflow. Ensure that ISIM and ITDI server can talk to each other by setting up secure communication properties or by disabling the in test or PoC environments.

To test or configure extension in the ISIM server you will need a couple of script components and the extension component to activate the workflow extension. In addition to that Assembly Line name, initial dataset and returned dataset need to be added to global properties of the workflow. The following picture shows and example of such configuration:


First script will set up the attribute list, which will be sent to the ITDI server. The script might look something like this:

//Decide which AL to Run. The config file (rs.xml) is loaded from the properties file, but a config file can contain
//more than one AssemblyLine. This parameter tells the extension which specific AL you wish to execute
var alName = "Test";
aLName.set(alName);

//Create a list to work with
var myList = new java.util.ArrayList();

//Create an attribute value
var av = new com.ibm.itim.common.AttributeValue("Hello","World!");
//It supports multiple values too - let's add another!
av.addValue("World-2!");
//Can even use more attributevalues (This is why we use a list ;-)
var av2 = new com.ibm.itim.common.AttributeValue("More Attributes","Yes - please");

//Add our attributes to the list
myList.add(av);
myList.add(av2);

//Save it back to the global variable. ListOfData is defined in WF Properties as a List of
//AttributeValues
ListOfData.set(myList);

When dataset is added to workflow properties it is time to configure the extension itself. The example of such configuration is shown in the picture below:


The second script component will receive the output from the Assembly Line and parse it so that data can be used further in the workflow. In Properties, a global Map has been defined, and in the extension,  we save the output to that Map. This map can now be retrieved with the following code:

var myMap = DataOut.get();

Any value is now accessible through the ITIM JS extensions, meaning that if you know an attribute to exist you can access it directly as a field. For example, if your AL added an attribute called "Now" containing the current date, it would be accessible using the myMap.Now code.

This implementation has been tested originally with ITIM 5.1 (previous version of ISIM) and ITDI 7.0. With small modifications it will run on ISIM 6. However, the concept of the integration might be equally applied to IBM Identity Governance and Intelligence application or any other application which needs to make synchronous calls to number of different target applications, if they provide a way to pass data to the ITDI remote Assebly Line handler.

Useful Links:

ITDI General Concepts:

https://www.ibm.com/support/knowledgecenter/en/SSCQGF_7.1.0/com.ibm.IBMDI.doc_7.1/generaltdiconcepts.htm

ITDI Assembly Line Handler Interface

https://www.stephen-swann.co.uk/javadoc/tdi6.1.1/com/ibm/di/api/remote/AssemblyLineHandler.html

ISIM Workflow Application Interface:

https://www.stephen-swann.co.uk/javadoc/sim6.0/com/ibm/itim/workflow/application/WorkflowApplication.html

Workflow extension example for ISIM:

ISIM ITDI Proxy Extension.zip

Authors:

konstantin.chistyakov@ibm.comFRANZW@dk.ibm.com.




0 comments
65 views

Permalink