Saturday, February 2, 2013

OIM11g: Bulk Load the Data in Access Policies

Hi All,

The requirement for the code that you see below comes from my client who while learning to create access policies asked me below question:

In OIM, you cannot add multiple groups in single iteration to AccessPolicy but you can remove multiple groups. What's the rationale behind this?

Well, I couldn't agree more with him and I have no answer for him and before he could throw any other question or think of asking me to modifying the OIM UI to provide capability to add multiple groups to Access Policy, I told him that I can create a Bulk Data Load Utility which can be used for loading the groups in bulk to access policies and below is the code for that:

package security.provisioning;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import com.thortech.xl.vo.AccessPolicyResourceData;
import com.thortech.xl.vo.PolicyChildTableRecord;
import Thor.API.tcResultSet;
import Thor.API.Operations.tcAccessPolicyOperationsIntf;
import oracle.iam.identity.rolemgmt.api.RoleManager;
import oracle.iam.identity.rolemgmt.api.RoleManagerConstants.RoleAttributeName;
import oracle.iam.identity.rolemgmt.vo.Role;
import oracle.iam.platform.Platform;
import oracle.iam.platform.entitymgr.vo.SearchCriteria;
import oracle.iam.scheduler.vo.TaskSupport;
import com.thortech.util.logging.Logger;

public class InitialAccessPolicyLoad extends TaskSupport {
 HashMap> mapping = new HashMap>();
 tcAccessPolicyOperationsIntf moAccesspolicyutility = null;
 private static final Logger logger = Logger.getLogger("SECURITY.EVENTS");
 private static final String CLASS_NAME = "security.provisioning.InitialAccessPolicyLoad : ";
 private static final long formKey = 25;
 private static final long objectKey = 24;
 private static final String tableKey = "22";
 private static final String objName = "OID User";
 private static final String fName = "UD_OID_USR";
 private static final String groupPrefix ="41~cn=";
 private static final String groupSuffix=",cn=Groups,dc=sample,dc=com";

 public void execute(HashMap arg0) {
  final String METHOD_NAME = "execute :: ";
  try {

   logger.debug(CLASS_NAME + METHOD_NAME + "Entering Method - execute");
   // Output File Name
   String inputFileName = arg0.get("Input File Name").toString();
   logger.debug(CLASS_NAME + METHOD_NAME + " Input File Name "
     + inputFileName);

   // Delimiter for EDR Group List
   String ROLE_DELIMITER = arg0.get("List Delimiter").toString();
   logger.debug(CLASS_NAME + METHOD_NAME + " List Delimiter "
     + ROLE_DELIMITER);

   // Delimiter for the Attributes in the Input File
   String FILE_DELIMITER = arg0.get("Field Delimiter").toString();
   logger.debug(CLASS_NAME + METHOD_NAME + " Field Delimiter "
     + FILE_DELIMITER);

   // Read Input File
   BufferedReader buff = new BufferedReader(new FileReader(inputFileName));
   buff.readLine();
   String Line = null; 
   boolean isValidRecord = true;
   String PolicyName = null;
   String RoleName = null;
   String Groups = null;
   ArrayList GroupList = new ArrayList();
   while ((Line = buff.readLine()) != null) {
  
    if (Line.startsWith("#")) {
     isValidRecord = false;
    }
  
    String[] values = Line.split(FILE_DELIMITER);
  
    if (values.length == 1) {
     PolicyName = values[0];
     isValidRecord = false;

    } else if (values.length == 2) {
     PolicyName = values[0];
     RoleName = values[1];
     isValidRecord = false;

    } else if (values.length == 3) {
     isValidRecord = true;
     PolicyName = values[0];
     RoleName = values[1];
     Groups = values[2];
     String[] gList = Groups.split(ROLE_DELIMITER);
     for(int i=0;i      GroupList.add(gList[i]);
     }
    }
  
  
    if (isValidRecord) {
     uploadPolicyData(PolicyName,RoleName,GroupList);
     logger.debug(CLASS_NAME + METHOD_NAME + "ADDING RECORD: " + Line);
    } else {
     logger.debug(CLASS_NAME + METHOD_NAME + "INVALID RECORD: " + Line);
    }

   }
   

   logger.info(CLASS_NAME + METHOD_NAME
     + " Access Policies Data Loaded");

  } catch (Exception e) {
   logger.error(CLASS_NAME + METHOD_NAME + e.getMessage());
  }
 }

