8 Developing Event Handlers for Extending User Management Operations

This chapter describes the asynchronous implementation of the post-processing functions involved in user management operations. It contains the following topics:

8.1 An Overview of User Management Operations

In an Identity Management system, any action performed by a user or system is called an operation. Examples of operations are creating users and updating users. Each operation goes through pre- and post-processing stages.

What happens at each stage is determined by branching and by the event handler, if any, that is deployed at that stage. If a stage has a branch, responses from the event handlers decide which branch to take. If a stage has no event handlers, or event handlers respond with no recommendation, the operation simply follows the default path and moves to the next stage.

Each operation performed in an identity management environment can have consequences for users or other entities. For example, creating a user might result in provisioning of resources to that user, updating the history results in changes to the reporting tables, and creating a new password policy might make certain user passwords invalid and require changes during next login.

Operations specific to a user, such as creation, modification, deletion, enable, disable, and so on are referred to as user management operations. The lifecycle of an operation consists of these stages:

  • validation: Stage to perform validation on the orchestration, such as validity of orchestration parameters. Orchestration parameter is the data that is required to carry out the orchestration operation.

  • pre-processing: Stage to perform orchestration parameter manipulations or get approvals or perform Segregation of Duties (SoD) checks.

  • audit: Stage in which the auditing of operation is performed.

  • action: Stage in which the action takes place.

  • post-processing: Stage in which consequent operations related to the current operation takes place. Examples of consequent operations are auto role membership and policy evaluation on a user creation.

  • compensation: Process is moved to this stage if the operation is rolled back by calling the compensate method.

  • finalization: Last stage in the process to perform any clean up.

You can customize the consequences of user management operations such as create, update, delete, enable, disable, lock, unlock, and change password - also referred to as the post-processing functions of user management operations - by writing event handlers.

Tip:

See "Writing Custom Event Handlers" for details about how to write event handlers.

in 11g Release 1 (11.1.1), Oracle Identity Manager supports asynchronous execution of post-processing functions associated with user management operations. This significantly improves the perceived performance of user management operations.

Post-processing functions associated with user management operations can be triggered programmatically on a given set of users. This capability becomes useful in situations where the users are managed directly on the data store, specifically in a reconciliation or bulk load scenario.

8.2 Extending User Management Operations with Event Handlers

The 11g Release 1 (11.1.1) kernel exposes Service Provider Interfaces (SPIs) that are implemented to customize the functionality of user management operations. Currently, you can customize only pre-process, post-process, and validation stages of an operation for an entity.

Note:

Customizations of pre-process and validation functions are synchronous with the operation. However, customizations of the post-process functions are asynchronous.

This section describes extending user management operations with event handlers in the following topics:

8.2.1 Understanding Elements in Event Handlers XML Files

Event Handlers XML files are comprised of elements and element attributes. This section describes some of the elements and element attributes within Event Handlers XML files. It also describes a mandatory namespace for the event handler XML definitions.

Elements

The top-level (or parent) element in Event Handlers XML files is eventhandlers. Table 8-1 lists and describes sub-elements that are typically defined within the eventhandlers parent element.

Table 8-1 Typical Sub-elements within the eventhandlers Element

Sub-element Description

validation-handler

Identifies the validations that will be performed on the orchestration.

action-handler

Identifies the operations that will be performed at preprocess, postprocess, and action stages.

failed-handler

Identifies the event handlers that will be executed if an event handler fails.

finalization-handler

Identifies the event handlers to execute at the end of the orchestration. Finalization is the last stage of any orchestration.

change-failed

Identifies event handlers to be executed upon consequence orchestration failures.

out-of-band-handler

Defines event handlers for out-of-the-band orchestration flows such as veto and cancel. A process can move to some out-of-the-band stages if the event handlers are invalid or canceled. These stages are:

  • Invalid: Process is moved to this stage if orchestration validation fails.

  • Veto: Process is moved to this stage if any of the preprocess event handlers are vetoed. For example, if approvals are rejected by the approver, then orchestration is vetoed.

  • Cancel: Process is moved to this stage if the operation is stopped by calling the cancel method.

  • Compensation: Process is moved to this stage if the operation is rolled back by calling the compensate method.

compensate-handler

Identifies the event handlers that will be executed in the compensation flow of the orchestration.


