Skip to Content.
Sympa Menu

grouper-users - RE: [grouper-users] RE: Grouper ldap loader

Subject: Grouper Users - Open Discussion List

List archive

RE: [grouper-users] RE: Grouper ldap loader


Chronological Thread 
  • From: Chris Hyzer <>
  • To: Gagné Sébastien <>, Rahul Doshi <>, "" <>
  • Subject: RE: [grouper-users] RE: Grouper ldap loader
  • Date: Tue, 14 Aug 2012 17:39:48 +0000
  • Accept-language: en-US

Sébastien,

 

I added your method as well to LoaderLdapElUtils, these two could probably be merged, though more than likely for now people can use these for good examples to base their implementation on based on their environment…

 

Thanks,

Chris

 

  /**

   * cache for if cn is person or group

   * cn -> is Person; true = person, false = group, store in memory for 3 hours

   */

  private static GrouperCache<String, Boolean> cacheIsPerson = new GrouperCache<String, Boolean>("loaderLdapElUtilsCacheIsPerson",

      10000, false, 60 * 3 * 60, 60 * 3 * 60, false);

 

  /**

   * cache for DN to group name

   * dn -> group ID store for 3 hours

   */

  private static GrouperCache<String, String> cacheDnToGroupName = new GrouperCache<String, String>("loaderLdapElUtilsCacheDnToGroupName",

      10000, false, 60 * 3 * 60, 60 * 3 * 60, false);

 

  /**

   * Logging infos

   */

  private static final Log LOG = GrouperUtil.getLog(LoaderLdapElUtils.class);

 

  /**

   * convert a user dn to a user CN, and a group dn to a group ID or Uuid

   * @param baseDn e.g. OU=People,DC=devsim,DC=umontreal,DC=ca

   * @param dn of group member

   * @param grouperBaseStem is the base stem where the groups go.  e.g. my:groups:

   * @param idOrIdentifier true for id (group id), false for identifier (group name)

   * @return CN for person, Uuid or Group name for a group

   */

  public static String convertAdMemberDnToSpecificValue(String dn, String baseDn, String grouperBaseStem, boolean idOrIdentifier) {

    if (LOG.isDebugEnabled()) {

      LOG.debug("Start conversion of DN '" + dn + "'");

    }

   

    if (StringUtils.isBlank(dn)) {

      return dn;

    }

   

    // see if the dn is in the space that is managed by grouper

    if (dn.indexOf(baseDn) < 0) {

      LOG.error("Group member isn't managed in Grouper : " + dn);

      return dn;  // this will cause an error since the subject cant be found...

    }

     

    // Get the CN/sAMAccountName from the DN

    String cn = LoaderLdapElUtils.convertDnToSpecificValue(dn);

 

    // see if it is a person or group

    Boolean isPerson = cacheIsPerson.get(cn);

 

    // ID is not cached, get the value from LDAP

    if (isPerson == null) {

 

      // Send a request to LDAP.  Note, in the future we can make this part of the original filter maybe

      List<String> results = LdapSession.list(String.class, "personLdap",

          "", null, "(&(sAMAccountName=" + cn +")(objectClass=person))","sAMAccountName");

     

      // If no results were found, it means it didn't pass through the (objectClass=person) filter

      isPerson = new Boolean(results.size() > 0);

     

      // Put the result in the cache

      cacheIsPerson.put(cn, isPerson);

     

      if (LOG.isDebugEnabled()) {

        LOG.debug("Object not found in cache, result : " + cn + " = " + (isPerson ? "user" : "group"));

      }

     

    } else {

      if (LOG.isDebugEnabled()) {

        LOG.debug("Object was found in cache, result : " + cn + " = " + (isPerson ? "user" : "group"));

      }

    }

 

    // if its a person return the cn (samaccountname)

    if (isPerson) {

      if (LOG.isDebugEnabled()) {

        LOG.debug("DN: '" + dn + "' converted to CN '" + cn + "'");

      }     

      return cn;

    }

   

    // convert the DN to a grouper group

    String groupName = convertDnToGroupName(dn, baseDn, grouperBaseStem);

    

    // see if the group exists

    Group group = GrouperDAOFactory.getFactory().getGroup().findByName(groupName, false, null) ;

    if (group == null) {

      if (LOG.isDebugEnabled()) {

        LOG.debug("Group doesnt exist, creating: '" + groupName +"'");

      }

 

      // If the group which is a member doesnt exist, create it

      //

      group = new GroupSave(GrouperSession.staticGrouperSession())

              .assignName(groupName)

              .assignCreateParentStemsIfNotExist(true)

              .save();

    }

 

 

    // return the ID of the group

    if (LOG.isDebugEnabled()) {

      LOG.debug("DN: '" + dn + "' converted to group: '" + group.getName() + "' and id: '" + group.getId() + "'");

    }

   

    return idOrIdentifier ? group.getId() : group.getName();

  }

 

  /**

   * convert a DN to a group name

   * @param dn

   * @param baseDn e.g. OU=People,DC=devsim,DC=umontreal,DC=ca

   * @param grouperBaseStem is the base stem where the groups go.  e.g. my:groups:

   * @return the subject identifier (group name)

   */

  public static String convertDnToGroupName(String dn, String baseDn, String grouperBaseStem) {

    // see it is already in the cache

    String cachedGroupID = cacheDnToGroupName.get(dn);

    if (cachedGroupID != null) {

      if (LOG.isDebugEnabled()) {

        LOG.debug("DN of groupe as in the cache cache, DN='" + dn + "' --> GroupID='" + cachedGroupID + "'");

      }

      return cachedGroupID;

    }

   

    // convert the dn of the grouper group to group name in grouper :

    // from : CN=dgtic-dev-deleg,OU=Groupes,OU=dgtic,OU=People,DC=devsim,DC=umontreal,DC=ca

    // to   : udem:dgtic:Groupes:dgtic-dev-deleg

   

    // take out the part of the name which is the baseDn and not part of grouper

    String partDn = dn.substring(0, dn.indexOf(baseDn));

    String[] splitDn = GrouperUtil.splitTrim(partDn, ",");

 

    // convert the rest of the bushy group part of dn to the group name

    StringBuilder groupName = new StringBuilder();

    for (String element : splitDn) {

      if (element.indexOf('=') >= 0) {  // Éviter les éléments vide (p. ex. s'il reste ',' à la fin)

        groupName.insert(0, element.substring(element.indexOf('=') + 1)).insert(0,':');

      }

    }

   

    // add the base stem if it is there

    if (!StringUtils.isBlank(grouperBaseStem)) {

      groupName.insert(0, grouperBaseStem);

    }

   

    cacheDnToGroupName.put(dn, groupName.toString());

    return groupName.toString();

  }

 

 

 

