Oct 29, 2013

Oracle Identity Management Connector Overview

Oracle Identity Manager (OIM) is a complete Identity Governance system that automates access rights management, and provisions IT resources.  One important aspect of this system is the Identity Connectors that are used to integrate OIM with external, identity-aware applications.
New in OIM 11gR2 PS1 is the Identity Connector Framework (ICF) which is the foundation for both OIM and Oracle Waveset.

Identity Connectors perform several very important functions:
  • On boarding accounts from trusted sources like SAP, Oracle E-Business Suite, & PeopleSoft HCM
  • Managing users lifecycle in various Target systems through provisioning and recon operations
  • Synchronizing entitlements from targets systems so that they are available in the OIM request catalog
  • Fulfilling access grants and access revoke requests
  • Some connectors may support Role Lifecycle Management
  • Some connectors may support password sync from target to OIM
The Identity Connectors are broken down into several families:
The BMC Remedy Family
  • BMC Remedy Ticket Management
  • BMC Remedy User Management
The Microsoft Family
  • Microsoft Active Directory
  • Microsoft Active Directory Password Sync
  • Microsoft Exchange
The Novell Family
  • Novell eDirectory
  • Novell GroupWise
The Oracle E-Business Suite Family
  • Oracle e-Business Employee Reconciliation
  • Oracle e-Business User Management
The PeopleSoft Family
  • PeopleSoft Employee Reconciliation
  • PeopleSoft User Management
The SAP Family
  • SAP CUA
  • SAP Employee Reconciliation
  • SAP User Management
The UNIX Family
  • UNIX SSH
  • UNIX Telnet
As you can see, there are a large number of connectors that support apps from a variety of vendors to enable OIM to manage your business applications and resources.

Apr 15, 2013

Creating a Custom OVD Plug-in

1. Introduction

OVD does not come with functionality out of the box to implement this requirement but does allow you to write custom plugins, where you can extend the capabilities of OVD to include requirements such as the one my customer had.

This post shows how to develop a custom OVD plug-in.

This plug-in reads a LDAP Object’s attribute value, splits the value in two, using a delimiter, and creates two new attributes with values assigned from the split operation.

Though this is a very simple requirement, and in fact my customer requirements were more complex than that, it can be used as a starting point to develop different use-case needs.

This plug-in is designed to work with a LDAP Adapter, and will run it’s logic for each LDAP "get" operation, before handing the result back to OVD.

The plug-in is flexible enough to work with any LDAP "objectClass" that has an attribute of String data type with a pattern delimiter that can be split in two.


2. Creating the Custom OVD Plug-in


a. Create a Standard Java Project in your preferred IDE. For this example, Eclipse is used.

b. Add vde.jar, ovdcommon.jar and asn1c.jar to your project's build path. These files are located in $ORACLE_HOME/ovd/jlib. I created Variable in Eclipse to avoid those libs to be packaged with the final JAR.



c. Create a package and a new Class, name it what you will and make your class extend "com.octetstring.vde.chain.BasePlugin".

d. In this class we will create the following properties:

String jobCode = null;
String jobTitle = null;
String delimiter = null;
String originalAttribute = null;
String objectclass = null;

Those properties will be configurable through OVD console, this way our plugin is flexible and can accept different configurations at runtime. More on that later…

e. Implement just the methods that you want the plug-in to run its logic. In this example we implemented the "postSearchEntry", which is called after each "get" call to the LDAP. In this way, we can manipulate the result from the LDAP, before handing it back to OVD. Besides that, we will also implement "available()" and "init()" methods. The first tells OVD if this plugin is available for the current Chain, which for simplicity sake, we will always return true. The latter, we will use to read and initialize our variables configured in OVD console.



f. Create a new (or edit existing one) MANIFEST.MF file in the META-INF folder. It should contains the following information:

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.7.1
Created-By: 1.6.0_41-b02 (Sun Microsystems Inc.)
vde-package-name: SplitLDAPAttribute
vde-package-ops-add: false
vde-package-ops-delete: false
vde-package-ops-bind: false
vde-package-ops-modify: false
vde-package-ops-rename: false
vde-package-ops-get: true
vde-package-description: Splits a configured LDAP attribute into two other attributes using a separator character. 
vde-package-classname: com.oracle.ateam.demo.SplitAttribute
vde-package-type: 0
vde-package-version: 0
vde-package-param-jobCode-description: The first attribute that will be created as the result of the split.
vde-package-param-jobTitle-description: The second attribute that will be created as the result of the split.
vde-package-param-delimiter-description: The separator character that will split the LDAP attribute
vde-package-param-originalAttribute-description: The attribute that will be split into two new attributes.
vde-package-param-objectclass-description: The ObjectClass which the filter should run the split operation

