Thursday, September 26, 2013

OIM: Audit handler failed

Here is the Error of the day:

Just saw it after restarting OIM Server in one of the environment:

Issue: oracle.iam.platform.async.TaskExecutionException: java.lang.Exception: Audit handler failed
        at com.thortech.xl.audit.engine.jms.XLAuditMessage.execute(XLAuditMessage.java:59)
        at oracle.iam.platform.async.impl.TaskExecutor.executeManagedTask(TaskExecutor.java:122)
        at oracle.iam.platform.async.impl.TaskExecutor.execute(TaskExecutor.java:69)
        at oracle.iam.platform.async.messaging.MessageReceiver.onMessage(MessageReceiver.java:68)
        at sun.reflect.GeneratedMethodAccessor644.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke


Cause: Under Investigation

Wednesday, September 25, 2013

msExchVersion Attribute not supported by OIM Exchange Connector 11.1.1.6.0

While checking the forums, I came across this post where the author was trying to run the target reconciliation using msExchVersion attribute in search filter. The author has OIM 11g BP07 and was using OIM - Exchange Connector 11.1.1.6.0. The environment has multiple version of Exchange Servers i.e., 2007 & 2003.

Just for little background, Exchange 2007 introduced a new user attribute called msExchVersion that tracks the Exchange version a mailbox is created on. This may be useful if you want to manage mailboxes by Exchange version.
Exchange 2003 and earlier = ""
Exchange 2007  = "4535486012416"
Exchange 2010 = "44220983382016"

 
After reading the connector 11.1.1.6.0 documentation, I came to know that only specific attributes can be used in search filter for running limited reconciliation. (Refer Page 75). Here is the list:

The following attributes are supported in the filters:
  • ArchiveQuota
  • ProhibitSendQuota
  • ArchiveWarningQuota
  • Database
  • IssueWarningQuota
  • ProhibitSendQuota
  • ProhibitSendReceiveQuota
  • UseDatabaseQuotaDefaults
  • ExternalEmailAddress
  • DisplayName
  • SimpleDisplayName
  • EmailAddressPolicyEnabled
  • HiddenFromAddressListsEnabled
  • MaxSendSize
  • MaxReceiveSize
  • Name
  • Alias
  • PrimarySmtpAddress
  • RecipientLimits
  • RecipientType
  • WhenChanged
  • CustomAttribute1, CustomAttribute2, and so on up to CustomAttribute15

However, the 11.1.1.5.0 and 9.1.1.7 doesn't specifically mention any list of attributes that can be used in search filter in reconciliation task. So, I think in environment with mixed version of Exchange servers, these two version should be used. 
 
References:
 
  • https://forums.oracle.com/thread/2586016
  • Exchange Reconciliation For Environments With Mixed 2003 and 2007/2010 Servers (Doc ID 1463160.1)
  • Patch 13778888: RELEASE VEHICLE FOR EXCHANGE CONNECTOR 11.1.1.5.0
  • Patch 17198005: RELEASE VEHICLE FOR EXCHANGE CONNECTOR 11.1.1.6.0
 

Patch 17198005: RELEASE VEHICLE FOR EXCHANGE CONNECTOR 11.1.1.6.0


Friday, September 20, 2013

OID: Command to create new OID Component

Here is the command to create new OID Component:

./opmnctl createcomponent -componentType OID -componentName oid3 -adminHost server -adminPort 7001  -Db_info "dbhost:1532:dbservicename" -Port 3063 -Sport 3133

Command requires login to weblogic admin server (server ):
  Username: weblogic
  Password:

Creating empty component directories...Done
Provisioning OID files for oid3
  OID onCreate....

Enter ODS password:
  Validating OID input parameters
Enter ODSSM password:
Enter OID admin password:
  Creating wallet and tnsnames.ora for OID
  Adding configuration entry for OID
  Updating opmn.xml with OID snippet
  Updating component-logs.xml with OID name
  Setting proxy mbean properties
Registering oid3 component
Invoking opmn reload...Done
Command succeeded.

Thursday, September 19, 2013

OIM11g R1 Post Processor Event Handler to remove User Role after user is disabled

Here is the code:

package oim.custom.eventhandlers;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import oracle.iam.identity.rolemgmt.api.RoleManager;
import oracle.iam.identity.rolemgmt.api.RoleManagerConstants.RoleAttributeName;
import oracle.iam.identity.rolemgmt.vo.Role;
import oracle.iam.identity.rolemgmt.vo.RoleManagerResult;
import oracle.iam.identity.usermgmt.api.UserManager;
import oracle.iam.identity.usermgmt.vo.User;
import oracle.iam.platform.Platform;
import oracle.iam.platform.context.ContextManager;
import oracle.iam.platform.entitymgr.vo.SearchCriteria;
import oracle.iam.platform.kernel.spi.PostProcessHandler;
import oracle.iam.platform.kernel.vo.AbstractGenericOrchestration;
import oracle.iam.platform.kernel.vo.BulkEventResult;
import oracle.iam.platform.kernel.vo.BulkOrchestration;
import oracle.iam.platform.kernel.vo.EventResult;
import oracle.iam.platform.kernel.vo.Orchestration;
import Thor.API.tcResultSet;
import Thor.API.Operations.tcLookupOperationsIntf;
import com.thortech.util.logging.Logger;

