Help with Assignment Rule

Which IIQ version are you inquiring about?

Version 8.3

Share all details related to your problem, including any error messages you may have received.

I need to create an Assignment Rule for populating a Business Role.

The criteria for the Rule is - all Identities whos location is not Canada but they are the Manager to an Identity whos location is in Canada.

I don’t know how/where to get started with this and was hoping someone had an example Assignment Rule that I could try to work off of to get this working.

I have been searching and reading the “Rules” doc, but didn’t find anything that seemed like this type of rule.

Any help would be greatly appreciated!

Thank you.

1 Like

Hi Christopher,
It’s actually pretty simple rule. Something like that

import sailpoint.object.QueryOptions;
import sailpoint.object.Filter;

String identityId = identity.getId();
String location = "Canada";
String locationAttributeName = "location";


if(!location.equals(identity.getAttribute(locationAttributeName)) {
     QueryOptions qo = new QueryOptions();

     Filter f1 = Filter.eq("manager.id",identityId);
     Filter f2 = Filter.eq("location",location);
     qo.add(Filter.and(f1,f2));
     Iterator it = context.search(Identity.class,qo);
     if(it.hasNext()) {
          return true;
     }
}
return false;

I’ve wrote it from the top of my head so you may need to tune it a bit but I wanted to give you the idea how you can achieve this.

Generaly 2 checks to be done

  1. We check if user is not in Canada
  2. We check if there is at least one identity where identity is set as manager and location is Canada
1 Like

just my though … it may better count objects instead of search and return true when count (countObjects(java.lang.Class cls, QueryOptions options)) is greater than 0 … thinking in terms of performance

1 Like

Hi Hemant,
That’s also possible - remeber context.search does not return all objects but just iterator to first object.

That’s why in this case I believe both solutions will have similar performance.

Thanks so much for the replies and help, WAY over my level of understanding!

I tried the code and get -
BeanShell script error: bsh.ParseException: Parse error at line 16, column 19. Encountered: qo BSF info: NonCanadianMgr at line: 0 column: columnNo

I over simplified my question, I don’t actually have a single ‘Canada’ location I can search. I have to search for multiple values, I was hoping it would be something like this (excuse my ignorance) -

if (identity.location == "Saskatoon" || identity.location == "Toronto" || identity.location == "Vancouver"){
	if (identity.manager.location != "Saskatoon" && identity.manager.location != "Toronto" && identity.manager.location !== "Vancouver") {
		Return identity.manager;
		}
	}

Thanks again for your help, at least I have a starting place now!!

1 Like

share the full assignment rule

1 Like

I started with just ‘Saskatoon’ in hopes I could expand it to all three locations at some point -

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE Rule PUBLIC "sailpoint.dtd" "sailpoint.dtd">
<Rule created="1703184577302" id="0aab09888bec1fc4818c8db6331622e0" language="beanshell" modified="1703184879051" name="NonCanadianMgr" type="IdentitySelector">
  <Description>This rule is used to select an Identity that is related to the given Identity</Description>
  <Signature returnType="boolean">
    <Inputs>
      <Argument name="log" type="org.apache.commons.logging.Log">
        <Description>
          The log object associated with the SailPointContext.
        </Description>
      </Argument>
      <Argument name="context" type="sailpoint.api.SailPointContext">
        <Description>
          A sailpoint.api.SailPointContext object that can be used to query the database if necessary.
        </Description>
      </Argument>
      <Argument name="identity" type="Identity">
        <Description>
          The identity.
        </Description>
      </Argument>
      <Argument name="roleName" type="String">
        <Description>
          The name of the sailpoint.object.Bundle (role) that is being selected for the Identity. 
          If roles are not applicable to this Identity selection, this value will be void.
        </Description>
      </Argument>
    </Inputs>
    <Returns>
      <Argument name="success">
        <Description>
            True if the selection was successful; false otherwise.
        </Description>
      </Argument>
    </Returns>
  </Signature>
  <Source>import sailpoint.object.QueryOptions;
import sailpoint.object.Filter;

String identityId = identity.getId();
String location = "Saskatoon";
String locationAttributeName = "location";



if(!location.equals(identity.getAttribute(locationAttributeName)) {
     QueryOptions qo = new QueryOptions();

     Filter f1 = Filter.eq("manager.id",identityId);
     Filter f2 = Filter.eq("location",location);
     qo.add(Filter.and(f1,f2));
     Iterator it = context.search(Identity.class,qo);
     if(it.hasNext()) {
          return true;
     }
	 

}
return false;</Source>
</Rule>

1 Like

Just to give you all a good laugh, this is the direction I was heading with it –

import sailpoint.object.QueryOptions;
import sailpoint.object.Filter;

String identityId = identity.getId();
String location1 = "Saskatoon";
String locationAttributeName1 = "location1";
String location2 = "Toronto";
String locationAttributeName2 = "location2";
String location3 = "Vancouver";
String locationAttributeName3 = "location3";
String location4 = "Remote - Canada";
String locationAttributeName4 = "location4";


if(!location.equals(identity.getAttribute(locationAttributeName1)) {
     QueryOptions qo = new QueryOptions();

     Filter f1 = Filter.eq("manager.id",identityId);
     Filter f2 = Filter.eq("location",location1);
     qo.add(Filter.and(f1,f2));
     Iterator it = context.search(Identity.class,qo);
     if(it.hasNext()) {
          return true;
     }
	 
if(!location.equals(identity.getAttribute(locationAttributeName2)) {
     QueryOptions qo = new QueryOptions();

     Filter f3 = Filter.eq("manager.id",identityId);
     Filter f4 = Filter.eq("location",location2);
     qo.add(Filter.and(f3,f4));
     Iterator it = context.search(Identity.class,qo);
     if(it.hasNext()) {
          return true;
     }	 
	 
if(!location.equals(identity.getAttribute(locationAttributeName3)) {
     QueryOptions qo = new QueryOptions();

     Filter f5 = Filter.eq("manager.id",identityId);
     Filter f6 = Filter.eq("location",location3);
     qo.add(Filter.and(f5,f6));
     Iterator it = context.search(Identity.class,qo);
     if(it.hasNext()) {
          return true;
     }	 
	 
if(!location.equals(identity.getAttribute(locationAttributeName4)) {
     QueryOptions qo = new QueryOptions();

     Filter f7 = Filter.eq("manager.id",identityId);
     Filter f8 = Filter.eq("location",location4);
     qo.add(Filter.and(f7,f8));
     Iterator it = context.search(Identity.class,qo);
     if(it.hasNext()) {
          return true;
     }	 
	 
}
return false;

:smiley:

1 Like

the condition if(!location.equals(identity.getAttribute(locationAttributeName)) doesn’t have closing bracket you need to use if(!location.equals(identity.getAttribute(locationAttributeName)))

1 Like

Hi Christoph,
You don’t need to do that much ‘ifs’. There is method available in Filter class that allows you to check for multiple values

so your code can be something like that

import sailpoint.object.QueryOptions;
import sailpoint.object.Filter;

String identityId = identity.getId();
String locationAttributeName = "location";
String identityLocation = identity.getAttribute(locationAttributeName);

List canadaLocations = new ArrayList();

canadaLocations.add("Saskatoon");
canadaLocations.add("Toronto");
canadaLocations.add("Vancouver");
canadaLocations.add("Remote - Canada");

if(!canadaLocations.contains(identityLocation))) {
     QueryOptions qo = new QueryOptions();

     Filter f1 = Filter.eq("manager.id",identityId);
     Filter f2 = Filter.in(locationAttributeName ,canadaLocations);
     qo.add(Filter.and(f1,f2));
     Iterator it = context.search(Identity.class,qo);
     if(it.hasNext()) {
          return true;
     }	 
}
return false;

if you need to check more than one attribute (let’s say attributes from location1 to location5) it’s also possible similar way

import sailpoint.object.QueryOptions;
import sailpoint.object.Filter;
import org.apache.commons.collections.CollectionUtils;

String identityId = identity.getId();
String locationAttributeName1 = "location1";
String locationAttributeName2 = "location2";
String locationAttributeName3 = "location3";
String locationAttributeName4 = "location4";
String locationAttributeName5 = "location5";
String identityLocation1 = identity.getAttribute(locationAttributeName1);
String identityLocation2 = identity.getAttribute(locationAttributeName2);
String identityLocation3 = identity.getAttribute(locationAttributeName3);
String identityLocation4 = identity.getAttribute(locationAttributeName4);
String identityLocation5 = identity.getAttribute(locationAttributeName5);

List identityLocations = new ArrayList();
identityLocations.add(identityLocation1);
identityLocations.add(identityLocation2);
identityLocations.add(identityLocation3);
identityLocations.add(identityLocation4);
identityLocations.add(identityLocation5);

List canadaLocations = new ArrayList();

canadaLocations.add("Saskatoon");
canadaLocations.add("Toronto");
canadaLocations.add("Vancouver");
canadaLocations.add("Remote - Canada");

if(!CollectionUtils.containsAny(identityLocations, canadaLocations)) {
     QueryOptions qo = new QueryOptions();

     // If managerID = identityId AND (locationAttr1-5 contains canadaLocation)

     Filter f1 = Filter.eq("manager.id",identityId);
     Filter f21 = Filter.in(locationAttributeName1,canadaLocations);
     Filter f22 = Filter.in(locationAttributeName2,canadaLocations);
     Filter f23 = Filter.in(locationAttributeName3,canadaLocations);
     Filter f24 = Filter.in(locationAttributeName4,canadaLocations);
     Filter f25 = Filter.in(locationAttributeName5,canadaLocations);

     Filter f3 = Filter.or(f21,f22,f23,f24,f25);

     qo.add(Filter.and(f1,f3));

     Iterator it = context.search(Identity.class,qo);
     if(it.hasNext()) {
          return true;
     }	 
}
return false;

Remember this rule needs to be as efficient as possible as it will be executed for every single identity during identity refresh so if you put to much if’s it may impact performance.

I think it is just awesome that you guys share your time and knowledge helping other people. Thank you very much, I’ll go see what I can do with this.

Have a great weekend, Happy Holidays if that applies to you!!

Thanks again.

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.