Element Attributes

The elements within Event Handlers XML files contain attributes. Table 8-2 lists and describes attributes that are typically defined within elements.

Table 8-2 Typical Attributes of Sub-elements within the eventhandlers Element

Element Attribute Description

Name

The name of the event handler.

class

Full package name of the Java class that implements the event handler.

entity-type

Identifies the type of entity the event handler is executed on. A value of ANY sets the event handler to execute on any entity.

operation

Identifies the type of operation the event handler is executed on. A value of ANY sets the event handler to execute on any operation.

order

Identifies the order (or sequence) in which the event handler is executed. Supported values are FIRST, LAST, or a numeral.

orch-target

Identifies the type of orchestration, such as entity orchestration, Toplink orchestration, and so on. The following is a list of supported values:

  • oracle.iam.platform.kernel.vo.EntityOrchestration

  • oracle.iam.platform.kernel.vo.MDSOrchestration

  • oracle.iam.platform.kernel.vo.RelationOrchestration

  • oracle.iam.platform.kernel.vo.ToplinkOrchestration

The default value is oracle.iam.platform.kernel.vo.EntityOrchestration.

sync

This attribute is operational in only the action-handler and change-failed elements. The sync attribute indicates whether the event handler is synchronous or asynchronous. Supported values are TRUE or FALSE. If set to TRUE (synchronous), the kernel expects the event handler to return an EventResult. If set to FALSE (asynchronous), you must return null as the event result and notify the kernel about the event result later.

Note: The sync attribute must be set to TRUE for validation-handler elements.

stage

This attribute is operational in only the out-of-band-handler, action-handler, and failed-handler elements. The stage attribute indicates the stage at which the event handler gets executed. The following is a list of supported values:

  • preprocess

  • action

  • audit

  • postprocess

  • veto

  • cancelled

tx

This attribute is operational in only the out-of-band-handler, action-handler, compensate-handler, and finalization-handler elements. The tx attribute indicates whether or not the event handler should run in its own transaction. Supported values are TRUE or FALSE.


Namespace Requirement in <eventhandlers> Element

Example 8-1 is the namespace that MUST be defined in the <eventhandlers> root element for all custom event handler XML definitions.

Example 8-1 Mandatory Namespace Definition for Custom Event Handlers

<eventhandlers xmlns="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">

8.2.2 Writing Custom Event Handlers

All customizations to user management operations need to be implemented as event handlers.

Perform the following steps to write a custom event handler:

  1. Implement the custom event handler:

    See Section 8.2.2.1, "Implementing Custom Event Handlers"

  2. Create a plug-in containing the custom event handler:

    See Section 8.2.2.2, "Creating Plug-ins for Custom Event Handlers"

  3. Define custom events:

    See Section 8.2.2.3, "Defining Custom Events"

8.2.2.1 Implementing Custom Event Handlers

To implement custom event handlers:

  1. Implement one of the SPIs mentioned in Table 8-3 to write a custom pre-process, post-process, or validation handler.

    Table 8-3 SPIs to Write Custom Event Handlers

    Stage SPI to implement

    Pre-Process

    oracle.iam.platform.kernel.spi.PreProcessHandler

    Post-Process

    oracle.iam.platform.kernel.spi.PostProcessHandler

    Validation

    oracle.iam.platform.kernel.spi.ValidationHandler


  2. Include the following JAR files in the class path to compile a custom class:

    From OIM_INSTALL_HOME/server/platform

    • iam-platform-kernel.jar

    • iam-platform-utils.jar

    • iam-platform-context.jar

    • iam-plaftorm-authz-service.jar

    From OIM_INSTALL_HOME/designconsole/lib

    • oimclient.jar

    • xlAPI.jar

    From OIM_INSTALL_HOME/designconsole/lib and OIM_INSTALL_HOME/server:

    All other JAR files

  3. Create a library of JAR files containing the custom classes.

The following code samples illustrate how to invoke Oracle Identity Manager 9.1.x APIs and 11g APIs to customize user management operations. See SPI Javadocs for more information.

Example 1: Custom Password Validation

Example 8-2 shows a sample custom validation handler code fragment that checks to ensure that $ is not used in a password.

