Friday, August 7, 2015

Access Policy Harvesting in OIM 11gR2PS2

Today I am going to write about a new and very powerful feature introduced in OIM 11gR2PS2 which is Access Policy Harvesting. Though its late but better late than ever :)
Well the oracle document has covered the part of how to do it, but the doc doesn't much explain as to what it is. Below is the link to original Oracle Doc-:
Access Policy Harvesting

Lets start with a use case. An organization decides to implement Identity Management and Role based access control using OIM 11gR2PS2. As a developer we will first install/develop connectors for provisioning, de-provisioning and reconciliation. You will create Roles and access policies to get the RBAC working. Now arises the problem with the existing accounts. Yes definitely, we can reconcile them but the accounts won't be linked with the access policies. So for the existing accounts, as they weren't created by the access policy, can't be revoked or modified by the access policy. Lets understand more with an example.

Lets say there is role "Sales Supervisor" in OIM, tied to access policy "Sales Supervisor". The access policy provides following application accesses.
1) Application A - entitlement SALE_SUP.
2) Application B - entitlement SALES_SUPERVISOR.

There is a user X having both the above application accesses. Now for this user you shouldn't just assign the role in OIM as after assigning the role the access policy will try to create the accounts and as the accounts already exist the provisioning will fail. Else we can reconcile the accounts first then assign the Role but this will not actually link the accounts with your access policy and then comes a much bigger risk. What if the user changes his/her job and goes to finance, in this case user will need a role something like "Finance Supervisor". Now we will remove the role "Sales Supervisor" which should remove all the user's Sales related access, but it won't as the accounts weren't linked with the role/access policy.

To overcome this there are workarounds like have the CREATE_USER process task call the tcCompelteTask adapter. Assign the role to the user, access policy will provision the accounts successfully. Replace the tcCompelteTask with the actual adapter and get it working. Else we can also modify the DB tables to manually retrofit the access policy key for the reconciled accounts and so on. But being workarounds they impose risk and chances of error.

Now is the time for introduction of "Access Policy Harvesting". With this new feature you can actually link the reconciled accounts with the existing access policies and future changes to the accounts will be managed by the access policy changes. Below are steps (same as the Oracle Docs) to enable "Access Policy Harvesting"

1) Set the values of XL.AllowAPHarvesting and XL.AllowAPBasedMultipleAccountProvisioning system properties to TRUE
2) Set the retrofit flag to ON for the policy to be linked by selecting Retrofit Access Policy.
3) Populate the ITResource field in access policy defaults. (Make sure the IT resource attribute is populated in the access policy).
4) Designate a field on the process form (for all applications part of the access policy) as the discriminator field and set the value of the Account Discriminator property to True. Then, populate the access policy defaults for the account discriminator field. Well if you don't have the multiple account provisioning enabled then just for the sake of simplicity set the property Account Discriminator to true for IT resource field. If you have multiple account/per user for an application then you must be knowing which attribute can discriminates the accounts and you can set the property to true for it.

The above four steps will enable Access Policy Harvesting. Below should be the sequence to do the harvesting.

1) Reconcile all the application accounts for the user(s) at least the ones which are part of your access policy.
2) Verify if all the accounts are linked to user(s).
3) Assign the corresponding role(s) to the user(s).
4) Run the evaluate policy job.
5) You can monitor the oim_server.out file which will print that the harvesting is happening, or if at all there are any errors.


Feel free to ask any questions in the comments

-gaurav


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