Sunday, February 14, 2016

Oracle Internet Directory(OID) - Oracle Identity Manager(OIM) Password sync

OID provided plugins feature by exposing different apis(ospf.jar), which will get triggered on different ldap operations like add,modify,delete etc. at different time like pre or post operation. By using the same we can get the updated password in oid and using OIM apis (UserManager) set the same in OIM in order to make it in sync.


Steps to develop java plugin to sync password in OID and OIM.

1. Develop java code which will take password when any one update the in OID and set that password in oim for appropriate user using OIM apis (UserManager). Compile the code and create the jar of the same. 
While compiling the code make sure that ospf.jar, oimclient.jar and other OIM's jars(as per requirement) should present in CLASSPATH. You will get this jars from OID and OIM machines.

Note : Please make sure that method name should be the same post_modify() as we are going to trigger our plugin post userPassword modified in ldap.
Example:

import javax.naming.directory.BasicAttribute;
import javax.naming.directory.ModificationItem;
import javax.security.auth.login.LoginException;

import oracle.iam.identity.usermgmt.api.UserManager;
import oracle.iam.identity.usermgmt.api.UserManagerConstants;
import oracle.iam.platform.OIMClient;
import oracle.ldap.ospf.LdapBaseEntry;
import oracle.ldap.ospf.LdapModification;
import oracle.ldap.ospf.ModifyLdapOperation;
import oracle.ldap.ospf.PluginDetail;
import oracle.ldap.ospf.PluginFlexfield;
import oracle.ldap.ospf.PluginResult;
import oracle.ldap.ospf.ServerLog;
import oracle.ldap.ospf.ServerPluginAdapter;


public class PasswordSyncPlugin extends ServerPluginAdapter{
    private static final String className = PasswordSyncPlugin.class.getName();
    private static final String USERPASSOWRD = "userpassword";
public OIMClient oimClient;

    public PluginResult post_modify_modify(PluginDetail pluginDetails) throws Exception{
    final String methodName = "#post_modify()"; 
PluginResult pluginResult=new PluginResult();
try{
      ServerLog.log(className + methodName +"Entering into the Password sync plugin");   
PluginFlexfield plgFlexfield = pluginDetails.getPluginFlexfield();
ServerLog.log(className + methodName +"List of flex fields:"+
            plgFlexfield.getFlexfieldNames());                    
String oidUniqueAttr = plgFlexfield.getFlexfield("OIDUniqueAttr");
ServerLog.log(className + methodName +"OID Unique attribue "+ oidUniqueAttr);
LdapBaseEntry ldapBaseEntry = pluginDetails.getLdapBaseEntry();
String uidToBeModify = ldapBaseEntry.getAttribute(oidUniqueAttr).toString(); 
ServerLog.log(className + methodName +"Mofify Operation performed on user :["
                +uidToBeModify.toString()+"]");
String finalUidToModify = null;
if(uidToBeModify != null && !uidToBeModify.equals("")){
String uid [] = uidToBeModify.split(":");
if(uid.lenghth >= 2)
finalUidToModify = uid[1].trim();
}
ModifyLdapOperation opObj = (ModifyLdapOperation)pluginDetails.getLdapOperation();
LdapModification modObj = opObj.getLdapModification();
String newPassword = null;
if (modObj!=null){
        ModificationItem modItem = modObj.getModificationItemAt(0);
         BasicAttribute basicAttr = (BasicAttribute)modItem.getAttribute();
         if ((basicAttr.getID()).equals(USERPASSOWRD)){
             newPassword = (String)basicAttr.get(0);
        if(newPassword != null) 
        ServerLog.log(className + methodName +"Got newly updated password!!");    
         }
      }
 
  //Updating password in OIM
      oimClient = this.connectToOim(plgFlexfield);
if(oimClient != null && finalUidToModify != null){
          UserManager userManager = oimClient.getService(UserManager.class);
          ServerLog.log(className + methodName +"User Manager:"+ userManager);
       userManager.changePassword(UserManagerConstants.AttributeName.USER_LOGIN.getId(),
    finalUidToModify, newPassword.toCharArray(), false);
       ServerLog.log(className + methodName +"Password Updated Successfully in oim for user:"                 + "[" + uidToBeModify + "]");
       if(oimClient !=null){
          oimClient.logout();
    }
}
     }catch(Exception e){
         ServerLog.log(className + methodName +"Exception occured while connecting to the       OIM."+ e.getMessage());
e.printStackTrace();
}
       return pluginResult;
    }
    