From: Gagné Sébastien [mailto:]
Sent: Monday, August 13, 2012 9:36 AM
To: Chris Hyzer; Rahul Doshi;
Subject: RE: [grouper-users] RE: Grouper ldap loader

 

Thanks, it’s nice to have this feature, but how would it handle these situations :

 

1-      Same group suffix for groups and users. I know this isn’t a standard structure, but it’s our case here , what I had to do here is a request to the LDAP server to check the object class :
List<String> results = LdapSession.list(String.class, "personLdap", "", null, "(&(sAMAccountName=" + cn +")(objectClass=person))","sAMAccountName");

2-  Groups in a bushy OU structure.
I see that you only use the prefix+CN, but what if there’s an OU between groupSuffix and the group’s CN ?
e.g. using
Suffix = “OU=People,DC=dev,DC=umontreal,DC=ca”
Prefix = “udem”
Convert from:
CN=it-dev-delegation,OU=Groups,OU=it,OU=People,DC=dev,DC=umontreal,DC=ca

To group name: udem:it:Groups:it-dev-delegation

For that case, I removed the suffix, split the remaining String on ‘,’ , added each part to the group name and then added the groupPrefix

 

I could send you our code if you need it

 

 

De : Chris Hyzer []
Envoyé : 13 août 2012 02:19
À : Rahul Do
shi; Gagné Sébastien;
Objet : RE: [grouper-users] RE: Grouper ldap loader

 

 