public class RemoveRolesFromRetiredUser implements PostProcessHandler {
 private static final Logger logger = Logger.getLogger("CUSTOM.EVENTS");
 private static final String CLASS_NAME = "oim.custom.eventhandlers.RemoveRolesFromRetiredUser : ";
 private static final String LOOKUP_COLUMN_DECODE = "Lookup Definition.Lookup Code Information.Decode";


 public void initialize(HashMap arg0) {
  String METHOD_NAME = "initialize :: ";
  logger.info(CLASS_NAME + METHOD_NAME
    + " Initializing RemoveRolesFromRetiredUser Event Handler ");
 }


 @Override
 public BulkEventResult execute(long processId, long eventId,
   BulkOrchestration bulkorchestration) {
  String METHOD_NAME = "BulkEventResult execute :: ";
  logger.info(CLASS_NAME + METHOD_NAME + "Inside ");
  try {
   String operation = bulkorchestration.getOperation();
   logger.debug(CLASS_NAME + METHOD_NAME
     + "bulkorchestration.getOperation() " + operation);

   String user = bulkorchestration.getTarget().getEntityId();
   logger.debug(CLASS_NAME + METHOD_NAME
     + "bulkorchestration.getTarget().getEntityId() " + user);

   logger.debug(CLASS_NAME + METHOD_NAME
     + " ContextManager.getContextType() "
     + ContextManager.getContextType());

   // Remove the  Roles of the Retired User
   if (isUserRetired(user) && operation.equals("DISABLE")) {
    logger.info(CLASS_NAME + METHOD_NAME
      + " Updated Description of Disabled User "
      + getUserName(user, "User Login") + " is "
      + getUserName(user, "Description"));
    logger.info(CLASS_NAME + METHOD_NAME
      + " Updated Container of Disabled User "
      + getUserName(user, "User Login") + " is " + getUserName(user, "UserDN"));
    logger.info(CLASS_NAME + METHOD_NAME
      + "Removing the Roles from the Disabled User "
      + getUserName(user, "User Login"));
    removeRolesOfUser(user);
   }
  } catch (Exception e) {
   logger.error(CLASS_NAME + METHOD_NAME + e.getMessage());
   e.printStackTrace();
  }
  return new BulkEventResult();
 }


 public boolean isUserRetired(String userKey) {
  String METHOD_NAME = "isUserRetired :: ";
  logger.debug(CLASS_NAME + METHOD_NAME + "Inside ");
  boolean isUserRetired = false;
  try {
   HashSet retiredContainers = readLookup("Lookup.OIM.RetiredContainers");
   Iterator itr = retiredContainers.iterator();
   String userDN = getUserName(userKey, "UserDN");
   while(itr.hasNext()) {
    String containername = itr.next().toString();
    if(userDN.contains(containername)) {
     isUserRetired = true;
    }
   } 
  } catch (Exception e) {
   logger.error(CLASS_NAME
     + METHOD_NAME
     + "Error checking User Container "
     + e.getMessage());
  }
  return isUserRetired;
 }


 // Method to remove Roles from User
 public void removeRolesOfUser(String userkey) {
  final String METHOD_NAME = "removeOIMRoles :: ";
  logger.debug(CLASS_NAME + METHOD_NAME + "Inside ");
  String rolename = null;
  try {
   HashSet groupList = getRolesForUser(userkey);
   Set roleKeysSet = new HashSet();
   Iterator itr = groupList.iterator();
   while (itr.hasNext()) {
    rolename = itr.next().toString();
    roleKeysSet.add(getRoleKey(rolename));
   }
   RoleManagerResult result = null;
   RoleManager rmgr = Platform.getService(RoleManager.class);
   result = rmgr.revokeRoleGrants(userkey, roleKeysSet);
   logger.debug(CLASS_NAME + METHOD_NAME + "Role " + rolename
     + " Removed from User "
     + getUserName(userkey, "User Login") + result.getStatus());
  } catch (Exception e) {
   logger.debug(CLASS_NAME + METHOD_NAME + "Error Removing Roles "
     + e.getMessage());
   e.printStackTrace();
  }
 }