 public void uploadPolicyData(String PolicyName, String RoleName, ArrayList GroupList) {
  final String METHOD_NAME = "uploadPolicyData :: ";

  try {

   tcAccessPolicyOperationsIntf moAccesspolicyutility = Platform
     .getService(tcAccessPolicyOperationsIntf.class);
   HashMap searchPolicy = new HashMap();
   searchPolicy.put("Access Policies.Name", PolicyName);
   tcResultSet result = moAccesspolicyutility.findAccessPolicies(searchPolicy);
 
   long policyKey = result.getLongValue("Access Policies.Key");
   logger.debug(CLASS_NAME + METHOD_NAME + "Access Policies.Key" +policyKey);
 
   Long roleKey = Long.parseLong(getRoleKey(RoleName));
   long[] roleKeys = { roleKey };
 
   //Add the Role NAME
   moAccesspolicyutility.assignGroups(policyKey, roleKeys);
   logger.info(CLASS_NAME + METHOD_NAME
     + " Role: "+ RoleName +" is attached to the Access Policy: " + PolicyName);
 
   for(int i = 0;i  
    HashMap childTableMap = new HashMap();
    String groupName = groupPrefix+GroupList.get(i)+groupSuffix;
    logger.debug(CLASS_NAME + METHOD_NAME + "OID Group Name: " +groupName);
    childTableMap.put("UD_OID_GRP_GROUP_NAME", groupName);
    AccessPolicyResourceData policyData = new AccessPolicyResourceData(objectKey,objName,formKey,fName,"P");
    PolicyChildTableRecord pChildTableData = policyData.addChildTableRecord(tableKey, "UD_OID_GRP", "Add", childTableMap);
    moAccesspolicyutility.setDataSpecifiedForObject(policyKey, objectKey, formKey, policyData);
    logger.info(CLASS_NAME + METHOD_NAME
      + " Group: "+ GroupList.get(i) +" attached to the Access Policy: " + PolicyName);
   }

  } catch (Exception e) {
   logger.error(CLASS_NAME + METHOD_NAME + e.getMessage());
  }
 }



 public String getRoleKey(String roleName) {

  final String METHOD_NAME = "getRoleKey :: ";
  System.out.println(CLASS_NAME + METHOD_NAME
    + "Entering Method - getRoleKey");

  RoleManager rmgr = Platform.getService(RoleManager.class);
  Set retAttrs = new HashSet();
  String roleKey = null;
  try {
   retAttrs.add(RoleAttributeName.DISPLAY_NAME.getId());
   SearchCriteria criteria = null;
   criteria = new SearchCriteria(RoleAttributeName.NAME.getId(),
     roleName, SearchCriteria.Operator.EQUAL);
   List roles = rmgr.search(criteria, retAttrs, null);
   roleKey = roles.get(0).getEntityId();
  } catch (Exception e) {
   logger.error(CLASS_NAME + METHOD_NAME + e.getMessage());
  }
  return roleKey;
 }

 // Method to check if  Role exists in OIM or not
 public boolean isRoleExist(String[] roles) {

  String METHOD_NAME = "isRoleExist :: ";
  logger.debug(CLASS_NAME + METHOD_NAME +"Entering Method - isRoleExist");
  boolean roleExist = false;
  boolean roleListEmpty = false;
  if(Arrays.toString(roles).length() == 2) {
   roleListEmpty = true;
  }

  try {
   if (!roleListEmpty) {
   RoleManager rmgr = Platform.getService(RoleManager.class);
   Set retAttrs = new HashSet();
   retAttrs.add(RoleAttributeName.DISPLAY_NAME.getId());
   SearchCriteria criteria = null;
   for (int i = 0; i < roles.length; i++) {
    criteria = new SearchCriteria(RoleAttributeName.NAME.getId(),
      roles[i], SearchCriteria.Operator.EQUAL);
    List role = rmgr.search(criteria, retAttrs, null);
    if (role.size() != 0) {
     roleExist = true;
    } else {
     logger.debug(CLASS_NAME + METHOD_NAME + roles[i]
       + " DOESN'T EXIST IN OIM");
     roleExist = false;
    }
   }
  }
   }catch (Exception e) {
    logger.error(CLASS_NAME + METHOD_NAME + e.getMessage());
  }
  return roleExist;
 }