    private OIMClient connectToOim(PluginFlexfield plgFlexfield) {
    final String methodName = "#connectToOim()";
    String oimAdminUser = plgFlexfield.getSecuredFlexfield("OIMAdminUser");
String password = plgFlexfield.getSecuredFlexfield("Password");
String oimT3URL = plgFlexfield.getSecuredFlexfield("OIMT3URL");
String authwlConfPath = plgFlexfield.getFlexfield("Authwl_Conf_Path");
String oimInitialContextFactory = "weblogic.jndi.WLInitialContextFactory"; 
String oimAppSrvType = "wls";
ServerLog.log(className + methodName +"OIM Adamin User: "+ oimAdminUser);
ServerLog.log(className + methodName +"OIM t3 URL:"+ oimT3URL);
ServerLog.log(className + methodName +"OIM authwl Conf Path:"+ authwlConfPath);
// set up the environment for making the OIM API invocation
java.util.Hashtable<String, String> env = new java.util.Hashtable<String, String>();
env.put(oracle.iam.platform.OIMClient.JAVA_NAMING_FACTORY_INITIAL,oimInitialContex         tFactory);
env.put(oracle.iam.platform.OIMClient.JAVA_NAMING_PROVIDER_URL, oimT3URL);
System.setProperty("java.security.auth.login.config",authwlConfPath);
System.setProperty("OIM.AppServerType", oimAppSrvType);
System.setProperty("APPSERVER_TYPE", oimAppSrvType);
OIMClient oimclient = new oracle.iam.platform.OIMClient(env);
try {
      oimclient.login(oimAdminUser, password.toCharArray());
ServerLog.log(className + methodName +"Connected to OIM successfully!!!");
} catch (LoginException e) {
ServerLog.log(className + methodName +"Exception occured while connecting to the       OIM."+e.getMessage());
e.printStackTrace();
oimclient = null;
}
return oimclient;
}
}

2. After created the jar please make sure jar file has only two entries - class file of above code and META-INF folder which contains MANIFEST.MF file.
Please add the class name entry (fully qualified along with package name if present) in MANIFEST.MF file like given below.


3. Stop the OID instance and add the above jar at following path of the OID machine.
$ORACLE_HOME/ldap/server/plugin

4. As OID doesn't have OIM's jars in CLASSPATH to add the same copy required jars at any path and use same while adding following entry in opmn.xml file, which is present at
 <OIDInstance Location>/config/OPMN/opmn/opmn.xml


5. Go to Oracle Directory Service Manager (odsm) console and login with admin user and do the following configuration.
http://<host>:<port>/odsm

a.Click on “Create A New Connection”.


      b. Enter the details and click on connect

     c. Once login click on Advanced

    d.Click on new(highlighted in yellow)

      e.Fill up Mandatory and Optional property following details and click on OK

Note :
Ø  Plug-in Package Name - should be the same as jar name
Ø  Plug-in Ldap Operation - should be the ldapmodify as we want to trigger it on modify   Operation
Ø  Plug-in Timing – Should be post as we want post modify.



     f. Set Flex attribute which is retrieved in plugin code(its optional - if want to pass parameter to the plugin). To set this open the same plugin as above and select Optional properties.


6.  Now start the OID instance by running opmnl script which is present at
<OIDInstance Location>/bin

7. Try to modify the userPassword in oid and check it would reflect in OIM

***********************************************************************


If you want to print log statements in above code then needs to enable the logs in OID

Enabling the OID logs:

1.Create file with ldif extension with following entries.
example:
ServerLogOn.ldif

dn: cn=oid1,cn=osdldapd,cn=subconfigsubentry
changetype: modify
replace: orcldebugop
orcldebugop: 16

dn: cn=oid1,cn=osdldapd,cn=subconfigsubentry
changetype: modify
replace: orcldebugflag
orcldebugflag: 268435456

Note: In first line there cn=oid1 because my oid instance name is that. It could be different in your case.
Also you can give different values for orcldebugop and orcldebugflag as per requirement
Please refer following links for the same:

2. Goto follwing path $ORACLE_HOME/bin and execute following command

ldapmodify -h <host> -p <port> -D "cn=orcladmin" -w <password> -f ServerLogOn.ldif

3.Verify log enabled or not using following command

ldapsearch -h <OIDHOST> -p <PORT> -D cn=orcladmin -w <PWD> -b "cn=oid1,cn=osdldapd,cn=subconfigsubentry" -s base objectclass=* orcldebugflag orcldebugop

Disabling the OID logs:

1.Create file with ldif extension with following entries.
example:
ServerLogOff.ldif

dn: cn=oid1,cn=osdldapd,cn=subconfigsubentry
changetype: modify
replace: orcldebugop
orcldebugop: 0

dn: cn=oid1,cn=osdldapd,cn=subconfigsubentry
changetype: modify
replace: orcldebugflag
orcldebugflag: 0

2. Goto follwing path $ORACLE_HOME/bin and execute following command

ldapmodify -h <host> -p <port> -D "cn=orcladmin" -w <password> -f ServerLogOff.ldif