 public HashSet getRolesForUser(String userkey) {
  String METHOD_NAME = "getRolesForUser :: ";
  logger.debug(CLASS_NAME + METHOD_NAME + "Inside ");
  HashSet roleList = new HashSet();
  try {
   logger.debug(CLASS_NAME + METHOD_NAME + "Reading "
     + getUserName(userkey, "User Login") + "Roles ");
   RoleManager rolemanager = Platform.getService(RoleManager.class);
   List groupList = rolemanager
     .getUserMemberships(userkey, true);
   for (Role role : groupList) {
    String roleName = role.getAttribute("Role Name").toString();
    logger.debug(CLASS_NAME + METHOD_NAME + "RoleName :" + roleName);
    roleList.add(roleName);
   }
   HashSet removeRoles = readLookup("Lookup.OIM.IgnoreRole");

   // Exclude Default Roles from the List
   roleList.removeAll(removeRoles);

  } catch (Exception e) {
   logger.error(CLASS_NAME + METHOD_NAME + "Error Reading Roles"
     + e.getMessage());
   e.printStackTrace();
  }
  return roleList;
 }

 // Method to read Lookup containing default OIM Roles
 public HashSet readLookup(String lookup) {
  String METHOD_NAME = "readLookup :: ";
  logger.debug(CLASS_NAME + METHOD_NAME + "Inside ");
  HashSet records = new HashSet();
  try {
   String lookupDecode = lookup;
  
   // Read Lookup to Find FilteredRoles
   tcLookupOperationsIntf lookupOps = Platform
     .getService(tcLookupOperationsIntf.class);
   tcResultSet lookupResultSet = lookupOps
     .getLookupValues(lookupDecode);
   for (int i = 0; i < lookupResultSet.getRowCount(); i++) {
    lookupResultSet.goToRow(i);
    String decode = lookupResultSet.getStringValue(
      LOOKUP_COLUMN_DECODE).trim();
    records.add(decode);
   }
  } catch (Exception e) {
   logger.error(CLASS_NAME + METHOD_NAME + "Error Reading Lookup"
     + e.getMessage());
   e.printStackTrace();
  }
  return records;
 }

 // Method to get RoleKey based on Rolename input
 public String getRoleKey(String roleName) {
  final String METHOD_NAME = "getRoleKey :: ";
  logger.debug(CLASS_NAME + METHOD_NAME + "Inside ");
  RoleManager rmgr = Platform.getService(RoleManager.class);
  Set retAttrs = new HashSet();
  String roleKey = null;
  try {
   retAttrs.add(RoleAttributeName.DISPLAY_NAME.getId());
   SearchCriteria criteria = null;
   criteria = new SearchCriteria(RoleAttributeName.NAME.getId(),
     roleName, SearchCriteria.Operator.EQUAL);
   List roles = rmgr.search(criteria, retAttrs, null);
   roleKey = roles.get(0).getEntityId();
  } catch (Exception e) {
   e.printStackTrace();
  }
  return roleKey;
 }

 // Method to retrieve User Login based on the usr_key
 public String getUserName(String key, String attribute) {
  String METHOD_NAME = "getUserName :: ";
  logger.debug(CLASS_NAME + METHOD_NAME + "Inside ");
  String userattr = null;
  try {
   HashMap attributes = null;
   HashMap parameters = null;
   Set attrNames = null;
   List users = null;
   UserManager umgr = Platform.getService(UserManager.class);
   SearchCriteria criteria = new SearchCriteria("usr_key", key,
     SearchCriteria.Operator.EQUAL);
   attrNames = new HashSet();
   attrNames.add(attribute);
   users = umgr.search(criteria, attrNames, parameters);
   if (users != null && !users.isEmpty()) {
    for (User user : users) {
     attributes = user.getAttributes();
     userattr = attributes.get(attribute).toString();
     logger.debug(CLASS_NAME + METHOD_NAME + " User : "
       + userattr);
    }
   }
  } catch (Exception e) {
   logger.error(CLASS_NAME + METHOD_NAME
     + "Error Retrieving User Login " + e.getMessage());
   e.printStackTrace();
  }
  return userattr;
 }

 @Override
 public EventResult execute(long processId, long eventId,
   Orchestration orchestration) {
  return null;
 }

 @Override
 public boolean cancel(long arg0, long arg1,
   AbstractGenericOrchestration arg2) {
  return false;
 }

 @Override
 public void compensate(long arg0, long arg1,
   AbstractGenericOrchestration arg2) {
 }

}

Here is the plugin.xml:

http://www.w3.org/2001/XMLSchema-instance
">
Here is the eventhandlers.xml:

http://www.oracle.com/schema/oim/platform/kernel
" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.oracle.com/schema/oim/platform/kernel orchestration-handlers.xsd"> 
Cheers!

Monday, September 9, 2013

OIM: How to Disable/Enable User Resource Object using API

Here is the sample code to disable the resource objects allocated to a user:
 
 
Long userKey = Long.parseLong(getUserKey(
"y9506a"));
 
userOp = oimClient.getService(tcUserOperationsIntf.class);
 
tcResultSet userObjects = userOp.getObjects(userKey);
 
Long processKey = userObjects.getLongValue(Users-Object Instance For User.Key");
 
 // Disable the Resource Object
 
userOp.disableAppForUser(userKey, processKey);
 
// Enable the Resource Object
 
userOp.enableAppForUser(userKey, processKey);
 
String ostatus = userObjects.getStringValue(
"Objects.Object Status.Status");
 
System.
out.println(ostatus);