This is fixed in 2.1.2, and this concludes 2.1.2 scope, will start building, testing, etc

 

 

I put this method in LoaderLdapElUtils 


  /** 
   * convert from uid=someapp,ou=people,dc=myschool,dc=edu to someapp and allow groups 
   * @param dn full dn 
   * @param allowGroups if groups are allowed 
   * @param groupSuffix group suffix e.g. ,OU=Groups,DC=dev,DC=umontreal,DC=ca 
   * @param groupPrefix group prefix e.g. umontreal:adgroups: 
   * if null then no prefix 
   * @param createGroupIfNotThere if we should see if group exists and if not, create 
   * @param idOrIdentifier true for Id (uuid), false for Identifier of group (name) 
   * @return the subjectId or Identifier 
   */ 
  public static String convertDnToSpecificValueOrGroup(String dn, String groupPrefix, 
      String groupSuffix, boolean createGroupIfNotThere, boolean idOrIdentifier) { 

    //not sure why this would happen 
    if (dn == null) { 
      return dn; 
    } 

    boolean isGroup = dn.toLowerCase().endsWith(groupSuffix.toLowerCase()); 
     
    if (isGroup) { 
      String cn = dn.substring(0, dn.length() - groupSuffix.length()); 

      if (StringUtils.countMatches(cn, "=") != 1) { 
        throw new RuntimeException("Why is there not 1 equals in this CN??? '" + cn + "'"); 
      } 

      //this should be CN=groupName, convert to groupName 
      cn = GrouperUtil.prefixOrSuffix(cn, "=", false); 

      String groupName = StringUtils.isBlank(groupPrefix) ? cn : (groupPrefix + cn); 
       
      Group group = GrouperDAOFactory.getFactory().getGroup().findByName(groupName, 
          false, null); 

      if (createGroupIfNotThere) { 
        if (group == null) { 

          group = new GroupSave(GrouperSession.staticGrouperSession()) 
              .assignName(groupName).assignCreateParentStemsIfNotExist(true).save(); 
        } 
      } 

      if (group == null) { 
         
        LOG.error("Why is group null??? " + groupName); 
        return null; 
      } 
       
      return idOrIdentifier ? group.getId() : group.getName(); 

    } 
    //not a group 
    return LoaderLdapElUtils.convertDnToSpecificValue(dn); 
  } 

 

 