Example 8-2 Sample Custom Validation Handler

 throws ValidationException, ValidationFailedException {
    HashMap<String, Serializable> parameters = orchestration.getParameters();
    String password = (parameters.get("usr_password") instanceof ContextAware)
      ? (String) ((ContextAware) parameters.get("usr_password")).getObjectValue()
      : (String) parameters.get("usr_password");
    if (password.contains("$")) {
      throw new ValidationFailedException();
    }
}

Example 2: Custom Pre-process Event Handler to Set Middle Initial

Example 8-3 shows a sample custom pre process event handler code fragment that sets the middle initial to the first letter of the first name if the user does not have a middle name.

Note:

Bulk reconciliation does not execute preprocess event handlers.

Example 8-3 Sample Custom Pre Process Event Handler

// This custom preprocess event handler sets the first letter of the first name as
// the middle initial when the user doesn't have a middle name
public EventResult execute
   (long processId, long eventId, Orchestration orchestration) {
   HashMap<String, Serializable> parameters = orchestration.getParameters();
// If the middle name is empty set the first letter of the first name 
// as the middle initial
String middleName = getParamaterValue(parameters, "Middle Name");
  if (isNullOrEmpty(middleName)) {
     String firstName = getParamaterValue(parameters, "First Name");
     middleName = firstName.substring(0,1);
     orchestration.addParameter("Middle Name", middleName);
  }
  return new EventResult();
}
private String getParamaterValue(HashMap<String, Serializable> parameters, 
  String key) {
  String value = (parameters.get(key) instanceof ContextAware)
  ? (String) ((ContextAware) parameters.get(key)).getObjectValue()
  : (String) parameters.get(key);
  return value;
}

Example 3: Custom Post-process Event Handler to Provision Resource Object

Example 8-4 shows a sample custom post process event handler code fragment that provisions a resource object OBJ005 to a user whose role is ROLE 00.5:

Example 8-4 Sample Custom Post Process Event Handler

// This custom post process event handler provisions resource object 'OBJ005' 
// to a user who has role 'ROLE 005'
public EventResult execute(long processId, long eventId, 
  Orchestration orchestration) {
    tcUserOperationsIntf userOperationsService =   
    Platform.getService(tcUserOperationsIntf.class);
try {
  String userKey = getUserKey(processId, orchestration);
  if (hasRole(userKey, "ROLE 005")) {
     long objKey = findObject("OBJ001");
userOperationsService.provisionResource(Long.getLong(userKey), objKey);
}
} catch (Exception e) {
throw new EventFailedException("Error occurred ", e);
}
 
return new EventResult();
}
 
// This method retrieves the key of the user entity on which an operation 
// is performed
// This method shows how to retrieve the operation being performed, entity type
// and the associated value objects 
private String getUserKey (long processID, Orchestration orchestration) {
  String userKey;
  String entityType = orchestration.getTarget().getType();
  EventResult result = new EventResult();
 
if (!orchestration.getOperation().equals("CREATE")) {
userKey = orchestration.getTarget().getEntityId();
} else {
OrchestrationEngine orchEngine = Platform.getService(OrchestrationEngine.class);
userKey = (String) orchEngine.getActionResult(processID);
}
return userKey;
}
 
// This method checks if a given user has a given role. 
// It demonstrates how to invoke a OIM 11g API from a custom event handler
private boolean hasRole(String userKey, String roleName) 
  throws Exception {
  RoleManager roleManager = Platform.getService(RoleManager.class);
  List<Identity> roles = roleManager.getUserMemberships(userKey);
 
  for (Iterator iterator = roles.iterator(); iterator.hasNext();) {
Role role = (Role) iterator.next();
if (roleName.equals((String)role.getAttribute("Role Name"))) {
return true;
}
 
}
return false;
}
 
// This method finds details about a resource object with the given name. 
// It demonstrates how to invoke a 9.1.x API from a custom event handler
private long findObject(String objName) throws Exception {
  long objKey = 0;
  tcObjectOperationsIntf objectOperationsService =  
  Platform.getService(tcObjectOperationsIntf.class);
HashMap params = new HashMap();
params.put("Objects.Name", objName);
tcResultSet objects = objectOperationsService.findObjects(params);
for (int i = 0; i < objects.getRowCount(); i++) {
  objects.goToRow(i);
  if (objects.getStringValue("Objects.Name").equals(objName)) {
  objKey = objects.getLongValue("Objects.Key");
}
}
 return objKey;
}