 public HashMap getAttributes() {
  return null;
 }

 public void setAttributes() {
 }

}
I don't know how easy/hard is to modify the UI to provide the capability but considering this as "Nice To Have" requirement, I think the above solution is good enough. There are couple of things like Checking if OID Group exist or not or update(add & delete) the Groups I might need to add later.

Note: This code is specific to OID Resource and assume that access policy is already created.

 

OIM: Retrieve Access Policy Modified in Last x Days

Hi All,

This is an extension of the blog I wrote in Dec last year :

http://ajmerasunny.blogspot.com/2012/12/oim-11g-read-access-policy-data.html

Basically, the below code retrieves the Role that is attached to the Access Policy along with the Groups that are provisioned using the same. This code is with reference to Oracle Internet Directory Target System. After writing the data to the flatfile, the task also triggers the OIM OOTB "Evaulate User Policies" to propagate the changes to the affected users.

package security.provisioning;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import com.thortech.xl.vo.AccessPolicyResourceData;
import com.thortech.xl.vo.PolicyChildTableRecord;
import Thor.API.tcResultSet;
import Thor.API.Operations.tcAccessPolicyOperationsIntf;
import oracle.iam.platform.Platform;
import oracle.iam.scheduler.api.SchedulerService;
import oracle.iam.scheduler.vo.JobHistory;
import oracle.iam.scheduler.vo.TaskSupport;
import com.thortech.util.logging.Logger;


public class DumpAccessPolicyDataByDays extends TaskSupport {
 HashMap> mapping = new HashMap>();
 tcAccessPolicyOperationsIntf moAccesspolicyutility = null;
 private static final Logger logger = Logger.getLogger("CUSTOM.EVENTS");
 private static final String CLASS_NAME = "security.provisioning.DumpAccessPolicyDataByDays : ";