Note: GrouperUtilElSafe (exposed as grouperUtil in EL) new has  

  public static String toUpperCase(String input) { 

and 

  public static String toLowerCase(String input) { 

if getting the wrong thing from LDAP 

 


From: Rahul Doshi []
Sent: Monday, July 30, 2012 9:25 AM
To: Gagné Sébastien; Chris Hyzer;

Subject: Re: [grouper-users] RE: Grouper ldap loader

Yes, I ran into same issues but was able to get it to work by following suggestions in the link.  Below is the code 

 

 

  public static String convertDnToSpecificValue(String dn) {

   

    //e.g. ,OU=Groups,DC=dev,DC=umontreal,DC=ca

    String adGroupSuffix = GrouperLoaderConfig.getPropertyString("cmu.group.suffix", true);

   

    //not sure why this would happen

    if (dn == null) {

      return dn;

    }

   

    if (dn.toLowerCase().endsWith(adGroupSuffix.toLowerCase())) {

      String cn = dn.substring(0, dn.length()-adGroupSuffix.length());

     

      if (StringUtils.countMatches(cn, "=") != 1) {

        throw new RuntimeException("Why is there not 1 equals in this CN??? '" + cn + "'");

      }

     

      //this should be CN=groupName, convert to groupName

      cn = GrouperUtil.prefixOrSuffix(cn, "=", false);

     

      //e.g. umontreal.grouper.ad.group.prefix = umontreal:adgroups:

      String grouperGroupPrefix = GrouperLoaderConfig.getPropertyString("cmu.group.prefix", true);

      

      String groupName = grouperGroupPrefix + cn;

      

      Group group = GrouperDAOFactory.getFactory().getGroup().findByName(groupName, false, null) ;

      

      if (group != null) {

   

  return group.getId();

      }

      else {

   

  group = new GroupSave(GrouperSession.staticGrouperSession()).assignName(groupName).assignCreateParentStemsIfNotExist(true).save();

   

  return group.getId();

      }

 

     }

    //not a group

    return LoaderLdapElUtils.convertDnToSpecificValue(dn);

  }

}

 

Thanks,

Rahul

 

From: Gagné Sébastien <>
Date: Monday, July 30, 2012 9:15 AM
To: Chris Hyzer <>, Rahul Doshi <>, "" <>
Subject: RE: [grouper-users] RE: Grouper ldap loader

 

We had a similar problem (it’s me in the link) : when creating “somestem:admins” it tries to add the group member “someotherstem:admins” but if it doesn’t exist in Grouper it won’t be added because it doesn’t find it. We had to add a “create missing groups” feature to our “translate AD CN in Group’s member to Grouper Group IDs”

 

You also have to be careful with what you are searching (Ids or Identifiers), because in source g:gsa (group adapter) Group ID are the generated UUIDs (e.g. 30bb5405f55942129948b4ee924331ea) while Group identifier are, I believe, the group name (e.g. somestem:admins)

 

I haven’t tried the loader ldap with a flat structure, so there might be a problem translating “member=cn=someotherstem:admins, ou=group, dc= example, dc = org” to the proper group id “baseStem:someotherstem:admins”

 

 

De : [] De la part de Chris Hyzer
Envoyé : 26 juillet 2012 16:23
À : Rahul Doshi;
Objet : [grouper-users] RE: Grouper ldap loader

 

Actually, is this an LDAP_GROUP_LIST job, and is cn=someotherstem:admins, ou=group, dc= example, dc = org one of the groups that is returns from the ldap filter (as well as a member of a group).  If so, then with the link below, you can do what you want to do.  If that member which is a group is not managed by the loader, so we can do this with a tweak to grouper or an EL tweak.  Let me know

 

Thanks,

Chris

 

From: Chris Hyzer
Sent: Thursday, July 26, 2012 4:16 PM
To: 'Rahul Doshi';
Subject: RE: Grouper ldap loader

 

I hadn’t really considered that case when creating the loader, but I think it can be done fairly easily with some EL and a java class.  It is very similar to this email, except that the group will be created perhaps in EL…

 

https://lists.internet2.edu/sympa/arc/grouper-users/2012-05/msg00026.html

 

Want me to try to send you an example?

 

Thanks,

Chris

 

 

From: [] On Behalf Of Rahul Doshi
Sent: Thursday, July 26, 2012 4:03 PM
To:
Subject: [grouper-users] Grouper ldap loader

 

Hello,

 

I am trying to use grouper loader to load all the existing groups from our ldap environment.  It seems to load the groups fine except that it is ignoring the nested group membership.  For hypothetical group below if I run the loader job,  I only see somstem:admins group created in grouper with member xyz.  What I would have expected to see is two groups somestem:admins and someotherstem:admins created in grouper and someotherstem:admins also be the member of some stem:admins.  Is there something that I am missing in my configuration? 

 

Groupname

cn=somestem:admins, ou=group, dc=example, dc=org

member=uid=xyz, ou=person,dc=example,dc=org

member=cn=someotherstem:admins, ou=group, dc= example, dc = org

 

Thanks,

Rahul




Archive powered by MHonArc 2.6.16.

Top of Page