Repository: ranger
Updated Branches:
  refs/heads/master 6890976ee -> f4019d11b


RANGER-1735: Support representing nested group memberships in Ranger Admin


Project: http://git-wip-us.apache.org/repos/asf/ranger/repo
Commit: http://git-wip-us.apache.org/repos/asf/ranger/commit/f4019d11
Tree: http://git-wip-us.apache.org/repos/asf/ranger/tree/f4019d11
Diff: http://git-wip-us.apache.org/repos/asf/ranger/diff/f4019d11

Branch: refs/heads/master
Commit: f4019d11ba20fb6d61171876e4f14ea428028887
Parents: 6890976
Author: Sailaja Polavarapu <spolavar...@hortonworks.com>
Authored: Thu Sep 7 14:21:27 2017 -0700
Committer: Sailaja Polavarapu <spolavar...@hortonworks.com>
Committed: Thu Sep 7 14:21:27 2017 -0700

----------------------------------------------------------------------
 .../process/LdapDeltaUserGroupBuilder.java      | 309 +++++++++++++-----
 .../process/LdapUserGroupBuilder.java           | 322 +++++++++++++++----
 .../config/UserGroupSyncConfig.java             |  22 ++
 .../ranger/usergroupsync/TestLdapUserGroup.java |  11 +-
 ugsync/src/test/resources/ADSchema.ldif         |   2 +
 .../src/test/resources/ranger-ugsync-site.xml   |   5 +
 6 files changed, 524 insertions(+), 147 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ranger/blob/f4019d11/ugsync/src/main/java/org/apache/ranger/ldapusersync/process/LdapDeltaUserGroupBuilder.java
----------------------------------------------------------------------
diff --git 
a/ugsync/src/main/java/org/apache/ranger/ldapusersync/process/LdapDeltaUserGroupBuilder.java
 
b/ugsync/src/main/java/org/apache/ranger/ldapusersync/process/LdapDeltaUserGroupBuilder.java
index d27a217..394bde2 100644
--- 
a/ugsync/src/main/java/org/apache/ranger/ldapusersync/process/LdapDeltaUserGroupBuilder.java
+++ 
b/ugsync/src/main/java/org/apache/ranger/ldapusersync/process/LdapDeltaUserGroupBuilder.java
@@ -49,6 +49,8 @@ import javax.naming.ldap.PagedResultsResponseControl;
 import javax.naming.ldap.StartTlsRequest;
 import javax.naming.ldap.StartTlsResponse;
 
+import org.apache.commons.collections.BidiMap;
+import org.apache.commons.collections.bidimap.DualHashBidiMap;
 import org.apache.log4j.Logger;
 import org.apache.ranger.unixusersync.config.UserGroupSyncConfig;
 import org.apache.ranger.usergroupsync.AbstractUserGroupSource;
@@ -98,6 +100,7 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
   private SearchControls groupSearchControls;
   private String groupMemberAttributeName;
   private String groupNameAttribute;
+       private int groupHierarchyLevels;
 
        private LdapContext ldapContext;
        StartTlsResponse tls;
@@ -110,21 +113,22 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
   private boolean  groupUserMapSyncEnabled = false;
 
   //private Map<String, UserInfo> userGroupMap;
-  
-  private Table<String, String, String> groupUserTable; 
+
+  private Table<String, String, String> groupUserTable;
   private Map<String, String> userNameMap;
+       private BidiMap groupNameMap;
 
        public static void main(String[] args) throws Throwable {
                LdapDeltaUserGroupBuilder  ugBuilder = new 
LdapDeltaUserGroupBuilder();
                ugBuilder.init();
        }
-       
+
        public LdapDeltaUserGroupBuilder() {
                super();
                LOG.info("LdapDeltaUserGroupBuilder created");
-               
+
                String userNameCaseConversion = 
config.getUserNameCaseConversion();
-               
+
                if 
(UserGroupSyncConfig.UGSYNC_NONE_CASE_CONVERSION_VALUE.equalsIgnoreCase(userNameCaseConversion))
 {
                    userNameCaseConversionFlag = false;
                }
@@ -132,9 +136,9 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
                    userNameCaseConversionFlag = true;
                    userNameLowerCaseFlag = 
UserGroupSyncConfig.UGSYNC_LOWER_CASE_CONVERSION_VALUE.equalsIgnoreCase(userNameCaseConversion);
                }
-               
+
                String groupNameCaseConversion = 
config.getGroupNameCaseConversion();
-               
+
                if 
(UserGroupSyncConfig.UGSYNC_NONE_CASE_CONVERSION_VALUE.equalsIgnoreCase(groupNameCaseConversion))
 {
                    groupNameCaseConversionFlag = false;
                }
@@ -145,7 +149,7 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
        }
 
        @Override
