Saturday, February 5, 2011

OIM Child Table manipulation

We have built a staging system to process the user requests before forwarding them to OIM. With this system, users may choose to add/remove a user from an AD group. After the staging system validates the request according to business rules, it generates a flat file with the following format:
Action(Add/Remove)*User name*AD Group Name.

After that we created a schedule task to parse this file then add or remove the group from the specified user. The schedule task will notify all users entered in “Recipients” attribute. And here is the code for this schedule task:
 import java.io.BufferedReader;  
 import java.io.FileReader;  
 import java.util.HashMap;  
 import com.thortech.util.logging.Logger;  
 import Thor.API.tcResultSet;  
 import Thor.API.Operations.tcFormInstanceOperationsIntf;  
 import Thor.API.Operations.tcITResourceInstanceOperationsIntf;  
 import Thor.API.Operations.tcUserOperationsIntf;  
 import com.thortech.xl.dataaccess.tcDataProvider;  
 import com.thortech.xl.dataobj.util.tcEmailNotificationUtil;  
 import com.thortech.xl.scheduler.tasks.SchedulerBaseTask;  
 public class ADGroupOperation extends SchedulerBaseTask  
 {  
   private static Logger logger = Logger.getLogger(“MYSCHTASKS”);  
   private tcUserOperationsIntf userOperIntf = null;  
   private tcFormInstanceOperationsIntf formIntf = null;  
   private tcITResourceInstanceOperationsIntf itResObj;  
   private tcEmailNotificationUtil sendMail;  
   private static final String strClass = “ADGroupOperation”;  
   private String username, action, userName, ADGroup;  
   private String splitarr[] = new String[3];  
   private long objKey, childFormKey, usrKey, procKey;  
   public void init()  
   {  
     final String strMethod = “Init()”;  
     try  
     {  
       logger.info(“Starting AD Group reconciliation”);  
       tcDataProvider db = super.getDataBase();  
       sendMail = new tcEmailNotificationUtil(db);  
       userOperIntf =  
       (tcUserOperationsIntf)getUtility(“Thor.API.Operations.tcUserOperationsIntf”);  
       formIntf =(tcFormInstanceOperationsIntf)getUtility( “Thor.API.Operations.tcFormInstanceOperationsIntf”);  
       tcEmailNotificationUtil sendMail = new tcEmailNotificationUtil();  
       itResObj = (tcITResourceInstanceOperationsIntf)getUtility(“Thor.API.Operations.tcITResourceInstanceOperationsIntf”);  
       HashMap hashmap1 = new HashMap();  
       hashmap1.put(“IT Resources.Name”,”Email Server”);  
       tcResultSet emailServerITRes = itResObj.findITResourceInstances(hashmap1);  
       long svrKey = emailServerITRes.getLongValue(“IT Resources.Key”);  
       tcResultSet emailServerConnParams = itResObj.getITResourceInstanceParameters(svrKey);  
       for(int i = 0; i < emailServerConnParams.getTotalRowCount(); i++)  
       {  
         emailServerConnParams.goToRow(i);  
         String s1 = emailServerConnParams.getStringValue(“IT Resources Type Parameter.Name”);  
         if(s1.trim().equals(“User Login”))  
         {  
           username= emailServerConnParams.getStringValue(“IT Resources Type Parameter Value.Value”);  
           logger.debug(“Sender = ” + username);  
           if (username.equals(“”))  
           {  
             logger.debug(“Sender not provided”);  
           }  
         }  
       }  
     }  
     catch (Exception ex)  
     {  
       logger.error(“Exception in ” + strClass + “.” + strMethod + “: “, ex);  
     }  
   }  
   public void execute()  
   {  
     try  
     {  
       BufferedReader readbuffer = new BufferedReader(new FileReader(getAttribute(“File name”)));  
       String strRead;  
       StringBuilder body = new StringBuilder();  
       body.append(“The following Errors have occured while performing AD group reconciliation: \n\n”);  
       int failed = 0;  
       while ((strRead=readbuffer.readLine())!= null)  
       {  
         try  
         {  
           splitarr = strRead.split(“\\*”);  
           action = splitarr[0];  
           userName = splitarr[1];  
           ADGroup = splitarr[2];  
           if (splitarr[0]== null || splitarr[1]== null || splitarr[2] == null) continue;  
           if (action.equalsIgnoreCase(“add”) || action.equalsIgnoreCase(“revoke”))  
           {  
             HashMap userHash = new HashMap();  
             userHash.put(“Users.User ID”, userName);  
             tcResultSet usrSet = userOperIntf.findUsers(userHash);  
             int m = usrSet.getRowCount();  
             if (m > 0 )  
             {  
               for (int n = 0 ; n < m ; n ++)  
               {  
                 usrSet.goToRow(n);  
                 if (! “Deleted”.equalsIgnoreCase(usrSet.getStringValue(“Users.Status”)))  
                 {  
                   usrKey= usrSet.getLongValue(“Users.Key”);  
                   boolean group_found = false;  
                   tcResultSet objects = userOperIntf.getObjects(usrKey);  
                   for (int j = 0; j < objects.getRowCount(); j++)  
                   {  
                     objects.goToRow(j);  
                     String objName = objects.getStringValue(“Objects.Name”);  
                     if(objName.equalsIgnoreCase(“AD User”))  
                     {  
                       procKey = objects.getLongValue(“Process Instance.Key”);  
                       objKey = objects.getLongValue(“Objects.Key”);  
                       long parentformkey = formIntf.getProcessFormDefinitionKey(procKey);  
                       int parentformver = formIntf.getProcessFormVersion(procKey);  
                       tcResultSet childforms = formIntf.getChildFormDefinition(parentformkey, parentformver);  
                       String plChildTableName = childforms.getStringValue(“Structure Utility.Table Name”);  
                       long formkey = childforms.getLongValue(“Structure Utility.Child Tables.Child Key”);  
                       tcResultSet childFormData = formIntf.getProcessFormChildData(formkey, procKey);  
                       for (int k = 0 ; k < childFormData.getRowCount();k++)  
                       {  
                         childFormData.goToRow(k);  
                         if (childFormData.getStringValue(“UD_ADUSRC_GROUPNAME”).equalsIgnoreCase(ADGroup))  
                         {  
                           childFormKey = childFormData.getLongValue(plChildTableName + “_KEY”);  
                           group_found = true;  
                         }  
                       }  
                       if (action.equalsIgnoreCase(“revoke”) && group_found)  
                       {  
                         logger.debug(“Currently removing user \’” + userName + “\’ from \’” + ADGroup + “\’ AD group”);  
                         formIntf.removeProcessFormChildData(formkey, childFormKey);  
                         logger.debug(“Successfully removed user \’” + userName + “\’ from \’” + ADGroup + “\’ AD group”);  
                       }  
                       else if (action.equalsIgnoreCase(“revoke”) && ! group_found)  
                       {  
                         logger.debug(“Currently removing user \’” + userName + “\’ from \’” + ADGroup + “\’ AD group”);  
                         logger.debug(“Could not remove the user \’” + userName + “\’ from group \’” + ADGroup + “\’. The user is not a member of the group.”);  
                         body.append(“- Could not remove the user \’” + userName + “\’ from group \’” + ADGroup + “\’. The user is not a member of the group. \n”);  
                         failed+=1;  
                       }  
                       else if (action.equalsIgnoreCase(“add”) && ! group_found)  
                       {  
                         HashMap groupHash = new HashMap();  
                         groupHash.put(“UD_ADUSRC_GROUPNAME”, ADGroup);  
                         formIntf.addProcessFormChildData(formkey, procKey, groupHash);  
                         logger.debug(“Successfully added user \’” + userName + “\’ to \’” + ADGroup + “\’ AD group”);  
                       }  
                       else if (action.equalsIgnoreCase(“add”) && group_found)  
                       {  
                         logger.debug(“Could not add user \’” + userName + “\’ to AD group \’” + ADGroup + “\’. The user is already a member of the group.”);  
                         body.append(“- Could not add user \’” + userName + “\’ to AD group \’” + ADGroup + “\’. The user is already a member of the group. \n”);  
                         failed+=1;  
                       }  
                     }  
                   }  
                 }  
               }  
             }  
             else  
             {  
               logger.debug(“User not found ” + userName);  
               body.append(“- User not found ” + userName +”\n”);  
               failed+=1;  
             }  
           }  
         }  
         catch (Exception e)  
         {  
           logger.error(“Error in ADGroupOperation/execute: “, e);  
           continue;  
         }  
       }  
       if (failed > 0)  
       {  
         sendMail.setBody(body.toString());  
         sendMail.setSubject(“AD group reconciliation failure”);  
         sendMail.setFromAddress(username);  
         String splitarr[] = getAttribute(“Recipients”).split(“,”);  
         for (int j = 0 ; j < splitarr.length; j++)  
         {  
           sendMail.sendEmail(splitarr[j]);  
         }  
       }  
       readbuffer.close();  
     }  
     catch (Exception e)  
     {  
       logger.error(“Error in ADGroupOperation/execute: “, e);  
     }  
   }  
 }  

