Thursday, July 3, 2014

Association of existing Database Security Store for a new Oracle Identity and Access Management Domain using mjoin


Configuration of database security store for Oracle Identity and Access Management installation is a mandatory step as this is the only type of security store supported.

Certain scenarios occur when you create the security store for a domain and due to some configuration issue or for any other reason you need to associate your existing security store to a new domain. This can be a painful job if you don't do it correctly. Please follow the below steps to re associate the security store.

This is also applicable when you clone the existing environment (db and filesystem) and try to bring up the new environment.

Prerequisites:

  1. The domain directory with which the store was initially created still exists.
  2. You must know the password with which store was initially created/configured. 

Steps:
  1. The security store with in your DB is encrypted using an encryption key. The first step is to get that key exported. Let's assume domain1 is the domain initially configured with the security store and domain2 is the new domain that needs to be associated. First export the encryption key using below command -

Windows:


<MW_HOME>\oracle_common\common\bin\wlst.cmd exportEncryptionKey(jpsConfigFile=<jpsConfigFile>, keyFilePath=<keyFilePath>, keyFilePassword=<keyFilePassword>)

For eg:

exportEncryptionKey(jpsConfigFile="<MW_HOME>\\user_projects\\domains\\domain1\\config\\fmwconfig\\jps-config.xml", keyFilePath="anyDir\\key" , keyFilePassword="idm123")



Linux:

<MW_HOME>/oracle_common/common/bin/wlst.sh exportEncryptionKey(jpsConfigFile=<jpsConfigFile>, keyFilePath=<keyFilePath>, keyFilePassword=<keyFilePassword>)

For eg:

exportEncryptionKey(jpsConfigFile="<MW_HOME>/user_projects/domains/domain1/config/fmwconfig/jps-config.xml", keyFilePath="anyDir/key" , keyFilePassword="idm123")


Notes:

1) This command may not run in one line and you will get the syntax error, in that case just first run wlst.cmd or wlst.sh, wait for the wlst prompt and then run the function: exportEncryptionKey(jpsConfigFile=<jpsConfigFile>, keyFilePath=<keyFilePath>, keyFilePassword=<keyFilePassword>)


2) The path to jpsConfigFile should be of your old domain (domain1). 
    <domain1/config/fmwconfig/jps-config.xml>

3) keyFilePath is the path where you want to export the encryption key.

4) keyFilePassword is the password you used to create/configure the security store.



  1. Associating the security store with the new domain (domain2) using join operation. Please run the following command:

Windows:

<MW_HOME>\oracle_common\common\bin\wlst.cmd <IAM_HOME>\common\tools\configureSecurityStore.py -d <domaindir> -c IAM -p <opss_schema_password> -m join -k <keyfilepath which is exported in previous step> -w <keyfilepassword>

For e.g.

<MW_HOME>\oracle_common\common\bin\wlst.cmd <IAM_HOME>\common\tools\configureSecurityStore.py -d <MW_Home>\user_projects\domains\domain2 -c IAM -p oracle123 -m join -k anyDir -w idm123



Linux:

<MW_HOME>/oracle_common/common/bin/wlst.sh <IAM_HOME>/common/tools/configureSecurityStore.py -d <newdomaindir> -c IAM -p <opss_schema_password> -m join -k <keyfilepath which is exported in previous step> -w <keyfilepassword>

For e.g.

<MW_HOME>/oracle_common/common/bin/wlst.cmd <IAM_HOME>/common/tools/configureSecurityStore.py -d <MW_Home>/user_projects/domains/domain2 -c IAM -p oracle123 -m join -k anyDir -w idm123

Notes:

1) The domain directory should be of new domain.
2) IAM is a static keyword that is used when creating the security store.
3) OPSS schema password is the one used to login to oracle db schema.
4) keyFilePath is the path till directory where we exported the encryption key file in previous step.
5) keyFilePassword is the password used to create the security store initially.

  1. This should associate your existing security store with the new domain. To validate please run the below commands:
On Windows:

<MW_HOME>\oracle_common\common\bin\wlst.cmd <IAM_HOME>\common\tools\configureSecurityStore.py -d <domaindir> -m validate
For example:

<MW_HOME>\oracle_common\common\bin\wlst.cmd <IAM_HOME>\common\tools\configureSecurityStore.py -d <MW_Home>\user_projects\domains\domain2 -m validate

On UNIX:

<MW_HOME>/oracle_common/common/bin/wlst.sh <IAM_HOME>/common/tools/configureSecurityStore.py -d <domaindir> -m validate
For example:

<MW_HOME>/oracle_common/common/bin/wlst.sh <IAM_HOME>/common/tools/configureSecurityStore.py -d <MW_Home>/user_projects/domains/ domain2 -m validate


Feel free to ask any questions in the comments

-gaurav

Tuesday, May 6, 2014

OUI-67074:OPatch failed during prerequisite checks: java.lang.NullPointerException

You may get an error while applying a certain OIM/SOA patch - 

OUI-67074:OPatch failed during prerequisite checks: java.lang.NullPointerException.