-       public void init() throws Throwable{            
+       public void init() throws Throwable{
                deltaSyncUserTime = 0;
                deltaSyncGroupTime = 0;
                DateFormat dateFormat = new SimpleDateFormat("yyyyMMddhhmmss");
@@ -154,7 +158,7 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
                userNameMap = new HashMap<String, String>();
                setConfig();
        }
-       
+
        private void createLdapContext() throws Throwable {
                Properties env = new Properties();
                env.put(Context.INITIAL_CONTEXT_FACTORY,
@@ -182,7 +186,7 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
                ldapContext.addToEnvironment(Context.SECURITY_AUTHENTICATION, 
ldapAuthenticationMechanism);
                ldapContext.addToEnvironment(Context.REFERRAL, ldapReferral);
        }
-       
+
        private void setConfig() throws Throwable {
                LOG.info("LdapDeltaUserGroupBuilder initialization started");
 
@@ -196,14 +200,14 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
     ldapAuthenticationMechanism = config.getLdapAuthenticationMechanism();
     ldapReferral = config.getContextReferral();
                searchBase = config.getSearchBase();
-               
+
                userSearchBase = config.getUserSearchBase().split(";");
                userSearchScope = config.getUserSearchScope();
                userObjectClass = config.getUserObjectClass();
                userSearchFilter = config.getUserSearchFilter();
-               
+
                userNameAttribute = config.getUserNameAttribute();
-               
+
                Set<String> userSearchAttributes = new HashSet<String>();
                userSearchAttributes.add(userNameAttribute);
                // For Group based search, user's group name attribute should 
not be added to the user search attributes
@@ -229,6 +233,7 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
     groupSearchFilter = config.getGroupSearchFilter();
     groupMemberAttributeName =  config.getUserGroupMemberAttributeName();
     groupNameAttribute = config.getGroupNameAttribute();
+               groupHierarchyLevels = config.getGroupHierarchyLevels();
 
     extendedGroupSearchFilter =  "(&"  + extendedGroupSearchFilter + "(|(" + 
groupMemberAttributeName + "={0})(" + groupMemberAttributeName + "={1})))";
     groupUserMapSyncEnabled = config.isGroupUserMapSyncEnabled();
@@ -279,7 +284,7 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
                }
 
        }
-       
+
        private void closeLdapContext() throws Throwable {
                if (tls != null) {
                        tls.close();
@@ -288,7 +293,7 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
                        ldapContext.close();
                }
        }
-       
+
        @Override
        public boolean isChanged() {
                // we do not want to get the full ldap dit and check whether 
anything has changed
@@ -299,27 +304,39 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
        public void updateSink(UserGroupSink sink) throws Throwable {
                LOG.info("LdapDeltaUserGroupBuilder updateSink started");
                //userGroupMap = new HashMap<String, UserInfo>();
-               groupUserTable = HashBasedTable.create(); 
-               if (!groupSearchFirstEnabled) {
+               groupUserTable = HashBasedTable.create();
+        groupNameMap = new DualHashBidiMap();
+        if (!groupSearchFirstEnabled) {
                        LOG.info("Performing user search first");
                        getUsers(sink);
                        if (groupSearchEnabled) {
                                getGroups(sink);
                        }
                        //LOG.debug("Total No. of users saved = " + 
groupUserTable.columnKeySet().size());
-                       
+
                } else {
                        LOG.info("Performing Group search first");
                        getGroups(sink);
                        if (userSearchEnabled) {
                                LOG.info("User search is enabled and hence 
computing user membership.");
                                getUsers(sink);
-                       } 
+                       }
                }
                if (groupUserTable.isEmpty()) {
                        //System.out.println("groupUserTable is empty!!");
                        return;
                }
+        
+               if (groupHierarchyLevels > 0) {
+                       LOG.info("Going through group hierarchy for nested 
group evaluation");
+            Set<String> groupFullNames = groupNameMap.keySet();
+                       for(String group : groupFullNames) {
+                               Set<String> nextLevelGroups = 
groupUserTable.column(group).keySet();
+                               goUpGroupHierarchy(nextLevelGroups, 
groupHierarchyLevels-1, groupNameMap.get(group).toString());
+                       }
+                       LOG.info("Completed group hierarchy computation");
+               }
+
                Iterator<String> groupUserTableIterator = 
groupUserTable.rowKeySet().iterator();
                while (groupUserTableIterator.hasNext()) {
                        String groupName = groupUserTableIterator.next();
@@ -327,12 +344,12 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
                        Map<String,String> groupUsersMap =  
groupUserTable.row(groupName);
                        Set<String> userSet = new HashSet<String>();
                        for(Map.Entry<String, String> entry : 
groupUsersMap.entrySet()){
-                               //String transformUserName = 
userNameTransform(entry.getKey()); 
+                               //String transformUserName = 
userNameTransform(entry.getKey());
                         userSet.add(entry.getValue());
                    }
                        List<String> userList = new ArrayList<>(userSet);
                        String transformGroupName = 
groupNameTransform(groupName);
-                       try { 
+                       try {
                                sink.addOrUpdateGroup(transformGroupName, 
userList);
                        } catch (Throwable t) {
                                LOG.error("sink.addOrUpdateGroup failed with 
exception: " + t.getMessage()
@@ -341,7 +358,7 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
                        }
                }
        }
-       
+
        private void getUsers(UserGroupSink sink) throws Throwable {
                NamingEnumeration<SearchResult> userSearchResultEnum = null;
                NamingEnumeration<SearchResult> groupSearchResultEnum = null;
@@ -355,7 +372,7 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
                        }
                        DateFormat dateFormat = new 
SimpleDateFormat("yyyyMMddhhmmss");
                        extendedUserSearchFilter = "(objectclass=" + 
userObjectClass + ")(|(uSNChanged>=" + deltaSyncUserTime + 
")(modifyTimestamp>=" + deltaSyncUserTimeStamp + "Z))";
-                       
+
                        if (userSearchFilter != null && 
!userSearchFilter.trim().isEmpty()) {
                                String customFilter = userSearchFilter.trim();
                                if (!customFilter.startsWith("(")) {
@@ -380,7 +397,7 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
                                        userSearchResultEnum = ldapContext
                                                        
.search(userSearchBase[ou], extendedUserSearchFilter,
                                                                        
userSearchControls);
-                                       
+
                                        while (userSearchResultEnum.hasMore()) {
                                                // searchResults contains all 
the user entries
                                                final SearchResult userEntry = 
userSearchResultEnum.next();
@@ -410,7 +427,7 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
                                                        }
                                                        continue;
                                                }
-                                               
+
                                                String userFullName = 
(userEntry.getNameInNamespace()).toLowerCase();
                                                String userName = (String) 
userNameAttr.get();
 
@@ -421,7 +438,7 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
                                                        }
                                                        continue;
                                                }
-                                               
+
                                                Attribute timeStampAttr  = 
attributes.get("uSNChanged");
                                                if (timeStampAttr != null) {
                                                        String uSNChangedVal = 
(String) timeStampAttr.get();
@@ -434,7 +451,7 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
                                                        timeStampAttr = 
attributes.get("modifytimestamp");
                                                        if (timeStampAttr != 
null) {
                                                                String 
timeStampVal = (String) timeStampAttr.get();
-                                                               Date parseDate 
= dateFormat.parse(timeStampVal);                                               
 
+                                                               Date parseDate 
= dateFormat.parse(timeStampVal);
                                                                long 
currentDeltaSyncTime = parseDate.getTime();
                                                                
LOG.info("timeStampVal = " + timeStampVal + "and currentDeltaSyncTime = " + 
currentDeltaSyncTime);
                                                                if 
(currentDeltaSyncTime > highestdeltaSyncUserTime) {
@@ -475,7 +492,7 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
                                                        List<String> groupList 
= new ArrayList<String>(groups);
                                                        try {
                                                                
sink.addOrUpdateUser(transformUserName, groupList);
-                                                               
+
                                                        } catch (Throwable t) {
                                                                
LOG.error("sink.addOrUpdateUserGroups failed with exception: " + t.getMessage()
                                                                + ", for user: 
" + transformUserName + " and groups: " + groupList);
@@ -575,9 +592,11 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
                        closeLdapContext();
                }
        }
-       
+
        private void getGroups(UserGroupSink sink) throws Throwable {
                NamingEnumeration<SearchResult> groupSearchResultEnum = null;
+        DateFormat dateFormat = new SimpleDateFormat("yyyyMMddhhmmss");
+        long highestdeltaSyncGroupTime = deltaSyncGroupTime;
                try {
                        createLdapContext();
                        int total;
@@ -594,12 +613,10 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
                                }
                                extendedGroupSearchFilter = 
extendedGroupSearchFilter + customFilter;
                        }
-                       
-                       DateFormat dateFormat = new 
SimpleDateFormat("yyyyMMddhhmmss");
+
                        extendedAllGroupsSearchFilter = "(&"  + 
extendedGroupSearchFilter + "(|(uSNChanged>=" + deltaSyncGroupTime + 
")(modifyTimestamp>=" + deltaSyncGroupTimeStamp + "Z)))";
-                       
+
                        LOG.info("extendedAllGroupsSearchFilter = " + 
extendedAllGroupsSearchFilter);
-                       long highestdeltaSyncGroupTime = deltaSyncGroupTime;
                        for (int ou=0; ou<groupSearchBase.length; ou++) {
                                byte[] cookie = null;
                                int counter = 0;
@@ -646,7 +663,7 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
                                                                timeStampAttr = 
groupEntry.getAttributes().get("modifytimestamp");
                                                                if 
(timeStampAttr != null) {
                                                                        String 
timeStampVal = (String) timeStampAttr.get();
-                                                                       Date 
parseDate = dateFormat.parse(timeStampVal);                                     
           
+                                                                       Date 
parseDate = dateFormat.parse(timeStampVal);
                                                                        long 
currentDeltaSyncTime = parseDate.getTime();
                                                                        
LOG.info("timeStampVal = " + timeStampVal + "and currentDeltaSyncTime = " + 
currentDeltaSyncTime);
                                                                        if 
(currentDeltaSyncTime > highestdeltaSyncGroupTime) {
@@ -661,7 +678,7 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
                                                                LOG.info("No 
members available for " + gName);
                                                                continue;
                                                        }
-                                                       
+
                                                        NamingEnumeration<?> 
userEnum = groupMemberAttr.getAll();
                                                        while 
(userEnum.hasMore()) {
                                                                String 
originalUserFullName = (String) userEnum.next();
@@ -687,6 +704,7 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
                                                                } else {
                                                                        
groupUserTable.put(gName, originalUserFullName, originalUserFullName);
                                                                }
+                                
groupNameMap.put(groupEntry.getNameInNamespace().toLowerCase(), gName);
                                                        }
                                                        LOG.info("No. of 
members in the group " + gName + " = " + userCount);
                                                }
@@ -719,17 +737,11 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
                                        
LOG.info("LdapDeltaUserGroupBuilder.getGroups() completed with group count: "
                                                        + counter);
                                } catch (Exception t) {
-                                       
LOG.error("LdapDeltaUserGroupBuilder.getGroups() failed with exception: " + t); 
+                                       
LOG.error("LdapDeltaUserGroupBuilder.getGroups() failed with exception: " + t);
                                        
LOG.info("LdapDeltaUserGroupBuilder.getGroups() group count: "
                                                        + counter);
                                }
                        }
-                       if (deltaSyncGroupTime < highestdeltaSyncGroupTime) {
-                               // Incrementing highestdeltaSyncGroupTime (for 
AD) in order to avoid search record repetition for next sync cycle.
-                               deltaSyncGroupTime = 
highestdeltaSyncGroupTime+1;
-                               // Incrementing the highest timestamp value 
(for OpenLdap) with 1min in order to avoid search record repetition for next 
sync cycle.
-                               deltaSyncGroupTimeStamp = dateFormat.format(new 
Date(highestdeltaSyncGroupTime + 60000l)); 
-                       }
 
                } finally {
                        if (groupSearchResultEnum != null) {
@@ -737,9 +749,22 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
                        }
                        closeLdapContext();
                }
+
+        if (groupHierarchyLevels > 0) {
+            if (deltaSyncGroupTime > 0) {
+                goUpGroupHierarchyLdap(groupNameMap.keySet(), 
groupHierarchyLevels-1);
+            }
+        }
+
+        if (deltaSyncGroupTime < highestdeltaSyncGroupTime) {
+            // Incrementing highestdeltaSyncGroupTime (for AD) in order to 
avoid search record repetition for next sync cycle.
+            deltaSyncGroupTime = highestdeltaSyncGroupTime+1;
+            // Incrementing the highest timestamp value (for OpenLdap) with 
1min in order to avoid search record repetition for next sync cycle.
+            deltaSyncGroupTimeStamp = dateFormat.format(new 
Date(highestdeltaSyncGroupTime + 60000l));
+        }
        }
 
-       
+
        private static String getShortGroupName(String longGroupName) throws 
InvalidNameException {
                if (longGroupName == null) {
                        return null;
@@ -755,7 +780,7 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
                LOG.info("longGroupName: " + longGroupName + ", groupName: " + 
groupName);
                return groupName;
        }
-       
+
        private static String getShortUserName(String longUserName) throws 
InvalidNameException {
                if (longUserName == null) {
                        return null;
@@ -771,7 +796,7 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
                LOG.info("longUserName: " + longUserName + ", userName: " + 
userName);
                return userName;
        }
-       
+
        private String userNameTransform(String userName) {
                //String userNameTransform = userName;
                if (userNameCaseConversionFlag) {
@@ -789,7 +814,7 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
 
                return userName;
        }
-       
+
        private String groupNameTransform(String groupName) {
                //String userNameTransform = userName;
                if (groupNameCaseConversionFlag) {
@@ -807,37 +832,167 @@ public class LdapDeltaUserGroupBuilder extends 
AbstractUserGroupSource {
 
                return groupName;
        }
-       
-}
 
-/*class UserInfo {
-       private String userName;
-       private String userFullName;
-       private Set<String> groupList;
-       
-       public UserInfo(String userName, String userFullName) {
-               this.userName = userName;
-               this.userFullName = userFullName;
-               this.groupList = new HashSet<String>();
-       }
-       
-       public void updateUserName(String userName) {
-               this.userName = userName;
-       }
-       
-       public String getUserName() {
-               return userName;
-       }
-       public String getUserFullName() {
-               return userFullName;
-       }
-       public void addGroups(Set<String> groups) {
-               groupList.addAll(groups);
-       }
-       public void addGroup(String group) {
-               groupList.add(group);
+       private void goUpGroupHierarchy(Set<String> groups, int 
groupHierarchyLevels, String groupSName) throws InvalidNameException {
+               if (groupHierarchyLevels <= 0 || groups.isEmpty()) {
+                       return;
+               }
+        LOG.info("nextLevelGroups = " + groups + " for group = " + groupSName);
+               Set<String> nextLevelGroups;
+
+               for (String group : groups) {
+            String groupFullName = groupNameMap.getKey(group).toString();
+
+                       // Add all members of sub group to the parent groups if 
the member is not a group in turn
+                       Set<String> allMembers = 
groupUserTable.row(groupSName).keySet();
+                       for(String member : allMembers) {
+                               String memberName = getShortGroupName(member);
+                               if (!groupUserTable.containsRow(memberName)) { 
//Check if the member of a group is in turn a group
+                                       LOG.info("Adding " + member + " to " + 
group);
+                                       String userSName = 
groupUserTable.get(groupSName, member);
+                                       LOG.info("Short name of " + member + " 
= " + userSName);
+                                       if (userSName != null) {
+                                               groupUserTable.put(group, 
member, userSName); //Add users from the nested group to parent group
+                                       }
+                               }
+                       }
+                       nextLevelGroups = 
groupUserTable.column(groupFullName).keySet();
+                       goUpGroupHierarchy(nextLevelGroups, 
groupHierarchyLevels - 1, group);
+               }
        }
-       public List<String> getGroups() {
-               return (new ArrayList<String>(groupList));
+
+       private void goUpGroupHierarchyLdap(Set<String> groupDNs, int 
groupHierarchyLevels) throws Throwable {
+               if (groupHierarchyLevels <= 0 || groupDNs.isEmpty()) {
+                       return;
+               }
+               Set<String> nextLevelGroups = new HashSet<String>();
+
+               NamingEnumeration<SearchResult> groupSearchResultEnum = null;
+               try {
+                       createLdapContext();
+                       int total;
+                       // Activate paged results
+                       if (pagedResultsEnabled)   {
+                               ldapContext.setRequestControls(new Control[]{
+                                               new 
PagedResultsControl(pagedResultsSize, Control.NONCRITICAL) });
+                       }
+                       String groupFilter = "(&(objectclass=" + 
groupObjectClass + ")";
+                       if (groupSearchFilter != null && 
!groupSearchFilter.trim().isEmpty()) {
+                               String customFilter = groupSearchFilter.trim();
+                               if (!customFilter.startsWith("(")) {
+                                       customFilter = "(" + customFilter + ")";
+                               }
+                               groupFilter += customFilter + "(|";
+                       }
+                       StringBuilder filter = new StringBuilder();
+
+                       for (String groupDN : groupDNs) {
+                               
filter.append("(").append(groupMemberAttributeName).append("=")
+                                               .append(groupDN).append(")");
+                       }
+                       filter.append("))");
+                       groupFilter += filter;
+
+                       LOG.info("extendedAllGroupsSearchFilter = " + 
groupFilter);
+                       for (int ou=0; ou<groupSearchBase.length; ou++) {
+                               byte[] cookie = null;
+                               int counter = 0;
+                               try {
+                                       do {
+                                               groupSearchResultEnum = 
ldapContext
+                                                               
.search(groupSearchBase[ou], groupFilter,
+                                                                               
groupSearchControls);
+                                               while 
(groupSearchResultEnum.hasMore()) {
+                                                       final SearchResult 
groupEntry = groupSearchResultEnum.next();
+                                                       if (groupEntry == null) 
{
+                                                               if 
(LOG.isInfoEnabled())  {
+                                                                       
LOG.info("groupEntry null, skipping sync for the entry");
+                                                               }
+                                                               continue;
+                                                       }
+                                                       counter++;
+                                                       Attribute groupNameAttr 
= groupEntry.getAttributes().get(groupNameAttribute);
+                                                       if (groupNameAttr == 
null) {
+                                                               if 
(LOG.isInfoEnabled())  {
+                                                                       
LOG.info(groupNameAttribute + " empty for entry " + 
groupEntry.getNameInNamespace() +
+                                                                               
        ", skipping sync");
+                                                               }
+                                                               continue;
+                                                       }
+                                                       
nextLevelGroups.add(groupEntry.getNameInNamespace());
+                                                       String gName = (String) 
groupNameAttr.get();
+
+                                                       Attribute 
groupMemberAttr = groupEntry.getAttributes().get(groupMemberAttributeName);
+                                                       int userCount = 0;
+                                                       if (groupMemberAttr == 
null || groupMemberAttr.size() <= 0) {
+                                                               LOG.info("No 
members available for " + gName);
+                                                               continue;
+                                                       }
+
+                                                       NamingEnumeration<?> 
userEnum = groupMemberAttr.getAll();
+                                                       while 
(userEnum.hasMore()) {
+                                                               String 
originalUserFullName = (String) userEnum.next();
+                                                               if 
(originalUserFullName == null || originalUserFullName.trim().isEmpty()) {
+                                                                       
continue;
+                                                               }
+                                                               userCount++;
+                                                               
originalUserFullName = originalUserFullName.toLowerCase();
+                                if (userNameMap.get(originalUserFullName) != 
null) {
+                                    groupUserTable.put(gName, 
originalUserFullName, userNameMap.get(originalUserFullName));
+                                } else {
+                                    groupUserTable.put(gName, 
originalUserFullName, originalUserFullName);
+                                }
+
+                                                       }
+                                                       LOG.info("No. of 
members in the group " + gName + " = " + userCount);
+                                               }
+                                               // Examine the paged results 
control response
+                                               Control[] controls = 
ldapContext.getResponseControls();
+                                               if (controls != null) {
+                                                       for (int i = 0; i < 
controls.length; i++) {
+                                                               if (controls[i] 
instanceof PagedResultsResponseControl) {
+                                                                       
PagedResultsResponseControl prrc =
+                                                                               
        (PagedResultsResponseControl)controls[i];
+                                                                       total = 
prrc.getResultSize();
+                                                                       if 
(total != 0) {
+                                                                               
LOG.debug("END-OF-PAGE total : " + total);
+                                                                       } else {
+                                                                               
LOG.debug("END-OF-PAGE total : unknown");
+                                                                       }
+                                                                       cookie 
= prrc.getCookie();
+                                                               }
+                                                       }
+                                               } else {
+                                                       LOG.debug("No controls 
were sent from the server");
+                                               }
+                                               // Re-activate paged results
+                                               if (pagedResultsEnabled)   {
+                                                       
ldapContext.setRequestControls(new Control[]{
+                                                                       new 
PagedResultsControl(pagedResultsSize, cookie, Control.CRITICAL) });
+                                               }
+                                       } while (cookie != null);
+                                       
LOG.info("LdapDeltaUserGroupBuilder.goUpGroupHierarchyLdap() completed with 
group count: "
+                                                       + counter);
+                               } catch (RuntimeException re) {
+                                       
LOG.error("LdapDeltaUserGroupBuilder.goUpGroupHierarchyLdap() failed with 
runtime exception: ", re);
+                                       throw re;
+                               } catch (Exception t) {
+                                       
LOG.error("LdapDeltaUserGroupBuilder.goUpGroupHierarchyLdap() failed with 
exception: ", t);
+                                       
LOG.info("LdapDeltaUserGroupBuilder.goUpGroupHierarchyLdap() group count: "
+                                                       + counter);
+                               }
+                       }
+
+               } catch (RuntimeException re) {
+                       
LOG.error("LdapDeltaUserGroupBuilder.goUpGroupHierarchyLdap() failed with 
exception: ", re);
+                       throw re;
+               } finally {
+                       if (groupSearchResultEnum != null) {
+                               groupSearchResultEnum.close();
+                       }
+                       closeLdapContext();
+               }
+               goUpGroupHierarchyLdap(nextLevelGroups, groupHierarchyLevels-1);
        }
-}*/
+}
+

http://git-wip-us.apache.org/repos/asf/ranger/blob/f4019d11/ugsync/src/main/java/org/apache/ranger/ldapusersync/process/LdapUserGroupBuilder.java
----------------------------------------------------------------------
diff --git 
a/ugsync/src/main/java/org/apache/ranger/ldapusersync/process/LdapUserGroupBuilder.java
 
b/ugsync/src/main/java/org/apache/ranger/ldapusersync/process/LdapUserGroupBuilder.java
index e62da5b..8dc147c 100644
--- 
a/ugsync/src/main/java/org/apache/ranger/ldapusersync/process/LdapUserGroupBuilder.java
+++ 
b/ugsync/src/main/java/org/apache/ranger/ldapusersync/process/LdapUserGroupBuilder.java
@@ -87,6 +87,7 @@ public class LdapUserGroupBuilder extends 
AbstractUserGroupSource {
        private SearchControls groupSearchControls;
        private String groupMemberAttributeName;
        private String groupNameAttribute;
+    private int groupHierarchyLevels;
 
        private LdapContext ldapContext;
        private StartTlsResponse tls;
@@ -99,6 +100,7 @@ public class LdapUserGroupBuilder extends 
AbstractUserGroupSource {
        private boolean groupUserMapSyncEnabled;
 
        private Map<String, UserInfo> userGroupMap;
+    //private Set<String> firstGroupDNs;
 
        public static void main(String[] args) throws Throwable {
                LdapUserGroupBuilder  ugBuilder = new LdapUserGroupBuilder();
@@ -131,7 +133,7 @@ public class LdapUserGroupBuilder extends 
AbstractUserGroupSource {
        }
 
        @Override
-       public void init() throws Throwable{            
+       public void init() throws Throwable{
                setConfig();
        }
 
@@ -205,7 +207,7 @@ public class LdapUserGroupBuilder extends 
AbstractUserGroupSource {
                userSearchControls = new SearchControls();
                userSearchControls.setSearchScope(userSearchScope);
                
userSearchControls.setReturningAttributes(userSearchAttributes.toArray(
-                               new String[userSearchAttributes.size()]));
+                new String[userSearchAttributes.size()]));
 
                pagedResultsEnabled =   config.isPagedResultsEnabled();
                pagedResultsSize =   config.getPagedResultsSize();
@@ -216,6 +218,7 @@ public class LdapUserGroupBuilder extends 
AbstractUserGroupSource {
                groupSearchFilter = config.getGroupSearchFilter();
                groupMemberAttributeName =  
config.getUserGroupMemberAttributeName();
                groupNameAttribute = config.getGroupNameAttribute();
+        groupHierarchyLevels = config.getGroupHierarchyLevels();
 
                extendedGroupSearchFilter = "(objectclass=" + groupObjectClass 
+ ")";
                if (groupSearchFilter != null && 
!groupSearchFilter.trim().isEmpty()) {
@@ -296,20 +299,30 @@ public class LdapUserGroupBuilder extends 
AbstractUserGroupSource {
        public void updateSink(UserGroupSink sink) throws Throwable {
                LOG.info("LDAPUserGroupBuilder updateSink started");
                userGroupMap = new HashMap<String, UserInfo>();
+
                if (!groupSearchFirstEnabled) {
                        LOG.info("Performing user search first");
                        getUsers(sink);
-
                        LOG.debug("Total No. of users saved = " + 
userGroupMap.size());
-                       //Iterator<UserInfo> userInfoIterator = userGroupMap.
+                       if (!groupSearchEnabled && groupHierarchyLevels > 0) {
+                               getRootDN();
+                       }
+            //Iterator<UserInfo> userInfoIterator = userGroupMap.
                        for (UserInfo userInfo : userGroupMap.values()) {
                                String userName = userInfo.getUserName();
                                if (groupSearchEnabled) {
                                        // Perform group search
                                        LOG.info("groupSearch is enabled, would 
search for groups and compute memberships");
+                    //firstGroupDNs = new HashSet<String>();
                                        getGroups(sink, userInfo);
                                }
+                if (groupHierarchyLevels > 0) {
+                    LOG.debug("Going through group hierarchy for nested group 
evaluation");
+                    goUpGroupHierarchyLdap(userInfo.getGroupDNs(), 
groupHierarchyLevels - 1, userInfo);
+                    LOG.debug("Completed group hierarchy computation");
+                }
                                List<String> groupList = userInfo.getGroups();
+                LOG.debug("updateSink(): group list for " + userName + " = " + 
groupList);
                                if (userNameCaseConversionFlag) {
                                        if (userNameLowerCaseFlag) {
                                                userName = 
userName.toLowerCase();
@@ -334,37 +347,41 @@ public class LdapUserGroupBuilder extends 
AbstractUserGroupSource {
                } else {
                        LOG.info("Performing Group search first");
                        getGroups(sink, null);
-                       if (userSearchEnabled) {
-                               LOG.info("User search is enabled and hence 
computing user membership.");
-                               getUsers(sink);
-                       } else {
-                               LOG.info("User search is disabled and hence 
using the group member attribute for username.");
-                               // Go through the userInfo map and update 
ranger admin.
-                               for (UserInfo userInfo : userGroupMap.values()) 
{
-                                       String userName = 
getShortUserName(userInfo.getUserFullName());
-                                       List<String> groupList = 
userInfo.getGroups();
-                                       if (userNameCaseConversionFlag) {
-                                               if (userNameLowerCaseFlag) {
-                                                       userName = 
userName.toLowerCase();
-                                               }
-                                               else {
-                                                       userName = 
userName.toUpperCase();
-                                               }
-                                       }
-
-                                       if (userNameRegExInst != null) {
-                                               userName = 
userNameRegExInst.transform(userName);
-                                       }
-
-                                       try {
-                                               sink.addOrUpdateUser(userName, 
groupList);
-                                       } catch (Throwable t) {
-                                               LOG.error("sink.addOrUpdateUser 
failed with exception: " + t.getMessage()
-                                               + ", for user: " + userName
-                                               + ", groups: " + groupList);
-                                       }
-                               }
-                       }
+            // Go through the userInfo map and update ranger admin.
+            for (UserInfo userInfo : userGroupMap.values()) {
+                String userName = getShortUserName(userInfo.getUserFullName());
+                if (groupHierarchyLevels > 0) {
+                    //System.out.println("Going through group hierarchy for 
nested group evaluation");
+                    goUpGroupHierarchyLdap(userInfo.getGroupDNs(), 
groupHierarchyLevels - 1, userInfo);
+                    //System.out.println("Completed group hierarchy 
computation");
+                }
+                if (userSearchEnabled) {
+                    LOG.info("User search is enabled and hence computing user 
membership.");
+                    getUsers(sink);
+                } else {
+                    LOG.info("User search is disabled and hence using the 
group member attribute for username" + userName);
+                    List<String> groupList = userInfo.getGroups();
+                    if (userNameCaseConversionFlag) {
+                        if (userNameLowerCaseFlag) {
+                            userName = userName.toLowerCase();
+                        } else {
+                            userName = userName.toUpperCase();
+                        }
+                    }
+
+                    if (userNameRegExInst != null) {
+                        userName = userNameRegExInst.transform(userName);
+                    }
+
+                    try {
+                        sink.addOrUpdateUser(userName, groupList);
+                    } catch (Throwable t) {
+                        LOG.error("sink.addOrUpdateUser failed with exception: 
" + t.getMessage()
+                                + ", for user: " + userName
+                                + ", groups: " + groupList);
+                    }
+                }
+            }
                }
        }
 
@@ -442,8 +459,10 @@ public class LdapUserGroupBuilder extends 
AbstractUserGroupSource {
                                                                                
if (userGroupfAttribute != null) {
                                                                                
        NamingEnumeration<?> groupEnum = userGroupfAttribute.getAll();
                                                                                
        while (groupEnum.hasMore()) {
-                                                                               
                String gName = getShortGroupName((String) groupEnum
-                                                                               
                                .next());
+                                                String groupDN = (String) 
groupEnum.next();
+                                                LOG.debug("Adding " + groupDN 
+ " to " + userName);
+                                                userInfo.addGroupDN(groupDN);
+                                                                               
                String gName = getShortGroupName(groupDN);
                                                                                
                if (groupNameCaseConversionFlag) {
                                                                                
                        if (groupNameLowerCaseFlag) {
                                                                                
                                gName = gName.toLowerCase();
@@ -498,7 +517,7 @@ public class LdapUserGroupBuilder extends 
AbstractUserGroupSource {
                                                                // then update 
user name in the userInfo map with the value from the search result
                                                                // and update 
ranger admin.
                                                                String 
userFullName = (userEntry.getNameInNamespace()).toLowerCase();
-                                                               
LOG.debug("Chekcing if the user " + userFullName + " is part of the retrieved 
groups");
+                                                               
LOG.debug("Checking if the user " + userFullName + " is part of the retrieved 
groups");
 
                                                                userInfo = 
userGroupMap.get(userFullName);
                                                                if (userInfo == 
null) {
@@ -508,27 +527,27 @@ public class LdapUserGroupBuilder extends 
AbstractUserGroupSource {
                                                                        
counter++;
                                                                        
LOG.info("Updating username for " + userFullName + " with " + userName);
                                                                        
userInfo.updateUserName(userName);
-                                                                       
List<String> groupList = userInfo.getGroups();
-                                                                       if 
(userNameCaseConversionFlag) {
-                                                                               
if (userNameLowerCaseFlag) {
-                                                                               
        userName = userName.toLowerCase();
-                                                                               
}
-                                                                               
else {
-                                                                               
        userName = userName.toUpperCase();
-                                                                               
}
-                                                                       }
-
-                                                                       if 
(userNameRegExInst != null) {
-                                                                               
userName = userNameRegExInst.transform(userName);
-                                                                       }
-
-                                                                       try {
-                                                                               
sink.addOrUpdateUser(userName, groupList);
-                                                                       } catch 
(Throwable t) {
-                                                                               
LOG.error("sink.addOrUpdateUser failed with exception: " + t.getMessage()
-                                                                               
+ ", for user: " + userName
-                                                                               
+ ", groups: " + groupList);
-                                                                       }
+                                    List<String> groupList = 
userInfo.getGroups();
+                                    if (userNameCaseConversionFlag) {
+                                        if (userNameLowerCaseFlag) {
+                                            userName = userName.toLowerCase();
+                                        }
+                                        else {
+                                            userName = userName.toUpperCase();
+                                        }
+                                    }
+
+                                    if (userNameRegExInst != null) {
+                                        userName = 
userNameRegExInst.transform(userName);
+                                    }
+
+                                    try {
+                                        sink.addOrUpdateUser(userName, 
groupList);
+                                    } catch (Throwable t) {
+                                        LOG.error("sink.addOrUpdateUser failed 
with exception: " + t.getMessage()
+                                                + ", for user: " + userName
+                                                + ", groups: " + groupList);
+                                    }
                                                                }
                                                        }
 
@@ -581,11 +600,12 @@ public class LdapUserGroupBuilder extends 
AbstractUserGroupSource {
        }
 
        private void getGroups(UserGroupSink sink, UserInfo userInfo) throws 
Throwable {
+        //LOG.debug("getGroups(): for user " + userInfo.getUserName());
                NamingEnumeration<SearchResult> groupSearchResultEnum = null;
                try {
                        createLdapContext();
                        int total;
-                       // Activate paged results
+            // Activate paged results
                        if (pagedResultsEnabled)   {
                                ldapContext.setRequestControls(new Control[]{
                                                new 
PagedResultsControl(pagedResultsSize, Control.NONCRITICAL) });
@@ -622,6 +642,7 @@ public class LdapUserGroupBuilder extends 
AbstractUserGroupSource {
                                                        if (groupEntry != null) 
{
                                                                counter++;
                                                                Attribute 
groupNameAttr = groupEntry.getAttributes().get(groupNameAttribute);
+                                //System.out.println("getGroups(): Going 
through all groups");
                                                                if 
(groupNameAttr == null) {
                                                                        if 
(LOG.isInfoEnabled())  {
                                                                                
LOG.info(groupNameAttribute + " empty for entry " + 
groupEntry.getNameInNamespace() +
@@ -629,7 +650,9 @@ public class LdapUserGroupBuilder extends 
AbstractUserGroupSource {
                                                                        }
                                                                        
continue;
                                                                }
-                                                               String gName = 
(String) groupNameAttr.get();
+                                String groupDN = 
groupEntry.getNameInNamespace();
+                                //System.out.println("getGroups(): groupDN = " 
+ groupDN);
+                                String gName = (String) groupNameAttr.get();
                                                                if 
(groupNameCaseConversionFlag) {
                                                                        if 
(groupNameLowerCaseFlag) {
                                                                                
gName = gName.toLowerCase();
@@ -643,9 +666,10 @@ public class LdapUserGroupBuilder extends 
AbstractUserGroupSource {
                                                                if 
(!groupSearchFirstEnabled) {
                                                                        
//computedGroups.add(gName);
                                                                        if 
(LOG.isInfoEnabled())  {
-                                                                               
LOG.info("computed groups for user: " + userInfo.getUserName() +", groups: " + 
gName);
+                                                                               
LOG.info("computed groups for user: " + userInfo.getUserName() + ", groups: " + 
gName);
                                                                        }
-                                                                       
userInfo.addGroup(gName);
+                                    userInfo.addGroupDN(groupDN);
+                                    userInfo.addGroup(gName);
                                                                } else {
                                                                        // If 
group based search is enabled, then
                                                                        // 
update the group name to ranger admin
@@ -671,9 +695,10 @@ public class LdapUserGroupBuilder extends 
AbstractUserGroupSource {
                                                                                
        userGroupMap.put(userFullName, userInfo);
                                                                                
} else {
                                                                                
        userInfo = userGroupMap.get(userFullName);
-                                                                               
}
-                                                                               
LOG.info("Adding " + gName + " to user " + userInfo.getUserFullName());
-                                                                               
userInfo.addGroup(gName);
+                                        }
+                                        LOG.info("Adding " + gName + " to user 
" + userInfo.getUserFullName());
+                                        userInfo.addGroup(gName);
+                                        userInfo.addGroupDN(groupDN);
                                                                        }
                                                                        
LOG.info("No. of members in the group " + gName + " = " + userCount);
                                                                }
@@ -755,17 +780,172 @@ public class LdapUserGroupBuilder extends 
AbstractUserGroupSource {
                return userName;
        }
 
+       private void goUpGroupHierarchyLdap(Set<String> groupDNs, int 
groupHierarchyLevels, UserInfo userInfo) throws Throwable {
+        LOG.debug("goUpGroupHierarchyLdap(): Incoming groups " + groupDNs);
+               if (groupHierarchyLevels <= 0 || groupDNs.isEmpty()) {
+                       return;
+               }
+               Set<String> nextLevelGroups = new HashSet<String>();
+
+               NamingEnumeration<SearchResult> groupSearchResultEnum = null;
+               try {
+                       createLdapContext();
+                       int total;
+                       // Activate paged results
+                       if (pagedResultsEnabled)   {
+                               ldapContext.setRequestControls(new Control[]{
+                                               new 
PagedResultsControl(pagedResultsSize, Control.NONCRITICAL) });
+                       }
+                       String groupFilter = "(&(objectclass=" + 
groupObjectClass + ")";
+            if (groupSearchFilter != null && 
!groupSearchFilter.trim().isEmpty()) {
+                String customFilter = groupSearchFilter.trim();
+                if (!customFilter.startsWith("(")) {
+                    customFilter = "(" + customFilter + ")";
+                }
+                groupFilter += customFilter + "(|";
+            }
+                       StringBuilder filter = new StringBuilder();
+
+                       for (String groupDN : groupDNs) {
+                               
filter.append("(").append(groupMemberAttributeName).append("=")
+                                               .append(groupDN).append(")");
+                       }
+                       filter.append("))");
+            groupFilter += filter;
+
+                       LOG.debug("extendedAllGroupsSearchFilter = " + 
groupFilter);
+                       for (int ou=0; ou<groupSearchBase.length; ou++) {
+                               byte[] cookie = null;
+                               int counter = 0;
+                               try {
+                                       do {
+                                               groupSearchResultEnum = 
ldapContext
+                                                                       
.search(groupSearchBase[ou], groupFilter,
+                                                                               
        groupSearchControls);
+                        //System.out.println("goUpGroupHierarchyLdap(): Going 
through the sub groups");
+                                               while 
(groupSearchResultEnum.hasMore()) {
+                                                       final SearchResult 
groupEntry = groupSearchResultEnum.next();
+                                                       if (groupEntry == null) 
{
+                                                               if 
(LOG.isInfoEnabled())  {
+                                                                       
LOG.info("groupEntry null, skipping sync for the entry");
+                                                               }
+                                                               continue;
+                                                       }
+                                                       counter++;
+                                                       Attribute groupNameAttr 
= groupEntry.getAttributes().get(groupNameAttribute);
+                                                       if (groupNameAttr == 
null) {
+                                                               if 
(LOG.isInfoEnabled())  {
+                                                                       
LOG.info(groupNameAttribute + " empty for entry " + 
groupEntry.getNameInNamespace() +
+                                                                               
        ", skipping sync");
+                                                               }
+                                                               continue;
+                                                       }
+                            String groupDN = groupEntry.getNameInNamespace();
+                            //System.out.println("goUpGroupHierarchyLdap(): 
next Level Group DN = " + groupDN);
+                                                       
nextLevelGroups.add(groupDN);
+                                                       String gName = (String) 
groupNameAttr.get();
+                                                       if 
(groupNameCaseConversionFlag) {
+                                                               if 
(groupNameLowerCaseFlag) {
+                                                                       gName = 
gName.toLowerCase();
+                                                               } else {
+                                                                       gName = 
gName.toUpperCase();
+                                                               }
+                                                       }
+                                                       if (groupNameRegExInst 
!= null) {
+                                                               gName = 
groupNameRegExInst.transform(gName);
+                                                       }
+                                                       
userInfo.addGroup(gName);
+                                               }
+                                               // Examine the paged results 
control response
+                                               Control[] controls = 
ldapContext.getResponseControls();
+                                               if (controls != null) {
+                                                       for (int i = 0; i < 
controls.length; i++) {
+                                                               if (controls[i] 
instanceof PagedResultsResponseControl) {
+                                                                       
PagedResultsResponseControl prrc =
+                                                                               
        (PagedResultsResponseControl)controls[i];
+                                                                       total = 
prrc.getResultSize();
+                                                                       if 
(total != 0) {
+                                                                               
LOG.debug("END-OF-PAGE total : " + total);
+                                                                       } else {
+                                                                               
LOG.debug("END-OF-PAGE total : unknown");
+                                                                       }
+                                                                       cookie 
= prrc.getCookie();
+                                                               }
+                                                       }
+                                               } else {
+                                                       LOG.debug("No controls 
were sent from the server");
+                                               }
+                                               // Re-activate paged results
+                                               if (pagedResultsEnabled)   {
+                                                       
ldapContext.setRequestControls(new Control[]{
+                                                                       new 
PagedResultsControl(PAGE_SIZE, cookie, Control.CRITICAL) });
+                                               }
+                                       } while (cookie != null);
+                                       
LOG.info("LdapUserGroupBuilder.goUpGroupHierarchyLdap() completed with group 
count: "
+                                                       + counter);
+                               } catch (RuntimeException re) {
+                                       
LOG.error("LdapUserGroupBuilder.goUpGroupHierarchyLdap() failed with runtime 
exception: ", re);
+                                       throw re;
+                               } catch (Exception t) {
+                                       
LOG.error("LdapUserGroupBuilder.goUpGroupHierarchyLdap() failed with exception: 
", t);
+                                       
LOG.info("LdapUserGroupBuilder.goUpGroupHierarchyLdap() group count: "
+                                                       + counter);
+                               }
+                       }
+
+               } catch (RuntimeException re) {
+                       
LOG.error("LdapUserGroupBuilder.goUpGroupHierarchyLdap() failed with exception: 
", re);
+                       throw re;
+               } finally {
+                       if (groupSearchResultEnum != null) {
+                               groupSearchResultEnum.close();
+                       }
+                       closeLdapContext();
+               }
+               goUpGroupHierarchyLdap(nextLevelGroups, groupHierarchyLevels - 
1, userInfo);
+       }
+
+       private void getRootDN() throws Throwable {
+               NamingEnumeration groupSearchResultEnum = null;
+               SearchControls sc1 = new SearchControls();
+               sc1.setSearchScope(SearchControls.OBJECT_SCOPE);
+               sc1.setReturningAttributes(new String[]{"namingContexts"});
+               try {
+                       createLdapContext();
+                       groupSearchResultEnum = ldapContext
+                                       .search("", "objectclass=*", sc1);
+                       //System.out.println("goUpGroupHierarchyLdap(): Going 
through the sub groups");
+                       while (groupSearchResultEnum.hasMore()) {
+                               SearchResult result1 = (SearchResult) 
groupSearchResultEnum.next();
+
+                               Attributes attrs = result1.getAttributes();
+                               Attribute attr = attrs.get("namingContexts");
+                               LOG.debug("namingContexts = " + attr);
+                               groupSearchBase = new String[] 
{attr.get(0).toString()};
+                               LOG.info("RootDN = " + 
Arrays.toString(groupSearchBase));
+                       }
+               } catch (RuntimeException re) {
+                       throw re;
+               } finally {
+                       if (groupSearchResultEnum != null) {
+                               groupSearchResultEnum.close();
+                       }
+                       closeLdapContext();
+               }
+       }
 }
 
 class UserInfo {
        private String userName;
        private String userFullName;
        private Set<String> groupList;
+    private Set<String> groupDNList;
 
        public UserInfo(String userName, String userFullName) {
                this.userName = userName;
                this.userFullName = userFullName;
                this.groupList = new HashSet<String>();
+        this.groupDNList = new HashSet<String>();
        }
 
        public void updateUserName(String userName) {
@@ -787,4 +967,14 @@ class UserInfo {
        public List<String> getGroups() {
                return (new ArrayList<String>(groupList));
        }
+
+    public void addGroupDNs(Set<String> groupDNs) {
+        groupDNList.addAll(groupDNs);
+    }
+    public void addGroupDN(String groupDN) {
+        groupDNList.add(groupDN);
+    }
+    public Set<String> getGroupDNs() {
+        return (groupDNList);
+    }
 }

http://git-wip-us.apache.org/repos/asf/ranger/blob/f4019d11/ugsync/src/main/java/org/apache/ranger/unixusersync/config/UserGroupSyncConfig.java
----------------------------------------------------------------------
diff --git 
a/ugsync/src/main/java/org/apache/ranger/unixusersync/config/UserGroupSyncConfig.java
 
b/ugsync/src/main/java/org/apache/ranger/unixusersync/config/UserGroupSyncConfig.java
index af27efa..45eeb1b 100644
--- 
a/ugsync/src/main/java/org/apache/ranger/unixusersync/config/UserGroupSyncConfig.java
+++ 
b/ugsync/src/main/java/org/apache/ranger/unixusersync/config/UserGroupSyncConfig.java
@@ -188,6 +188,9 @@ public class UserGroupSyncConfig  {
        private static final String LGSYNC_GROUP_MEMBER_ATTRIBUTE_NAME = 
"ranger.usersync.group.memberattributename";
        private static final String DEFAULT_LGSYNC_GROUP_MEMBER_ATTRIBUTE_NAME 
= "member";
 
+       private static final String LGSYNC_GROUP_HIERARCHY_LEVELS = 
"ranger.usersync.ldap.grouphierarchylevels";
+       private static final int DEFAULT_LGSYNC_GROUP_HIERARCHY_LEVELS = 0;
+
        private static final String UGSYNC_UPDATE_MILLIS_MIN = 
"ranger.usersync.unix.updatemillismin";
        private final static long DEFAULT_UGSYNC_UPDATE_MILLIS_MIN = 1 * 60 * 
1000; // ms
 
@@ -757,6 +760,20 @@ public class UserGroupSyncConfig  {
                return val;
        }
 
+       public int getGroupHierarchyLevels() {
+               int groupHierarchyLevels;
+               String val = prop.getProperty(LGSYNC_GROUP_HIERARCHY_LEVELS);
+               if(val == null || val.trim().isEmpty()) {
+                   groupHierarchyLevels = 
DEFAULT_LGSYNC_GROUP_HIERARCHY_LEVELS;
+               } else {
+                   groupHierarchyLevels = Integer.parseInt(val);
+               }
+               if (groupHierarchyLevels < 0)  {
+                   groupHierarchyLevels = 
DEFAULT_LGSYNC_GROUP_HIERARCHY_LEVELS;
+               }
+               return groupHierarchyLevels;
+       }
+
        public String getProperty(String aPropertyName) {
                return prop.getProperty(aPropertyName);
        }
@@ -1012,4 +1029,9 @@ public class UserGroupSyncConfig  {
        public void setUserNameAttribute(String userNameAttr) {
                prop.setProperty(LGSYNC_USER_NAME_ATTRIBUTE, userNameAttr);
        }
+
+       /* Used only for unit testing */
+       public void setGroupHierarchyLevel(int groupHierarchyLevel) {
+               prop.setProperty(LGSYNC_GROUP_HIERARCHY_LEVELS, 
String.valueOf(groupHierarchyLevel));
+        }
 }

http://git-wip-us.apache.org/repos/asf/ranger/blob/f4019d11/ugsync/src/test/java/org/apache/ranger/usergroupsync/TestLdapUserGroup.java
----------------------------------------------------------------------
diff --git 
a/ugsync/src/test/java/org/apache/ranger/usergroupsync/TestLdapUserGroup.java 
b/ugsync/src/test/java/org/apache/ranger/usergroupsync/TestLdapUserGroup.java
index 6ebc311..6393b3d 100644
--- 
a/ugsync/src/test/java/org/apache/ranger/usergroupsync/TestLdapUserGroup.java
+++ 
b/ugsync/src/test/java/org/apache/ranger/usergroupsync/TestLdapUserGroup.java
@@ -104,6 +104,7 @@ public class TestLdapUserGroup extends AbstractLdapTestUnit{
                config.setGroupSearchEnabled(false);
                config.setPagedResultsEnabled(true);
                config.setGroupSearchFirstEnabled(false);
+               //config.setGroupHierarchyLevel(0);
                ldapBuilder.init();
                PolicyMgrUserGroupBuilderTest sink = new 
PolicyMgrUserGroupBuilderTest();
                sink.init();
@@ -123,6 +124,7 @@ public class TestLdapUserGroup extends AbstractLdapTestUnit{
                config.setGroupSearchEnabled(false);
                config.setPagedResultsEnabled(false);
                config.setGroupSearchFirstEnabled(false);
+               //config.setGroupHierarchyLevel(0);
                ldapBuilder.init();
                PolicyMgrUserGroupBuilderTest sink = new 
PolicyMgrUserGroupBuilderTest();
                sink.init();
@@ -318,11 +320,12 @@ public class TestLdapUserGroup extends 
AbstractLdapTestUnit{
                config.setGroupObjectClass("groupOfNames");
                config.setGroupSearchEnabled(true);
                config.setGroupSearchFirstEnabled(true);
+               config.setUserSearchEnabled(false);
                ldapBuilder.init();
                PolicyMgrUserGroupBuilderTest sink = new 
PolicyMgrUserGroupBuilderTest();
                sink.init();
                ldapBuilder.updateSink(sink);
-               assertEquals(2, sink.getTotalUsers());
+               assertEquals(3, sink.getTotalUsers());
                assertEquals(2, sink.getTotalGroups());
        }
 
@@ -444,7 +447,7 @@ public class TestLdapUserGroup extends AbstractLdapTestUnit{
                PolicyMgrUserGroupBuilderTest sink = new 
PolicyMgrUserGroupBuilderTest();
                sink.init();
                ldapBuilder.updateSink(sink);
-               assertEquals(2, sink.getTotalUsers());
+               assertEquals(3, sink.getTotalUsers());
                assertEquals(2, sink.getTotalGroups());
        }
 
@@ -561,7 +564,7 @@ public class TestLdapUserGroup extends AbstractLdapTestUnit{
                PolicyMgrUserGroupBuilderTest sink = new 
PolicyMgrUserGroupBuilderTest();
                sink.init();
                ldapBuilder.updateSink(sink);
-               assertEquals(1, sink.getTotalUsers());
+               assertEquals(2, sink.getTotalUsers());
                assertEquals(1, sink.getTotalGroups());
        }
        
@@ -694,7 +697,7 @@ public class TestLdapUserGroup extends AbstractLdapTestUnit{
                LdapPolicyMgrUserGroupBuilderTest sink = new 
LdapPolicyMgrUserGroupBuilderTest();
                sink.init();
                ldapBuilder.updateSink(sink);
-               assertEquals(2, sink.getTotalUsers());
+               assertEquals(3, sink.getTotalUsers());
                assertEquals(2, sink.getTotalGroups());
        }
 

http://git-wip-us.apache.org/repos/asf/ranger/blob/f4019d11/ugsync/src/test/resources/ADSchema.ldif
----------------------------------------------------------------------
diff --git a/ugsync/src/test/resources/ADSchema.ldif 
b/ugsync/src/test/resources/ADSchema.ldif
index a45a2fb..1a343ed 100644
--- a/ugsync/src/test/resources/ADSchema.ldif
+++ b/ugsync/src/test/resources/ADSchema.ldif
@@ -2362,6 +2362,7 @@ objectClass: top
 objectClass: groupOfNames
 cn: Group10
 member: CN=User1000,CN=Users,DC=ranger,DC=qe,DC=hortonworks,DC=com
+member: CN=Group19,OU=Groups,DC=ranger,DC=qe,DC=hortonworks,DC=com
 distinguishedName: CN=Group10,OU=Groups,DC=ranger,DC=qe,DC=hortonworks,DC=com
 sAMAccountName: Group10
 sn: Group10
@@ -2571,6 +2572,7 @@ member: 
CN=User1804,CN=Users,DC=ranger,DC=qe,DC=hortonworks,DC=com
 member: CN=User1803,CN=Users,DC=ranger,DC=qe,DC=hortonworks,DC=com
 member: CN=User1802,CN=Users,DC=ranger,DC=qe,DC=hortonworks,DC=com
 member: CN=User1801,CN=Users,DC=ranger,DC=qe,DC=hortonworks,DC=com
+member: CN=Group18,OU=Groups,DC=ranger,DC=qe,DC=hortonworks,DC=com
 distinguishedName: CN=Group19,OU=Groups,DC=ranger,DC=qe,DC=hortonworks,DC=com
 sAMAccountName: Group19
 sn: Group19

http://git-wip-us.apache.org/repos/asf/ranger/blob/f4019d11/ugsync/src/test/resources/ranger-ugsync-site.xml
----------------------------------------------------------------------
diff --git a/ugsync/src/test/resources/ranger-ugsync-site.xml 
b/ugsync/src/test/resources/ranger-ugsync-site.xml
index 7d1c27c..0a1a86d 100644
--- a/ugsync/src/test/resources/ranger-ugsync-site.xml
+++ b/ugsync/src/test/resources/ranger-ugsync-site.xml
@@ -177,4 +177,9 @@
       <name>ranger.usersync.ldap.deltasync</name>
       <value>false</value>
     </property>
+
+    <property>
+      <name>ranger.usersync.group.hierarchylevels</name>
+      <value>2</value>
+    </property>
   </configuration>

Reply via email to