Note that the properties described in the MANIFEST file, corresponds to the properties we created in our class and that we want to configure in runtime in OVD console. We have also declared which methods are available and implemented in this plugin and other description metadata that will be available in OVD console.

3. The init() method:

    public void init(PluginInit initParams, String name) throws ChainException {
        if (initParams.containsKey("originalAttribute")) {
         originalAttribute = initParams.get("originalAttribute");
        }
        if (initParams.containsKey("jobCode")) {
         jobCode = initParams.get("jobCode");
        }
        if (initParams.containsKey("jobTitle")) {
         jobTitle = initParams.get("jobTitle");
        }
        if (initParams.containsKey("delimiter")) {
         delimiter = initParams.get("delimiter");
        }
        if (initParams.containsKey("objectclass")) {
         objectclass = initParams.get("objectclass");
        }
    }

4. postSearchEntry() method:

public void postSearchEntry(Chain chain, Credentials creds,
            Vector returnAttribs, Filter filter, Int8 scope,
            DirectoryString base, Entry entry, ChainEntrySet entrySet)
            throws ChainException, DirectoryException {

//Initialize ObjectClassCheck variable
boolean isObjectClassCheck = false;

//Initialize The Original Attribute variable that will be split
        DirectoryString splitAttribute = new DirectoryString(originalAttribute);
        
        //Initialize the ObjectClass Attribute variable
        DirectoryString objectClassAttribute = new DirectoryString("objectClass");
        
        //Checks if the current entry has the required objectclass
        if(entry.containsKey(objectClassAttribute)) {
        Vector objClasses = entry.get(objectClassAttribute);
        
        for(int i = 0; i < objClasses.size(); i++) {
         DirectoryString oc = (DirectoryString) objClasses.get(i);
        
         //If the current entry objectclass matches the configured by the 
         //plugin it will be processed
         if(oc.toString().equals(objectclass)){
         isObjectClassCheck = true;
         }
        }
        }

        //If the current entry has the Attribute that will be split and
        //if it is of the configured objectclass we proceed to split the attribute
        if (entry.containsKey(splitAttribute) && isObjectClassCheck) {
        
         //Gets the Attribute configured to be split
            DirectoryString splitAttributeValue = (DirectoryString) entry.get(splitAttribute).get(0);
            
            //Splits the Attribute value
            String[] splittedValues = splitAttributeValue.toString().split(delimiter);

            //Checks if the split result has at least 2 elements
            if (splittedValues != null && splittedValues.length > 1) {
            
             //Creates Custom Attributes and set their values
                DirectoryString jobCodeAttr = new DirectoryString(jobCode);
                Vector jobCodeVec = new Vector();
                jobCodeVec.add(new DirectoryString(splittedValues[0]));
                
                DirectoryString jobTitleAttr = new DirectoryString(jobTitle);
Vector jobTitleVec = new Vector();
jobTitleVec.add(new DirectoryString(splittedValues[1]));         
            
                //Adds the custom Attributes to the current entry
             entry.put(jobCodeAttr, jobCodeVec);
             entry.put(jobTitleAttr, jobTitleVec);
            }
        }

        // calls the next plug-in in the chain (or comment out if a handler)
        chain.nextPostSearchEntry(creds, returnAttribs, filter, scope, base, entry, entrySet);
    }


5. Creating the JAR file.

At this point all we need to do is package everything as a JAR file. Use your IDE’s or command line methods to package your project in a JAR file, but take special care to include the MANIFEST.MF we created in the resulting JAR.

6. Installing the plug-in

a. Go to OVD Console
b. Go to Advanced Tab, Library section



c. Click on the "Upload New Library" button, choose your JAR file and click OK



d. Refresh the view and your plug-in should appear on the list



7. Configuring the plug-in

a. Go to "Adapter" tab, choose the adapter you want to attach the plug-in to and click on "Plug-ins" tab



b. Click on "Create plug-in" button; give it a name, and select the plug-in class you created from the list.



c. Click on create parameter, and set the parameter values for each of the required parameters. Those parameters will be used by the plug-in logic to perform the attributes split.



d. In our example, those are the attributes used by our plug-in:



The example Plug-in has the following configurable parameters:

Parameter
Description
objectclasscheck
This is the object class the plug-in will only be invoked on.
jobCode
This is a new attribute the plug-in will create on the fly which will be populated with the first value from the split operation.  The name of the resulting attribute can be anything you want including an existing attribute.  If there is an existing LDAP attribute, the original attribute value will be replaced by the value the plug-in gets.
jobTitle
This is a new attribute the plug-in will create on the fly which will be populated with the second value from the split operation.  The name of the attribute can be anything you want including an existing attribute.  If there is an existing LDAP attribute, the original attribute value will be replaced by the value the plug-in gets.
delimiter
This is the character used to delimit the value.  For example if the attribute value is 23984839-Specialist, the hyphen “-“ could be used as the delimiter to split the value.
originalAttribute
This is the original LDAP attribute the plug-in will get the original value from.

e. Select the "Get" operation from the "Select Operation" drop-down list, choose the plug-in you created and click "Apply" button.



f. Click "Apply" to save the configuration for this adapter’s plug-in.



8. Testing the plug-in

a. Go to the “Data Browser” tab, drill down to the data structure exposed by your adapter, and select one of the groups.
b. In the right side of the screen, click on the “Views” button and Select “Show All”.



c. Inspect the object’s properties and find the newly created properties from the original property chosen to be split.



The same can be verified by external LDAP clients, like Apache Directory Studio.

The properties can also available in a Join view, where the LDAP adapter is joined with a Database Adapter, to include additional information coming from a database.

9. Uninstalling the Plug-in

a. Stop OVD process and ODSM server
b. Remove the JAR file from $ORACLE_INSTANCE/ovd/ovd1/ (do this for each OVD instance).
c. Restart ODSM and OVD
d. Remove the plug-in from the Adapter Plug-in Tab.

10. Reference

http://docs.oracle.com/cd/E23549_01/oid.1111/e10046/und_plug.htm

http://docs.oracle.com/cd/E15523_01/oid.1111/e10046/adv_cust.htm

Feb 12, 2013

Oracle Identity Manager(OIM) API for Account Provisioning

Oracle Identity Manager allows you to provision account using the OIM api. You can use Oracle Identity Manager to create, maintain, and delete accounts on target systems. Oracle Identity Manager becomes the front-end entry point for managing all the accounts on these systems. After the accounts are provisioned, the users for whom accounts have been provisioned are able to access the target systems without any interaction with Oracle Identity Manager. This is the provisioning configuration of Oracle Identity Manager.





Sometimes you will need give account from remote operations (webservice or some remote connector).For this operations , you have to find right application instance for provision account. You can use findApplicationInstanceByName method of oracle.iam.provisioning.api.ApplicationInstanceService service for find application instance. Then,you can provision an application instance with OIM api, usingoracle.iam.provisioning.api.ProvisioningService service.

import oracle.iam.provisioning.api.ProvisioningService;
import oracle.iam.provisioning.api.ApplicationInstanceService;

    public void provisionAccount(String userKey) throws ApplicationInstanceNotFoundException,
                                                                        GenericAppInstanceServiceException,
                                                                        UserNotFoundException,
                                                                        GenericProvisioningException {
  ProvisioningService service=getClient().getService(ProvisioningService.class); 
  ApplicationInstance appInstance=findApplicationInstanceByName("Application Instance Name");
                //serverName example : UD_ADUSER_SERVER
        //itResourceName example : Active Directory
        FormInfo formInfo = appInstance.getAccountForm();
        Map parentData = new HashMap();
        parentData.put(serverName, itResourceName);
        String formKey = String.valueOf(formInfo.getFormKey());
        AccountData accountData = new AccountData(formKey, null, parentData);
        Account account = new Account(appInstance, accountData);
        account.setAccountType(Account.ACCOUNT_TYPE.Primary);
        service.provision(userKey, account);
}

    public ApplicationInstance findApplicationInstanceByName(String applicationInstanceName) throws ApplicationInstanceNotFoundException,
                                                                                                GenericAppInstanceServiceException {
 ApplicationInstanceService service=getClient().getService(ApplicationInstanceService.class);
        ApplicationInstance appInstance=service.findApplicationInstanceByName(applicationInstanceName);
        return appInstance;
    }


Nov 16, 2011

OPSS Artifacts life cycle in an ADF Application

When you enable security in an ADF application, you see a couple of new artifacts in your JDeveloper workspace, namely jps-config.xml, jazn-data.xml and cwallet.sso.

Have you ever wondered what their purpose is, their life cycle and how they relate to WLS domain security configuration? This article is just about it.

As you might know, secured ADF applications leverage OPSS (Oracle Platform Security Services). OPSS is a fundamental component within Oracle Fusion Middleware security. It works as an abstraction layer on top of security services providers, shielding applications from all the complexities in dealing with them. For instance, applications can transparently switch between file-based and LDAP-based policy stores. Likewise for credential store services.