10 comments:

  1. This comment has been removed by the author.

    ReplyDelete
  2. Hi Madhu,

    Actually AD connector provides the interface between OIM and Active Directory. Any insertion or deletion of records in the child table will trigger the corresponding process task. The task will call the method to reflect the action in AD.

    Hope this answers your question.

    ReplyDelete
  3. Thanks for the reply..

    I m working with AD Connector in which on one screen there is a functionality to choose AD Group and assign it to user.

    In ur post,u mentioned about generation of flat file when user is getting assigned to a AD Group.

    I assume,in real AD Group is not getting assigned at that instant.You are running a schedule task to assign/remove ad group to a user which read flatfile

    I am looking for how u implemented this.

    Plz provide any oim documents that are available with you,if possible.

    Regards,
    Madhu

    ReplyDelete
  4. The flow is like this:

    Managers assigns AD groups in addition to other assignments using a form that is sent to OIM mailbox -> The staging system reads the mailbox and generates a flat file containing the user name and AD groups -> A scheduled task reads the flat file and modifies the child table -> Once the child table is modified, AD connector completes the action in active directory.

    I'm afraid I can't share the code or the documentation as this would violates the NDA.

    ReplyDelete
  5. Hi,

    I M trying to explore the functionality of your AD Group Assignment schedule Task.I need help to create schedule task in OIM.

    In the step 2 of creation of Schedule task it is asking about attribute.

    Step 2 : Define Scheduled Task Attributes


    --------------------------------------------------------------------------------




    Define attributes for CustomADGroupAssignRecon.


    Attribute With



    Can You tell me what I need to specify.

    Thanks
    Madhu

    ReplyDelete
  6. Hi,

    I resolved the issue.

    I'm afraid I can't share the code or the documentation as this would violates the NDA.

    I m not looking for any code or documentation.I m just looking for any material in oim, which helps me to improve myself in OIM Implementation.


    Thank you very much

    Regards,
    Madhu

    ReplyDelete
  7. Hi Madhu,

    I will prepare couple of documents and email them to you this weekend.

    ReplyDelete
  8. This comment has been removed by the author.

    ReplyDelete
  9. Thank You Very Much...

    I will be waiting for your Mail...

    Have a nice day

    Regards,
    Madhu

    ReplyDelete
  10. Hi Selim,
    I have to add three data in child form and if data is updated in oim than i have to reflect it in AD.i have written the code and it is working fine when add and remove are used separately. But i have to remove all the data and again have to add new data. when i combine both tc API call itself again. it first delete and than add data in AD but again it call remove function without finishing the class. so no data being added in ad. Please help me...

    ReplyDelete