There won’t be much details in the logs to let you analyze, and you will be left with no clue. The cause and solution of the error is there in the readme of the patch.

NOTE: On WINDOWS, the prefrred location is the drive root directory. For example, "C:\PATCH_TOP" and avoid choosing locations like,"C:\Documents and Settings\username\PATCH_TOP". This is necessary due to the 256 characters limitation on windows platform” 

So, please try to keep the path to PATCH_TOP shortest.

-gaurav

Wednesday, April 30, 2014

How to implement custom recon in OIM 11G R2?


Lets assume we have a disconnected/connected application in OIM which is integrated using a custom connector. To perform the reconciliation for such a custom application a custom code is required to fetch the data from target and create reconciliation event.

This post is to illustrate the recon for a disconnected application using a flat file as a source of data.

  • For disconnected application we‘ll need to find a mechanism to get the recon data from the application, simplest of this can be getting a text/csv file from the application team daily/weekly depending upon the recon schedule. For "connected application" we can connect directly to the application and fetch the data.

  • Generate the recon profile for the application this includes adding the fields for reconciliation in the Object reconciliation tab of resource object.

       For eg. We have 2 fields for recon - Account ID, Account Name. Adding ITResource field is very     important for custom recon to work
                  
  • Create a recon rule and map the recon attribute with the user profile attribute. Make sure the Active checkbox is checked.

  • In Reconcilliation tab goto Reconcilliation Action Rules and do the mapping as below.

  • Update the reconciliation field mapping in the process definition.




  • Create a custom scheduled job. You can refer my post for creating a scheduled job in OIM.
    • We are having below three arguments for the job. For eg:
      • File Name (Complete path)
      • ITResource Name (Mandatory)
      • Resource Object Name (Mandatory)

  • Write code to generate the custom recon events.

    import Thor.API.Exceptions.tcAPIException;
    import Thor.API.Operations.tcProvisioningOperationsIntf;
    import Thor.API.Operations.tcUserOperationsIntf;
    
    import com.bea.security.providers.xacml.entitlement.parser.Roles;
    
    import java.io.BufferedReader;
    import java.io.FileReader;
    import java.io.IOException;
    
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Vector;
    
    import oracle.iam.platform.Platform;
    import oracle.iam.reconciliation.api.BatchAttributes;
    import oracle.iam.reconciliation.api.EventAttributes;
    import oracle.iam.reconciliation.api.InputData;
    import oracle.iam.reconciliation.api.ReconOperationsService;
    import oracle.iam.reconciliation.api.ReconciliationResult;
    import oracle.iam.scheduler.vo.TaskSupport;
    
    public class dummyRecon extends TaskSupport {
        private tcUserOperationsIntf userOperation = null;
        private tcProvisioningOperationsIntf provisionOperation = null;
        private ReconOperationsService reconOperation;
        private Vector data = new Vector();
        private String fileName;
        private String ItResource;
        private String resourceObjName;
        public dummyRecon() {
    
        }
    
        public void execute(HashMap hashMap) {
            this.fileName = hashMap.get("File Name").toString();
            this.ItResource = hashMap.get("ITResource Name").toString();
            this.resourceObjName= hashMap.get("Resource Object Name").toString(); 
    initialize();
            getReconData();
            triggerRecon();
    
        }
    
        private void initialize() {
            this.userOperation =
                    ((tcUserOperationsIntf)Platform.getService(tcUserOperationsIntf.class));
            this.provisionOperation =
                    ((tcProvisioningOperationsIntf)Platform.getService(tcProvisioningOperationsIntf.class));
            this.reconOperation =
                    ((ReconOperationsService)Platform.getService(ReconOperationsService.class));
        }
    
        public HashMap getAttributes() {
            return null;
        }
    
        public void setAttributes() {
        }
    
        private void getReconData() {
    
            String file = this.fileName;
    
            BufferedReader reader = null;
            try {
                reader = new BufferedReader(new FileReader(file));
                int headerFieldCount = 0;
    
                String line = "";
    
    
                while ((line = reader.readLine()) != null) {
    
                    this.data.add(line.split("\\,"));
    
                }
    
            } catch (Exception e) {
                e.printStackTrace();
                try {
                    reader.close();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
            } finally {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
    
        }
    
        private void triggerRecon() {
            EventAttributes ea = new EventAttributes();
            for (int i = 0; i < data.size(); i++) {
                String[] temp = (String[])data.get(i);
                Map reconMap = new HashMap();
    
                reconMap.put("Account ID", temp[0]);
                reconMap.put("Account Name", temp[1]);
                reconMap.put("ITResource", this.ItResource); //Must Have this
                ea.setEventFinished(true);
                long eventKey =
                    reconOperation.createReconciliationEvent(this.resourceObjName,
                                                             reconMap, ea);
                try {
                    reconOperation.processReconciliationEvent(eventKey);
                } catch (tcAPIException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
    
            }
        }
    } 

    If you have any questions or need more details, please update the comments. I will try my best to answer them.

    -gaurav

    How to disable past dates in calendar component in OIM?


    When we declare any field on form as Date it renders a calendar with all the available dates. Depending on the requirements we may  need to restrict the display of dates. 

    For eg: Disable all future or past dates.

    This is post is to demonstrate the use of a custom managed bean to disable all past dates in the calendar. The ADF component that gets created is <af:inputdate>. This component has a property "minValue" which when set to a date, disables all prior dates. We will be setting this property to SYSDATE so that all past dates will be disabled and cannot be selected by the user. Below are the steps - :


    1. Lets start with creating the managed bean, create a new generic application in Jdev.
    2. Name the application, the prefix should be oracle.iam.ui custom.
    3. Name the project, don't select any technologies and click finish.
    4. Right click on the application and say new.
    5. Select ADF View Controller project.
    6. Name the project.
    7. Make sure the default package is oracle.iam.ui custom.
    8. Right click on the project, goto project properties> Libraries and Classpath> Add Library> Specify the
      path to OIM_HOME>Jdev>Lib and add OIM Client, OIM Model Shared and OIM View Shared library.        
      NOTE:
      These are the library files not the actual JARs, these just contain the path to the JAR files which are actually present at OIM_HOME>Jdev>modules and client folder. If you do not have local OIM Installed then download the library files to a local directory and download the modules and client folder also. The modules and client folder should be at the parent directory level of your library files. For eg if Library files are in C:/jdev/jars/libraries then your modules and client folder should be at C:/jdev/jars
    9. Create a new a new class in the project. The class should extends oracle.iam.ui.platform.view.backing.BaseStateMBand implements Serializable.
    10. Create a private property of type Date. Generate its getter and setter.
    11. The getter method should be actually returning the formatted current date. Refer the code as below:                                                                                                                                                                                import java.io.Serializable;
      import java.text.DateFormat;
      import java.text.SimpleDateFormat;
      import java.util.Calendar;
      import java.util.Date;

      public class CurrentDate {
      publicCurrentDate() {
      super();
          }
      private Date minDate = new Date();

      public void setMinDate(Date minDate) {
      this.minDate = minDate;
          }

      public Date getMinDate() {
      try {
                  Calendar now = Calendar.getInstance();
      java.util.Date date = now.getTime();
      DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
                  String currentDate = formatter.format(date);
      minDate = formatter.parse(currentDate);
      System.out.println("$$$$$$$$$$$$$$$$$Current Date is- $$$$$$$$$$" +
      minDate);
      returnformatter.parse(currentDate);
              } catch (Exception e) {
      return null;
              }
          }
      }
    12. Make sure there are no compilation errors, your bean is created now go to webcontent>PageFlows>adfc-config.xml.
    13. Declare your managed bean and specify its scope.
    14. The code is ready now, we need to deploy it to a jar file. Right Click on the project and  Go to deployments tab. Delete the deployment profile, if any. Click on new> Select the archive type as ADF Library Jar File, Name the archive as “adflibCustomModel” and hit ok.


    15.  Right click on the project and deploy, the jar will be created in the project>deploy folder, optionally the deployment path will be there in the logs.
    16.  This jar needs to be deployed to OIM, pls download the oracle.iam.ui.custom-dev-starter-pack.war from OIM_HOME>apps directory. Extract its contents. Place the adflibCustomModel.jar inside WEB-INF/lib. Lib directory might not exists, if so create it.
    17.  ZIP the war again and upload/place it to OIM_HOME>apps. To avoid extra work, take a backup of war.
    18.  Go to weblogic console>deployments> Click lock and edit>Check oracle.iam.ui.custom(11.1.1,11.1.1) and hit update> Click on next, dependent deployments will be displayed, check both of them and finish>Click on Activate Changes.
    19.  This may take time and you might get a timeout error, don’t worry your deployments are updated, restart the oim servers.
    20.  The code deployments is complete, we need to map our bean property to component property. Login as xlesysadm>Create and activate a SandBox> Assuming the date component is in a application request form> go to catalog>search the application>add to cart>checkout.
    21.  Click on customize link>select the date component and change any of its property. The minValue property cannot be set using webcenter, we need to set the property by editing the jsff file manually after exporting the sandbox. Lets just set the show required property to true. 
    22.  Close the webcenter, export the sandbox extract it and go to “oracle\iam\ui\runtime\form\view\pages\mdssys\cust\site\site” you will find a createform.jsff xml. Edit it> go to the the date component and add the minValue property like below:
      <af:inputDatexmlns:af="http://xmlns.oracle.com/adf/faces/rich" value="#{bindings.Date__c.inputValue}" label="#{bindings.Date__c.hints.label}" required="#{bindings.Date__c.hints.mandatory}" shortDesc="#{bindings.Date__c.hints.tooltip}" id="_xg_7" autoSubmit="true" minValue="#{currentDateBean.minDate}">
    23. Save the file and create again the sanbox.zip, login to OIM and import the sandbox. Follow step 20 and set the required property to false (we had just set it so that we can get the tag in sandbox).


      If you have any questions or need more details, please update the comments. I will try my best to answer them.
      -gaurav