 @Override
 public void execute(HashMap arg0) throws Exception {

  final String METHOD_NAME = "execute :: ";
  logger.debug(CLASS_NAME + METHOD_NAME + "Entering Method - execute");

  // Output File Name
  String outputFileName = arg0.get("Output File Name").toString();
  logger.debug(CLASS_NAME + METHOD_NAME + " Output File Name "
    + outputFileName);

  // Delimiter for FTB Roles in the Input File
  String ROLE_DELIMITER = arg0.get("List Delimiter").toString();
  logger.debug(CLASS_NAME + METHOD_NAME + " List Delimiter "
    + ROLE_DELIMITER);

  // Delimiter for the Attributes in the Input File
  String FILE_DELIMITER = arg0.get("Field Delimiter").toString();
  logger.debug(CLASS_NAME + METHOD_NAME + " Field Delimiter "
    + FILE_DELIMITER);

  // Policies Updated in Last x Days
  String noOfDays = arg0.get("Modified in Last x Days").toString();
  if (noOfDays.isEmpty()) {
   noOfDays = "0";
  }

  logger.debug(CLASS_NAME + METHOD_NAME + " Modified in Last x Days "
    + noOfDays);

  // Creating FileStream for writing the mapping data
  FileWriter fstream = new FileWriter(outputFileName);
  BufferedWriter out = new BufferedWriter(fstream);

  Calendar cal = Calendar.getInstance();
  SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
  cal.add(Calendar.DATE, -Integer.parseInt(noOfDays));
  String searchDate = sdf.format(cal.getTime());

  // Output File Header
  out.write("#Role,Groups");
  out.write("\n");

  tcAccessPolicyOperationsIntf moAccesspolicyutility = Platform
    .getService(tcAccessPolicyOperationsIntf.class);
  HashMap searchPolicy = new HashMap ();
  searchPolicy.put("Access Policies.Retrofit Flag", 1);
  tcResultSet result = moAccesspolicyutility.findAccessPolicies(searchPolicy);
    

  logger.debug(CLASS_NAME + METHOD_NAME
    + "Total Count of Access Policies Present in OIM is: "
    + result.getRowCount());

  String policyDate, policyName;
  int policyCount = 0;


  HashSet groupList = new HashSet();

  for (int i = 0; i < result.getTotalRowCount(); i++) {
 
   result.goToRow(i);
 
   long policyKey = result.getLongValue("Access Policies.Key");
   logger.debug(CLASS_NAME + METHOD_NAME + "Access Policy Key :" + policyKey);
 
   policyDate = result.getStringValue("Access Policies.Update Date");
   logger.debug(CLASS_NAME + METHOD_NAME + "Access Policies.Update Date:-> "+policyDate);
 
   policyName = result.getStringValue("Access Policies.Name");
   logger.debug(CLASS_NAME + METHOD_NAME + "Access Policy Name:"
     + policyName );

   if (searchDate.compareTo(policyDate) <= 0) {
    ++policyCount;
    logger.debug(CLASS_NAME + METHOD_NAME
      + "Searching for Access Policies Updated Since " + searchDate);
               
    tcResultSet policyresult = moAccesspolicyutility
      .getDataSpecifiedFor(policyKey);
  
    for (int f = 0; f < policyresult.getTotalRowCount(); f++) {
     policyresult.goToRow(f);
     long formKey = policyresult
       .getLongValue("Structure Utility.Key");
     long objectKey = policyresult.getLongValue("Objects.Key");
     tcResultSet groupResult = moAccesspolicyutility
       .getAssignedGroups(policyKey);
     for (int j = 0; j < groupResult.getTotalRowCount(); j++) {
      groupResult.goToRow(j);

      // Role
      String Role = groupResult
        .getStringValue("Groups.Group Name");
      logger.debug(CLASS_NAME + METHOD_NAME + " Role: "
        + Role);

      AccessPolicyResourceData policyData = moAccesspolicyutility
        .getDataSpecifiedForObject(policyKey,
          objectKey, formKey);
      HashMap pData = policyData
        .getChildTables();
      Set s = pData.keySet();
      Iterator it = s.iterator();
      logger.debug(CLASS_NAME + METHOD_NAME
        + "Below are the EDR Groups associated with FTB Role "
        + ftbRole);
      while (it.hasNext()) {
       String tableKey = it.next().toString();

       PolicyChildTableRecord[] pChildTableData = policyData
         .getChildTableRecords(tableKey);
       for (int g = 0; g < pChildTableData.length; g++) {
        String GroupName = pChildTableData[g]
          .getValue("UD_OID_GRP_GROUP_NAME");
        String arrtemp1[] = GroupName.split(",");
        String arrtemp2[] = arrtemp1[0].split("=");
        logger.debug(CLASS_NAME + METHOD_NAME
          + " " + arrtemp2[1]);
        // Adding the Groups in a ArrayList
        groupList.add(arrtemp2[1]);
       }
      }

      // Adding the  Role as Key and Groups as  ArrayList in  HashMap
      mapping.put(Role, groupList);

      // Instantiating new ArrayList for storing Groups
      groupList = new HashSet();
     }

    }
   }
  }

  logger.info(CLASS_NAME + METHOD_NAME
    + "Count of Access Policies matching Search Criteria is "
    + policyCount);


   
  // Writing the Mapping in FlatFile
  Set s = mapping.keySet();
  Iterator itr = s.iterator();
  while (itr.hasNext()) {
   String key = itr.next().toString();
   out.write(key);
   out.write(FILE_DELIMITER);
   Iterator listitr = mapping.get(key).iterator();
   int listSize = mapping.get(key).size();
   int i = 0;
   while (listitr.hasNext()) {
    out.write(listitr.next().toString());
    i++;
    if (i != listSize)
     out.write(ROLE_DELIMITER);
   }
   out.write("\n");
  }
  

  // Invoking Evaluate User Policies Schedule Task
   SchedulerService schService = Platform.getService(SchedulerService.class);
   schService.triggerNow("Evaluate User Policies");
   logger.info(CLASS_NAME + METHOD_NAME + " Evaluate User Policies is Executed");
   //Integer status = schService.getStatusOfJob("Evaluate User Policies");


    // Closing the File Stream
    out.close();
    fstream.close();
    logger.info(CLASS_NAME + METHOD_NAME +"Mapping written on " + outputFileName);
    


 }
 @Override
 public HashMap getAttributes() {
  return null;
 }

 @Override
 public void setAttributes() {
 }

}