8.2.2.2 Creating Plug-ins for Custom Event Handlers

To create plug-ins containing custom event handlers, you need to develop the appropriate event handler classes. See Chapter 7, "Developing Plug-ins" for details.

Note:

Ensure that plug-in point used in the plug-in definition is set to oracle.iam.platform.kernel.spi.EventHandler.

Note:

The plug-ins can be packaged as required, just like the JAR files, as long as they adhere to the packaging guidelines.

Here is an example of a plug-in XML file:

<?xml version="1.0" encoding="UTF-8"?>
<oimplugins>
  <plugins pluginpoint="oracle.iam.platform.kernel.spi.EventHandler">
    <plugin pluginclass=  
       "oracle.oim.extensions.preprocess.SamplePreprocessExtension" 
        version="1.0" 
        name="SamplePreprocessExtension">
    </plugin>
    <plugin pluginclass= 
        "oracle.oim.extensions.postprocess.SamplePostprocessExtension"
         version="1.0" 
         name="SamplePostprocessExtension">
    </plugin>
    <plugin pluginclass= 
       "oracle.oim.extensions.validation.SampleValidationExtension"
        version="1.0" 
        name="SampleValidationExtension">
    </plugin>
  </plugins>
</oimplugins>

8.2.2.3 Defining Custom Events

Take these steps to define custom events:

  1. Create the metadata XML file containing definitions of all the custom events.

    Example 8-5 shows what a metadata file looks like:

    Example 8-5 Sample Metadata XML File for Custom Event Definitions

    <?xml version='1.0' encoding='utf-8'?>
    <eventhandlers>
      <!-- Custom preprocess event handlers -->
      <action-handler
        class="oracle.oim.extensions.preprocess.SamplePreprocessExtension"
        entity-type="User" 
        operation="CREATE" 
        name="SamplePreprocessExtension"
        stage="preprocess"
        order="1000" 
        sync="TRUE"/>
     
      <!-- Custom postprocess event handlers -->
      <action-handler
        class="oracle.oim.extensions.postprocess.SamplePostprocessExtension"
        entity-type="User" 
        operation="CREATE" 
        name="SamplePostprocessExtension"
        stage="postprocess"
        order="1000" 
        sync="TRUE"/>
     
      <action-handler
        class="oracle.oim.extensions.postprocess.SamplePostprocessExtension"
        entity-type="User" 
        operation="MODIFY" 
        name="SamplePostprocessExtension"
        stage="postprocess"
        order="1000" 
        sync="TRUE"/>
     
      <!-- Custom validation event handlers -->
       <validation-handler
        class="oracle.oim.extensions.validation.SampleValidationExtension"
        entity-type="User" 
        operation="CREATE" 
        name="SampleValidationExtension"
        order="1000"/>       
     
       <validation-handler
        class="oracle.oim.extensions.validation.SampleValidationExtension"
        entity-type="User" 
        operation="MODIFY" 
        name="SampleValidationExtension"
        order="1000"/>       
    </eventhandlers>
    
  2. Import these event definitions into MDS. See Chapter 33, "MDS Utilities and User Modifiable Metadata Files" for more information. For a shiphome-based install the scripts necessary to import the event definitions are located in the following directory:

    OIM_HOME/common/wlst

    Note:

    You need not define all the custom event definitions in the same file. They could be split across multiple new event definition files or they could be added to any existing event definition file. Exporting the desired event definition file, modifying it, and importing it back implements the latter. For information about exporting and importing event definition files, see Chapter 33, "MDS Utilities and User Modifiable Metadata Files".

8.3 Troubleshooting an Event Handler

The following list contains information to help troubleshoot your event handler if it appears not to start. Common causes of this might be:

  • EventHandlers.xml has a syntax error.

  • EventHandlers.xml was imported into the wrong place in MDS. It must be in a top-level directory recognized by Oracle Identity Manager; for example, /db/, /file/ or /custom/. /mystuff/(for example) and the root directory (/) are not recognized.

  • A preprocess event handler has been implemented using reconciliation. Preprocess event handlers do not start on reconciliation.

  • A preprocess event handler has been implemented using reconciliation but not bulk orchestration execute. Both bulk and non-bulk methods must be implemented to work with reconciliation.