Wednesday, 22 April 2015

Import/Export OIM components through API

package oim.ani.migrationAssistant;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.rmi.server.ExportException;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Hashtable;
import javax.naming.NamingException;
import com.thortech.xl.ddm.exception.DDMException;
import com.thortech.xl.ddm.exception.TransformationException;
import com.thortech.xl.vo.ddm.RootObject;
import Thor.API.Exceptions.tcAPIException;
import Thor.API.Exceptions.tcBulkException;
import Thor.API.Operations.tcExportOperationsIntf;
import Thor.API.Operations.tcImportOperationsIntf;
import oracle.iam.platform.OIMClient;

public class MigrationUtility {

private static OIMClient getOIMClient(){
Hashtable env = new Hashtable(); 
System.setProperty("weblogic.Name", "oim_server1");
System.setProperty("java.security.auth.login.config","C:\\MyDocs\\designconsole\\config\\authwl.conf");   
env.put(OIMClient.JAVA_NAMING_FACTORY_INITIAL,"weblogic.jndi.WLInitialContextFactory");
env.put(OIMClient.JAVA_NAMING_PROVIDER_URL, "t3://<oim_host>:<oim_port>");
OIMClient oimClient = new OIMClient(env);
try{
oimClient.login("XELSYSADM", "<OIM_Password>".toCharArray());
System.out.println("oim login success");
}catch(Exception e){
e.printStackTrace();
}
return oimClient;

}

public static void importConfigXML(String importFileName, String category){
OIMClient client= getOIMClient();
StringBuffer sb= new StringBuffer();
BufferedReader br = null;
tcImportOperationsIntf importOpsintf = client.getService(tcImportOperationsIntf.class);
try {
importOpsintf.acquireLock(true);
boolean acquire=importOpsintf.isLockAcquired();
br = new BufferedReader(new FileReader(importFileName));
        String readLine=null;
        while((readLine =br.readLine()) != null)
        {
                    sb.append(readLine+"\n");
        }
        if(acquire){
         Collection importFiles=importOpsintf.addXMLFile(importFileName, sb.toString()); 
         Collection missingDepndencies= importOpsintf.getMissingDependencies(importFiles, category); 
           if(missingDepndencies.isEmpty())
              {
           importOpsintf.performImport(importFiles);
           System.out.println("import success");
              } 
            }
} catch (DDMException e) {
e.printStackTrace();
} catch (tcAPIException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} catch (NamingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (TransformationException e) {
e.printStackTrace();
} catch (tcBulkException e) {
e.printStackTrace();
}
}


public static void exportToConfigXML(String exportFile, String objectToExport, String export_object_type) {
try {
OIMClient client= getOIMClient();
FileWriter fstream = new FileWriter(exportFile);
BufferedWriter out = new BufferedWriter(fstream);
tcExportOperationsIntf moExportUtility = (tcExportOperationsIntf) client.getService(tcExportOperationsIntf.class);
Collection lstObjects = moExportUtility.findObjects(export_object_type, objectToExport);
System.out.println(lstObjects);
System.out.println("Dependencies --");
System.out.println(moExportUtility.getDependencies(lstObjects));
System.out.println("Children --");
System.out.println(moExportUtility.retrieveChildren(lstObjects));
System.out.println("Dependencie Tree --");
System.out.println(moExportUtility.retrieveDependencyTree(lstObjects));
lstObjects.addAll(moExportUtility.getDependencies(lstObjects));
lstObjects.addAll(moExportUtility.retrieveChildren(lstObjects));
lstObjects.addAll(moExportUtility.retrieveDependencyTree(lstObjects));
String s = moExportUtility.getExportXML(lstObjects, "*");    
out.write(s);
System.out.println("Objects successfully exported");
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}

public static void main(String[] args){
                String export_object_type="Lookup";
exportToConfigXML("C:\\MyDocs\\export\\OIMLookups.xml", "lookup.targetReconConfig",export_object_type);
importConfigXML("C:\\MyDocs\\export\\OIMLookups.xml","Lookup");
}
}

Restoring an old sandbox state in OIM

1. Login to Enterprise Manager

2. In Application Deployments select oracle.iam.console.identity.self-service.ear link

3. In the top right of the UI choose Application Deployment | MDS Configuration (from the drop-down)

4. At the bottom of the screen choose "Runtime MBean Browser" (under the Advanced Configuration section)

5. The right side of the screen should refresh and then click on the "Operations" tab.

6. Scroll down and identify the MBean operation "listMetadataLabels" and invoke it (choose the one that takes no parameters).
  Select the sandbox pre-create to which you want to restore and copy it to the clipboard.

  For example the value you might copy might look something like - Creation_IdM_test_09:25:00

7. Now go back to Operations by clicking Return.

8. Find the MBean operation "promoteMetadataLabel" (the first one in the list)

9. Invoke the "promoteMetadataLabel" MBean operation and enter the value saved to the clipboard in step 6.

10. Restart OIM.

Tuesday, 14 April 2015

Launching custom bounded task-flow from within OIM/ Adding custom ADF pages in OIM

This post basically covers in detail about how to add a custom link and ADF page in OIM. 
We will build an ADF project, develop a custom bounded task-flow and deploy the same in OIM. Then we will configure the link to launch our custom task-flow from within OIM which will display a simple page having an input text field and command button. 
On entering some text and clicking on the button will open a dialog showing the entered text. 

Simple??? Yes.. Readers can further build their own projects fitting their own requirements.

Lets see how to do it..


Note: This project is developed with Jdeveloper, make sure to have jdeveloper with soa-jdev-extension installed.

  1.  Create a Fusion Web Application (ADF) from your Jdeveloper.

  2. Name your Application and Project.
  3. Copy jdev.lib folder from 
  4. <OracleHome>/<Middleware home>/Oracle_IDM1/server and adflibPlatformUI.jar from <OracleHome>/Middleware/Oracle_IDM1/server/modules/oracle.iam.ui.view_11.1.2 to the server where you have the Jdeveloper.
  5. Right click on the viewController, from Project Properties then Libraries and Class Path and click on Add Library.
  6. Click on Load Directory and select jdev.lib folder just copied in the previous step.
  7. Select the OIM Client Library, OIM Model Shared Library, OIM View Shared Library and click OK.
  8. Click on Add Jar/Directory add the adflibPlatformUI.jar.
  9. Right click on the viewController and create a new ADF Task Flow.
  10. Provide the task flow details.
  11. Drag and drop a view activity from the component palette in to the just created task flow definition.Name the view activity as "defaultPage".
  12. Double click on the view activity. Create a new JSF Page Fragment.Leave the file name that appears by default. Expand the Page Implementation and select the  option “Automatically Expose UI Components in a New Managed Bean” and provide the managed bean name and class name
  13. As a result of the previous step, a jsff page named defaultPage.jsff and java class named MyCustomBean would be generated and a managed bean named myCustomBean would be created.
  14. Go to the task flow definition xml and switch to the “Overview” section. You would be able to see the managed bean just created in the previous step. You can change the scope of the bean here as per requirement. In our example we will change it to pageFlow scope and save the file.
  15. Switch to the defaultPage.jsff. Drag and drop the components from the Component Palette and design the page as per requirement. In our case we will keep it simple, it will have an input text field and a button. After entering value in the text field and clicking on the button a dialog box would appear showing the entered value.
  16. After generating the jsff page please make sure to switch to "Source" view and check if the bindings of the UI components and actionListener properties are correct. Bindings should look like this - binding="#{pageFlowScope.myCustomBean.cb1}
  17. The jsff page looks like this
<?xml version='1.0' encoding='UTF-8'?>
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" version="2.1"
          xmlns:af="http://xmlns.oracle.com/adf/faces/rich"
          xmlns:f="http://java.sun.com/jsf/core">
  <af:decorativeBox binding="#{pageFlowScope.myCustomBean.db1}" id="db1">
    <f:facet name="center">
      <af:panelBox text="My Panel" binding="#{pageFlowScope.myCustomBean.pb1}" id="pb1">
        <f:facet name="toolbar">
          <af:spacer width="10" height="10" binding="#{pageFlowScope.myCustomBean.s1}"
                     id="s1"/>
        </f:facet>
        <af:inputText label="Provide Your Input" binding="#{pageFlowScope.myCustomBean.it1}" id="it1"/>
        <af:separator binding="#{pageFlowScope.myCustomBean.s2}" id="s2"/>
        <af:spacer width="10" height="10" binding="#{pageFlowScope.myCustomBean.s3}" id="s3"/>
        <af:commandButton text="Submit" binding="#{pageFlowScope.myCustomBean.cb1}"
                          id="cb1" action="#{pageFlowScope.myCustomBean.buttonAction}"/>
      </af:panelBox>
    </f:facet>
    <f:facet name="top"/>
  </af:decorativeBox>
  <!--oracle-jdev-comment:auto-binding-backing-bean-name:myCustomBean-->
</jsp:root>

17. Edit the MyCustomBean.java generated as part of step 11 to implement the action listeners or the business logic as per requirement.

18. MyCustomBean.java looks like this - 

package fusionOIMApp.view.backing;

import oracle.adf.view.rich.component.rich.input.RichInputText;
import oracle.adf.view.rich.component.rich.layout.RichDecorativeBox;
import oracle.adf.view.rich.component.rich.layout.RichPanelBox;
import oracle.adf.view.rich.component.rich.nav.RichCommandButton;
import oracle.adf.view.rich.component.rich.output.RichSeparator;
import oracle.adf.view.rich.component.rich.output.RichSpacer;

public class MyCustomBean {
    private RichDecorativeBox db1;
    private RichPanelBox pb1;
    private RichInputText it1;
    private RichSpacer s1;
    private RichSeparator s2;
    private RichSpacer s3;
    private RichCommandButton cb1;

    public void setDb1(RichDecorativeBox db1) {
        this.db1 = db1;
    }
    public RichDecorativeBox getDb1() {
        return db1;
    }
    public void setPb1(RichPanelBox pb1) {
        this.pb1 = pb1;
    }
    public RichPanelBox getPb1() {
        return pb1;
    }
    public void setIt1(RichInputText it1) {
        this.it1 = it1;
    }
    public RichInputText getIt1() {
        return it1;
    }
    public void setS1(RichSpacer s1) {
        this.s1 = s1;
    }
    public RichSpacer getS1() {
        return s1;
    }
    public void setS2(RichSeparator s2) {
        this.s2 = s2;
    }
    public RichSeparator getS2() {
        return s2;
    }
    public void setS3(RichSpacer s3) {
        this.s3 = s3;
    }
    public RichSpacer getS3() {
        return s3;
    }
    public void setCb1(RichCommandButton cb1) {
        this.cb1 = cb1;
    }
    public RichCommandButton getCb1() {
        return cb1;
    }
    public String buttonAction() {
        System.out.println("Inside buttonAction");
        RichInputText inputText = getIt1();
        String selectedText = (String)inputText.getValue();
        System.out.println("Selected: "+selectedText);
        CustomFacesUtils.addInfoMessage("Hi, You Have Entered - "+selectedText);
        return null;
    }
}

19. The CustomFacesUtils class implements few methods to render UI components. 

package fusionOIMApp.view.backing;

import java.util.Map;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import oracle.adf.model.BindingContext;
import oracle.adf.model.binding.DCBindingContainer;
import oracle.adf.model.binding.DCControlBinding;
import oracle.iam.ui.platform.utils.TaskFlowUtils;
import oracle.jbo.uicli.binding.JUCtrlActionBinding;
import oracle.jbo.uicli.binding.JUEventBinding;

public class CustomFacesUtils {
  
    
    /**
     * Launch bounded taskFlow based on provided parameters.
     * @param id ID
     * @param taskFlowId Task Flow ID
     * @param name Name
     * @param icon Icon
     * @param description Description 
     * @param helpTopicId Help Topic Id
     * @param inDialog in Dialog
     * @param params params
     */
     public static void launchTaskFlow(String id, String taskFlowId,String name, String icon,String description, String helpTopicId,boolean inDialog, Map<String, Object> params) {
         System.out.println("Inside launchTaskFlow ---------------------------------------------");
         // create JSON payload for the contextual event
         String jsonPayLoad =TaskFlowUtils.createContextualEventPayLoad(id, null, taskFlowId ,name, icon, description, helpTopicId, inDialog, params);
         // create and enqueue contextual event
         DCBindingContainer bc = (DCBindingContainer)BindingContext.getCurrent().getCurrentBindingsEntry();
         DCControlBinding ctrlBinding = bc.findCtrlBinding(TaskFlowUtils.RAISE_TASK_FLOW_LAUNCH_EVENT);
         // support both bindings - using eventBinding as well as methodAction
         if (ctrlBinding instanceof JUEventBinding) {
             JUEventBinding eventProducer = (JUEventBinding) ctrlBinding;
             bc.getEventDispatcher().queueEvent(eventProducer, jsonPayLoad);
         } else if (ctrlBinding instanceof JUCtrlActionBinding) {
             JUCtrlActionBinding actionBinding = (JUCtrlActionBinding) ctrlBinding;
             bc.getEventDispatcher().queueEvent(actionBinding.getEventProducer(), jsonPayLoad);
         } else {
             throw new IllegalArgumentException("Incorrect binding for " + TaskFlowUtils.RAISE_TASK_FLOW_LAUNCH_EVENT);
         }
         System.out.println("End of launchTaskFlow ---------------------------------------------");
         bc.getEventDispatcher().processContextualEvents();
     }
    
    /**
     * Purpose of this method is to render the Information messages
     * @param message Information Message
     */
    public static void addInfoMessage(String message) {
        if(FacesContext.getCurrentInstance() != null) {
            FacesContext.getCurrentInstance().addMessage("", new FacesMessage(FacesMessage.SEVERITY_INFO, message, message));
        }
    }

    /**
     * Purpose of this method is to render the Error messages
     * @param message Error messages
     */
    public static void addErrorMessage(String message) {
        if(FacesContext.getCurrentInstance() != null) {
            FacesContext.getCurrentInstance().addMessage("", new FacesMessage(FacesMessage.SEVERITY_ERROR, message, message));
        }
    }

}

20. Write a java class which will have actionListener method to be invoked on clicking of the link to be added in OIM. In our example it is Redirect.java which looks like this - 

package fusionOIMApp.view.backing;

import java.util.HashMap;
import javax.faces.event.ActionEvent;
import oracle.iam.ui.platform.view.backing.BaseMB;

public class Redirect extends BaseMB {
    
    /**
     * Purpose of this method is to Redirect to Manage Role
     * @param actionEvent action event
     */
    public void actionListener(ActionEvent actionEvent) {
        
        System.out.println("Entering Sample Redirect");
        CustomFacesUtils.launchTaskFlow("home", "/WEB-INF/myOIMtask-flow-definition.xml#myOIMtask-flow-definition",
        "home", "/images/home.png", null, "helpTopicId", false, new HashMap<String, Object>());
        System.out.println("Launch taskflow successfull");
    }
}

20. From inside the actionListener method using CustomFacesUtils.launchTaskFlow() method to launch our custom taskflow. This actionListener method will be configured against the actionListener listener property of the link in OIM.

21. From under WEB-INF open adfc-config.xml and switch to the Overview section. Define the Redirect class managed bean with backingBean scope.



22. Right click on the viewController and create a JSF page - 



23. Provide file name, select option "Create as XML Document" and leave other options as default.


24. It would create blank container.jspx page. Now drag and drop the taskflow definition xml (in our example myOIMtask-flow-definition.xml) from the projects pane of the Jdeveloper in to this jspx page as region.


25. Finally the page should look like this - 


26. Right click on the container.jspx page and Goto Page Definition, a dialog box would appear and prompt you to create page definition. Click on Yes.


27. Repeat this previous step for the other jsff pages as well.

28. From Application tab of Jdeveloper, select secure -> Resource Grants. From Resource Type select taskflow. From Granted To pane click on add Application Role, select authenticated-role and click on OK. From Actions pane select view and click on save.



29. Repeat this step for the web pages as well by selecting the web page option from Resource Type.


30. Compile the project and export it as ADf Library Jar File.

31. Navigate to <Oracle Home>/<Middleware Home>/Oracle_IDM1/server/apps/ directory.

32. After backing up the war oracle.iam.ui.custom-dev-starter-pack.war unpack it and within WEB-INF create a folder named lib and place your ADF library jar here. Repack the war and place it in the same location where it has been picked up from that is  <Oracle Home>/<Middleware Home>/Oracle_IDM1/server/apps/.

33. Stop OIM server. Login to weblogic admin console and then from deployments update the deployment oracle.iam.ui.custom.

34. Start OIM server.


Our custom adf project is deployed in OIM server now. Next set of steps are about how to create link in OIM and configure the actionListener to launch the taskflow that we just created and deployed.

1. Log in to OIM Identity Console. Create a sandbox and activate it. Click on the Customize link and select the view as source. Add a Command Image Link or any other component as per Requirement.
We have adde a Detail Header Custom Ops and within that created a command image link as My link.


2. Export the sandbox and unzip it. Edit page where the link was added and add actionListener property to the link. In our case since we added the link in the left navigation pane the file to be edited is <sanbox name>\oracle\iam\ui\platform\pages\mdssys\cust\site\site\lhs-nav.jsff.xml and actionListener property would appear as 
actionListener="#{backingBeanScope.myActionBean.actionListener}"

3. Re-zip the sandbox contents and re-import it in OIM.

We are done with adding link in OIM. Next set of steps are to provide authenticated-role with taskflow

1. Log in to EM console. Expand Weblogic Domain, right click <oim domain> the security and the application policies.
2.  Select Application Stripe as OracleIdentityManager and click on search.


3. Select authenticated-role and click on Edit. From the permission sub tab click on add.
In the permission class add "oracle.adf.controller.security.TaskFlowPermission", in the Resource Name add your taskflow in our case it is "/WEB-INF/myOIMtask-flow-definition.xml#myOIMtask-flow-definition".
In the Permission Actions provide "View".
Click on Select and then OK.


Finally we are done with all the configurations and deployment and good to go for testing our custom ADF page in OIM.

Login to OIM Identity Console activate the sandbox and click on the link that has been added. Following page should appear and upon providing input in the text field and submitting, a dialog same as in the following screenshot should appear.









My IDM Experience

Enterprise security has long been the luxury or a good to have framework for an organization but no more now. It is at the core of an organizations's information security structure.
Poorly controlled enterprise applications/processes/data may lead to regulatory non-compliance because if the organization is audited, management will not be able to prove that company data is not at risk for being misused. In 2005, after ID heists at ChoicePoint, Bank of America and LexusNexis lawmakers began making moves to put the onus for safeguarding customer info and identity on the shoulders of the enterprises. Sarbanes-Oxley, Gramm-Leach-Bliley, HIPAA—each holds the organization, in various ways, responsible for controlling access to customer and employee information.
Identity management is a term that refers broadly to the administration of individual identities within a system, such as a company, a network or even a country. IAM solution can be used to initiate, capture, record and manage user identities and their related access permissions in an automated fashion. This ensures that access privileges are granted according to one interpretation of policy and all individuals and services are properly authenticated, authorized and audited.
So IAM projects may not directly increase either profitability or functionality of an organization but however, a lack of effective identity and access management poses significant risks not only to compliance but also an organization’s overall security. These mismanagement issues increase the risk of greater damages from both external and inside threats.
About Myself, I am an enterprise security solutions technical consultant/developer having been working for six years in this domain with various organizations for various clients. My expertise broadly is on Oracle IAM solutions.
I have created this space to share my experiences,expertise,innovations and ideas.