How to prevent a user from being listed as their own manager's manager

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.

Hello, I am currently working on a project where I need to prevent a specific scenario in our identity management - a user being listed as their own manager’s manager, creating a circular management relationship.

I understand that this might be achievable through the creation of an Advanced Policy or a custom rule, but I am unsure of the best practices to follow in this specific case. I am using SailPoint Version 8.3.

Could anyone provide guidance or advice on how to best approach this? Any examples of rules or policies that have been used to successfully prevent such scenarios would be greatly appreciated.

Thank you in advance for your assistance.

First you need to check how this manager value is populated ? Is that getting set via mapping from some trusted source .

Also hoe the manger is set in the trsuted source is that the same way ?

If manager id comes from authoritative source of identities than the easiest way would be customisation rule which removes manager if id of the manager is the same as id of the identity. This is in short - for more detailed and a bit more sophisticated solution we would need to know a bit.more details.

Especialy what is the source of manager information, what are the mappings etc…

@acgsneddon To provide a solution there is more information required.

  1. How is the manager attribute populated for the identity and on what basis
  2. Need the Application information from which the manager attribute is fetched

I had a similar scenario wherein I created a policy to validate

Thank you for your responses.

Our manager attribute is populated from Workday for HR-managed staff, which serves as the authoritative source. For our third-party staff, however, IdentityIQ is the source. Given these different sources for the two user groups, it seems we may need separate checks and measures for each.

Currently, we have a rule that checks for manager loops among identities. However, it doesn’t prevent a scenario where a third-party user is selected as their manager’s manager.

While I understand that a policy may not prevent such changes from being submitted, could it be configured to alert the requester of the discrepancy?

Where is the request being submitted, is it a form within SailPoint itself?
If so right a validation rule for the manager field selection to avoid this.

It would be done in SailPoint itself. Would you have an example of what the validation rule would look like?

Do you have the Form where you are doing this?
We can have the validation rule within that form fields.

Are you doing this using OOTB Edit Identity Quicklink? or a Custom Form?

if its a custom form have a validation rule to field to check against the cycling condition, if its a OOTB Edit Identity , check what is associated workflow in Life cycle Manager and within the workflow add a step to check this condition and throw an exception within that so that manager flow will not happen

Need to explore if we can have a validation directly on the Edit Identity page itself but above approach can be used , along with the Customization rule approach for your HR Managed staff

I’m using a Custom Form and with the details that have been provided, am looking at creating a validation rule. I’m currently trying to get the following script to work:

This rule is used to validate that a user does not set someone as their manager if they are listed as that person’s manager

import sailpoint.object.Identity;
    String managerName = form.getField("manager").getValue();
    Identity manager = context.getObjectByName(Identity.class, managerName);

    String identityName = form.getField("adLogin").getValue(); // Replace "adLogin" with the actual field name if it's different

    if (manager != null && manager.getManager() != null && manager.getManager().getName().equals(identityName)) {
        return "A user cannot be set as a manager of their own manager.";
    }

    return null;

Take a look on this article - actually Manager Loop is more complex in the end

https://community.sailpoint.com/t5/IdentityIQ-Articles/Detecting-manager-loops-in-your-IdentityIQ-data/ta-p/81367

1 Like

@acgsneddon
Please try to incorporate the code from rule mentioned by @kjakubiak in your validate script, this should resolve the use case related to Non-HR System Managed users.

@acgsneddon
You Can use below code as well to find if manager set is a cyclic Manager

Call the method getAllReportees with the user that is being modified and check if the result list is not null and contains the name of the user that is being set as manager ( basically value being set in form) , if the user is part of this list, you should throw an error.

Note - Please modify the code related queryoptions condition if you want but what I provided is a standard one and the method getAllReportees gives all the direct and indirect reportess of a given user

import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.Iterator;
import java.util.ArrayList;
import sailpoint.object.QueryOptions;
import sailpoint.object.Filter;
import sailpoint.object.Identity;
import sailpoint.tools.Util;
import sailpoint.object.Attributes;
import java.util.Map;
import java.util.List;
import java.util.HashMap;
import sailpoint.object.Custom;
import sailpoint.object.QueryOptions;
import sailpoint.object.Filter;

import sailpoint.api.IncrementalObjectIterator;
public List getAllReportees(String identityName){

List allreportees=new ArrayList();

QueryOptions managerQO=new QueryOptions();

managerQO.addFilter(Filter.eq("manager.name", identityName));

managerQO.addFilter(Filter.eq("correlated", true));

managerQO.addFilter(Filter.ne("type", "Service"));

managerQO.addFilter(Filter.ne("inactive", true));



IncrementalObjectIterator<Identity> identityIterator=new IncrementalObjectIterator<Identity>(context, Identity.class, managerQO);

while(identityIterator.hasNext())

{

  Identity ident=(Identity)identityIterator.next();
  String userName=ident.getName();

  allreportees.add(userName);

  if(isManager(userName)){

    allreportees.addAll(getAllReportees(userName));

  }


}

Util.flushIterator(identityIterator);
return  allreportees;

}

public boolean isManager(String identityName){

boolean isManager=false;

QueryOptions managerQO=new QueryOptions();

managerQO.addFilter(Filter.eq("manager.name", identityName));

managerQO.addFilter(Filter.ne("name", identityName));


managerQO.addFilter(Filter.eq("correlated", true));

managerQO.addFilter(Filter.ne("type", "Service"));

managerQO.addFilter(Filter.ne("inactive", true));



IncrementalObjectIterator<Identity> identityIterator=new IncrementalObjectIterator<Identity>(context, Identity.class, managerQO);

if(identityIterator.hasNext())

{

  isManager=true;

}

return isManager;

}