Let's take a closer look at each of those artifacts and their life cycles.

jps-config.xml


This file can be seen as the lookup services registry for OPSS. Among these services are login modules, authentication providers, authorization policy providers, credential stores and auditing services. 
Whenever an OPSS-enabled application requires security services, it looks up a JPSContext object where all the necessary services are supposedly configured.

In ADF applications, a workspace-level jps-config.xml is created once ADF security is enabled. It drives services lookup for ADF's BC (Business Components) Tester available in JDeveloper, which is a JavaSE application. If you want to have security unit tests, you can also easily leverage it.

It is never used once the ADF application gets deployed in a WLS container, even though it is packaged in the ear file. Within a WLS container, a jps-config.xml in /config/fmwconfig is used by all applications in all servers deployed in that WLS domain. There's no such concept of an application-level or server-level jps-config.xml.

jazn-data.xml


This file keeps users, groups and authorization policies for OPSS-enabled applications and is automatically created once ADF security is enabled. I've already covered users and groups life cycles in a previous article. It is important to mention that users and groups are also leveraged by ADF's BC Tester and can be integrated into security unit tests as well.

Authorization policies are, if not the most, one of the most sensitive parts of a secured ADF application, since it governs who has access to what. As you might guess, they are also leveraged by ADF's BC Tester. When the ADF application is deployed into WLS, at startup time, policies are OOTB (Out-Of-The-Box) migrated into the configured policy store, who, by default, is a file called system-jazn-data.xml, located under /config/fmwconfig. You can configure how (and if) policies are migrated through some properties in weblogic-application.xml. Here they are:

<listener>
<listener-class>oracle.security.jps.wls.listeners.JpsApplicationLifecycleListener<listener-class>
<listener>


This listener is the one actually responsible for pushing the changes to the runtime policy store. Make sure it is present in weblogic-application.xml. Otherwise, you’ll experience a lot of frustration in trying to deploy authorization policies along with your application.

<application-param>
<param-name>jps.policystore.migration</param-name>
<param-value>[MERGE|OVERWRITE|OFF]</param-value>
</application-param>


MERGE, OVERWRITE and OFF are exclusive and applicable for deployments and redeployments. And they mean exactly what you might be thinking.

  • MERGE will merge what’s already available in the runtime policy store. This might be particularly useful in some advanced deployments where more than one application share the same application policy stripe.
  • OVERWRITE wipes away the existing application policy stripe and load all policies from scratch.
  • OFF skips policy migration.
Do notice that once the application is undeployed, its policies are also removed from the policy store, unless you set the following property in weblogic-application.xml:
<application-param>
<param-name>jps.policystore.removal</param-name>
<param-value>OFF</param-value>
</application-param>

Authorization policies migration will always happen according to weblogic-application.xml configuration, no matter what the deployment method is.

cwallet.sso


This file keeps credentials used by the application. A subtle and fundamental distinction is important to be made here: credentials and identities are not the same thing. Simply put, in OPSS, identities are what authentication requests are done against, while credentials are securely kept objects that are somehow presented to authentication providers to be matched against identities. 

cwallet.sso is encrypted and you cannot browse it or explicitly edit it via JDeveloper. At design-time, different components make use of cwallet.sso and are responsible for creating the necessary credentials in it. Examples are OWSM policy attachments that override the csf-key and ADF connections requiring credentials in the call out.

If you need credentials that can’t be created within JDeveloper, you can either use wlst createCred online command or write some code using OPSS APIs. Both options makes the whole life cycle story a little catchy, because a running WLS container is necessary. You can also disable credentials migration and create them directly in the WLS domain where applications are deployed. 

Like authorization policies, credentials are also OOTB migrated into the configured WLS domain credential store on application startup. By default, the credential store is the cwallet.sso file in /config/fmwconfig folder.

The following weblogic-application.xml properties govern how (and if) they're deployed.

<listener>
<listener-class>oracle.security.jps.wls.listeners.JpsApplicationLifecycleListener</listener-class>
</listener>

As for policies, the same listener migrates credentials. Avoid frustration and make sure the listener is present if you want to migrate or control how your credentials are migrated.

<application-param>
<param-name>jps.credstore.migration</param-name>
<param-value>[MERGE|OVERWRITE|OFF]</param-value>
</application-param>
  • MERGE: migrate non-existing credentials only;
  • OVERWRITE: overwrites existing credentials;
  • OFF: skips credentials migration;