This is an automated email from the ASF dual-hosted git repository.

spolavarapu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ranger.git


The following commit(s) were added to refs/heads/master by this push:
     new cb621c3  RANGER-980: Support to update users/groups that are deleted 
at the sync source
cb621c3 is described below

commit cb621c3a07e7f9ec3013fb4b830e356e58051b34
Author: Sailaja Polavarapu <spolavar...@cloudera.com>
AuthorDate: Fri Jan 8 09:47:49 2021 -0800

    RANGER-980: Support to update users/groups that are deleted at the sync 
source
---
 .../main/java/org/apache/ranger/biz/XUserMgr.java  |  25 +
 .../java/org/apache/ranger/rest/XUserREST.java     |  16 +
 .../apache/ranger/ugsyncutil/model/XGroupInfo.java |  21 +
 .../apache/ranger/ugsyncutil/model/XUserInfo.java  |  19 +
 .../ugsyncutil/util/UgsyncCommonConstants.java     |  19 +-
 .../ldapusersync/process/LdapUserGroupBuilder.java |  52 +-
 .../unixusersync/config/UserGroupSyncConfig.java   |  74 ++-
 .../process/FileSourceUserGroupBuilder.java        |  38 +-
 .../process/PolicyMgrUserGroupBuilder.java         | 560 ++++++++++++++++-----
 .../unixusersync/process/UnixUserGroupBuilder.java |  80 ++-
 .../apache/ranger/usergroupsync/UserGroupSink.java |   3 +-
 .../PolicyMgrUserGroupBuilderTest.java             |   3 +-
 12 files changed, 703 insertions(+), 207 deletions(-)

diff --git a/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java 
b/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java
index b0d8569..010f320 100755
--- a/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java
+++ b/security-admin/src/main/java/org/apache/ranger/biz/XUserMgr.java
@@ -2972,6 +2972,7 @@ public class XUserMgr extends XUserMgrBase {
                        logger.warn("Could not find corresponding xUser for 
username: [" + vXPortalUser.getLoginId() + "], So not updating this user");
                        return vXUser;
                }
+               logger.info("xUser.getName() = " + xUser.getName() + " 
vXUser.getName() = " + vXUser.getName());
                vXUser.setId(xUser.getId());
                vXUser = xUserService.updateResource(vXUser);
                vXUser.setUserRoleList(roleList);
@@ -2995,4 +2996,28 @@ public class XUserMgr extends XUserMgrBase {
 
                return vXUser;
        }
+
+       public int updateDeletedUsers(Set<String> deletedUsers) {
+               for (String deletedUser : deletedUsers) {
+                       XXUser xUser = 
daoManager.getXXUser().findByUserName(deletedUser);
+                       if (xUser != null) {
+                               VXUser vObj = 
xUserService.populateViewBean(xUser);
+                               vObj.setIsVisible(RangerCommonEnums.IS_HIDDEN);
+                               xUserService.updateResource(vObj);
+                       }
+               }
+               return deletedUsers.size();
+       }
+
+       public int updateDeletedGroups(Set<String> deletedGroups) {
+               for (String deletedGroup : deletedGroups) {
+                       XXGroup xGroup = 
daoManager.getXXGroup().findByGroupName(deletedGroup);
+                       if (xGroup !=  null) {
+                               VXGroup vObj = 
xGroupService.populateViewBean(xGroup);
+                               vObj.setIsVisible(RangerCommonEnums.IS_HIDDEN);
+                               xGroupService.updateResource(vObj);
+                       }
+               }
+               return deletedGroups.size();
+       }
 }
diff --git a/security-admin/src/main/java/org/apache/ranger/rest/XUserREST.java 
b/security-admin/src/main/java/org/apache/ranger/rest/XUserREST.java
index 03ccfbe..8fae634 100644
--- a/security-admin/src/main/java/org/apache/ranger/rest/XUserREST.java
+++ b/security-admin/src/main/java/org/apache/ranger/rest/XUserREST.java
@@ -1408,4 +1408,20 @@ public class XUserREST {
        public List<String> setXUserRolesByName(UsersGroupRoleAssignments 
ugRoleAssignments) {
                return xUserMgr.updateUserRoleAssignments(ugRoleAssignments);
        }
+
+       @POST
+       @Path("/ugsync/groups/visibility")
+       @Produces({ "application/xml", "application/json" })
+       @PreAuthorize("hasRole('ROLE_SYS_ADMIN')")
+       public int updateDeletedGroups(Set<String> deletedGroups){
+               return xUserMgr.updateDeletedGroups(deletedGroups);
+       }
+
+       @POST
+       @Path("/ugsync/users/visibility")
+       @Produces({ "application/xml", "application/json" })
+       @PreAuthorize("hasRole('ROLE_SYS_ADMIN')")
+       public int updateDeletedUsers(Set<String> deletedUsers){
+               return xUserMgr.updateDeletedUsers(deletedUsers);
+       }
 }
diff --git 
a/ugsync-util/src/main/java/org/apache/ranger/ugsyncutil/model/XGroupInfo.java 
b/ugsync-util/src/main/java/org/apache/ranger/ugsyncutil/model/XGroupInfo.java
index df04266..5f5c9aa 100644
--- 
a/ugsync-util/src/main/java/org/apache/ranger/ugsyncutil/model/XGroupInfo.java
+++ 
b/ugsync-util/src/main/java/org/apache/ranger/ugsyncutil/model/XGroupInfo.java
@@ -19,14 +19,18 @@
 
  package org.apache.ranger.ugsyncutil.model;
 
+import java.util.Map;
+
 public class XGroupInfo {
        
        private String id;
        private String name;
        private String description;
        private String groupType;
+       private String isVisible;
        private String groupSource;
        private String otherAttributes;
+       private Map<String, String> otherAttrsMap;
        public String getId() {
                return id;
        }
@@ -52,6 +56,15 @@ public class XGroupInfo {
        public void setGroupType(String groupType) {
                this.groupType = groupType;
        }
+
+       public String getIsVisible() {
+               return isVisible;
+       }
+
+       public void setIsVisible(String isVisible) {
+               this.isVisible = isVisible;
+       }
+
        public String getGroupSource() {
                return groupSource;
        }
@@ -59,6 +72,14 @@ public class XGroupInfo {
                this.groupSource = groupSource;
        }
 
+       public Map<String, String> getOtherAttrsMap() {
+               return otherAttrsMap;
+       }
+
+       public void setOtherAttrsMap(Map<String, String> otherAttrsMap) {
+               this.otherAttrsMap = otherAttrsMap;
+       }
+
        public String getOtherAttributes() {
                return otherAttributes;
        }
diff --git 
a/ugsync-util/src/main/java/org/apache/ranger/ugsyncutil/model/XUserInfo.java 
b/ugsync-util/src/main/java/org/apache/ranger/ugsyncutil/model/XUserInfo.java
index 9405a76..058b984 100644
--- 
a/ugsync-util/src/main/java/org/apache/ranger/ugsyncutil/model/XUserInfo.java
+++ 
b/ugsync-util/src/main/java/org/apache/ranger/ugsyncutil/model/XUserInfo.java
@@ -21,14 +21,17 @@
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 public class XUserInfo {
        private String id;
        private String name;
        private String  description;
        private String otherAttributes;
+       private Map<String, String> otherAttrsMap;
        private String userSource;
        private String status;
+       private String isVisible;
     private List<String> groupNameList = new ArrayList<String>();
     private List<String> userRoleList = new ArrayList<String>();
        
@@ -67,6 +70,14 @@ public class XUserInfo {
                this.status = status;
        }
 
+       public String getIsVisible() {
+               return isVisible;
+       }
+
+       public void setIsVisible(String isVisible) {
+               this.isVisible = isVisible;
+       }
+
        public void setGroupNameList(List<String> groupNameList) {
                this.groupNameList = groupNameList;
        }
@@ -93,6 +104,14 @@ public class XUserInfo {
         this.userRoleList = userRoleList;
     }
 
+       public Map<String, String> getOtherAttrsMap() {
+               return otherAttrsMap;
+       }
+
+       public void setOtherAttrsMap(Map<String, String> otherAttrsMap) {
+               this.otherAttrsMap = otherAttrsMap;
+       }
+
        public String getOtherAttributes() {
                return otherAttributes;
        }
diff --git 
a/ugsync/src/main/java/org/apache/ranger/usergroupsync/UserGroupSink.java 
b/ugsync-util/src/main/java/org/apache/ranger/ugsyncutil/util/UgsyncCommonConstants.java
similarity index 62%
copy from 
ugsync/src/main/java/org/apache/ranger/usergroupsync/UserGroupSink.java
copy to 
ugsync-util/src/main/java/org/apache/ranger/ugsyncutil/util/UgsyncCommonConstants.java
index 794bc81..f20bf91 100644
--- a/ugsync/src/main/java/org/apache/ranger/usergroupsync/UserGroupSink.java
+++ 
b/ugsync-util/src/main/java/org/apache/ranger/ugsyncutil/util/UgsyncCommonConstants.java
@@ -17,20 +17,13 @@
  * under the License.
  */
 
- package org.apache.ranger.usergroupsync;
+package org.apache.ranger.ugsyncutil.util;
 
-import org.apache.ranger.ugsyncutil.model.UgsyncAuditInfo;
+public class UgsyncCommonConstants {
 
-import java.util.Map;
-import java.util.Set;
-
-public interface UserGroupSink {
-       void init() throws Throwable;
-
-       void postUserGroupAuditInfo(UgsyncAuditInfo ugsyncAuditInfo) throws 
Throwable;
-
-       void addOrUpdateUsersGroups(Map<String, Map<String, String>> 
sourceGroups,
-                                                               Map<String, 
Map<String, String>> sourceUsers,
-                                                               Map<String, 
Set<String>> sourceGroupUsers) throws Throwable;
+    public static final String ORIGINAL_NAME = "original_name";
+    public static final String FULL_NAME = "full_name";
+    public static final String SYNC_SOURCE = "sync_source";
+    public static final String LDAP_URL = "ldap_url";
 
 }
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 7e5e70a..c8fe3fc 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
@@ -48,6 +48,7 @@ import javax.naming.ldap.StartTlsRequest;
 import javax.naming.ldap.StartTlsResponse;
 import org.apache.commons.lang.StringUtils;
 import org.apache.log4j.Logger;
+import org.apache.ranger.ugsyncutil.util.UgsyncCommonConstants;
 import org.apache.ranger.unixusersync.config.UserGroupSyncConfig;
 import org.apache.ranger.ugsyncutil.model.LdapSyncSourceInfo;
 import org.apache.ranger.ugsyncutil.model.UgsyncAuditInfo;
@@ -62,7 +63,7 @@ public class LdapUserGroupBuilder implements UserGroupSource {
        private static final Logger LOG = 
Logger.getLogger(LdapUserGroupBuilder.class);
 
        private UserGroupSyncConfig config = UserGroupSyncConfig.getInstance();
-       
+
        private static final String DATA_TYPE_BYTEARRAY = "byte[]";
        private static final String DATE_FORMAT = "yyyyMMddHHmmss";
        private static final int PAGE_SIZE = 500;
@@ -106,6 +107,8 @@ public class LdapUserGroupBuilder implements 
UserGroupSource {
        private String groupCloudIdAttribute;
        private Set<String> otherGroupAttributes;
        private int groupHierarchyLevels;
+       private int deleteCycles;
+       private String currentSyncSource;
 
        private LdapContext ldapContext;
        StartTlsResponse tls;
@@ -127,6 +130,7 @@ public class LdapUserGroupBuilder implements 
UserGroupSource {
        public void init() throws Throwable{
                deltaSyncUserTime = 0;
                deltaSyncGroupTime = 0;
+               deleteCycles = 1;
                DateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
                deltaSyncUserTimeStamp = dateFormat.format(new Date(0));
                deltaSyncGroupTimeStamp = dateFormat.format(new Date(0));
@@ -139,7 +143,7 @@ public class LdapUserGroupBuilder implements 
UserGroupSource {
                
ldapSyncSourceInfo.setGroupSearchEnabled(Boolean.toString(groupSearchEnabled));
                
ldapSyncSourceInfo.setGroupSearchFirstEnabled(Boolean.toString(groupSearchFirstEnabled));
                
ldapSyncSourceInfo.setGroupHierarchyLevel(Integer.toString(groupHierarchyLevels));
-               ugsyncAuditInfo.setSyncSource("LDAP/AD");
+               ugsyncAuditInfo.setSyncSource(currentSyncSource);
                ugsyncAuditInfo.setLdapSyncSourceInfo(ldapSyncSourceInfo);
        }
 
@@ -200,6 +204,7 @@ public class LdapUserGroupBuilder implements 
UserGroupSource {
        private void setConfig() throws Throwable {
                LOG.info("LdapUserGroupBuilder initialization started");
 
+               currentSyncSource = config.getCurrentSyncSource();
                groupSearchFirstEnabled =   true;
                userSearchEnabled =   true;
                groupSearchEnabled =   true;
@@ -316,13 +321,24 @@ public class LdapUserGroupBuilder implements 
UserGroupSource {
        @Override
        public void updateSink(UserGroupSink sink) throws Throwable {
                LOG.info("LdapUserGroupBuilder updateSink started");
+               boolean computeDeletes = false;
                groupUserTable = HashBasedTable.create();
                sourceGroups = new HashMap<>();
                sourceUsers = new HashMap<>();
                sourceGroupUsers = new HashMap<>();
 
-        long highestdeltaSyncGroupTime = getGroups();
-        long highestdeltaSyncUserTime = getUsers();
+               if (config.isUserSyncDeletesEnabled() && deleteCycles >= 
config.getUserSyncDeletesFrequency()) {
+                       deleteCycles = 1;
+                       computeDeletes = true;
+                       if (LOG.isDebugEnabled()) {
+                               LOG.debug("Compute deleted users/groups is 
enabled for this sync cycle");
+                       }
+               }
+               if (config.isUserSyncDeletesEnabled()) {
+                       deleteCycles++;
+               }
+        long highestdeltaSyncGroupTime = getGroups(computeDeletes);
+        long highestdeltaSyncUserTime = getUsers(computeDeletes);
 
                if (groupHierarchyLevels > 0) {
                        LOG.info("Going through group hierarchy for nested 
group evaluation");
@@ -354,7 +370,7 @@ public class LdapUserGroupBuilder implements 
UserGroupSource {
                }
 
                try {
-                       sink.addOrUpdateUsersGroups(sourceGroups, sourceUsers, 
sourceGroupUsers);
+                       sink.addOrUpdateUsersGroups(sourceGroups, sourceUsers, 
sourceGroupUsers, computeDeletes);
                        DateFormat dateFormat = new 
SimpleDateFormat(DATE_FORMAT);
                        LOG.info("deltaSyncUserTime = " + deltaSyncUserTime + " 
and highestdeltaSyncUserTime = " + highestdeltaSyncUserTime);
                        if (deltaSyncUserTime < highestdeltaSyncUserTime) {
@@ -386,7 +402,7 @@ public class LdapUserGroupBuilder implements 
UserGroupSource {
                }
        }
 
-       private long getUsers() throws Throwable {
+       private long getUsers(boolean computeDeletes) throws Throwable {
                NamingEnumeration<SearchResult> userSearchResultEnum = null;
                NamingEnumeration<SearchResult> groupSearchResultEnum = null;
                long highestdeltaSyncUserTime;
@@ -399,7 +415,7 @@ public class LdapUserGroupBuilder implements 
UserGroupSource {
                                                new 
PagedResultsControl(pagedResultsSize, Control.NONCRITICAL) });
                        }
                        DateFormat dateFormat = new 
SimpleDateFormat(DATE_FORMAT);
-                       if (groupUserTable.rowKeySet().size() != 0 || 
!config.isDeltaSyncEnabled()) {
+                       if (groupUserTable.rowKeySet().size() != 0 || 
!config.isDeltaSyncEnabled() || (computeDeletes)) {
                                // Fix RANGER-1957: Perform full sync when 
there are updates to the groups or when incremental sync is not enabled
                                deltaSyncUserTime = 0;
                                deltaSyncUserTimeStamp = dateFormat.format(new 
Date(0));
@@ -495,8 +511,10 @@ public class LdapUserGroupBuilder implements 
UserGroupSource {
                                                }
 
                                                Map<String, String> userAttrMap 
= new HashMap<>();
-                                               
userAttrMap.put("original_name", userName);
-                                               userAttrMap.put("full_name", 
userFullName);
+                                               
userAttrMap.put(UgsyncCommonConstants.ORIGINAL_NAME, userName);
+                                               
userAttrMap.put(UgsyncCommonConstants.FULL_NAME, userFullName);
+                                               
userAttrMap.put(UgsyncCommonConstants.SYNC_SOURCE, currentSyncSource);
+                                               
userAttrMap.put(UgsyncCommonConstants.LDAP_URL, config.getLdapUrl());
                                                Attribute userCloudIdAttr = 
attributes.get(userCloudIdAttribute);
                                                if (userCloudIdAttr != null) {
                                                        
addToAttrMap(userAttrMap, "cloud_id", userCloudIdAttr, 
config.getUserCloudIdAttributeDataType());
@@ -589,7 +607,7 @@ public class LdapUserGroupBuilder implements 
UserGroupSource {
                return highestdeltaSyncUserTime;
        }
 
-       private long getGroups() throws Throwable {
+       private long getGroups(boolean computeDeletes) throws Throwable {
                NamingEnumeration<SearchResult> groupSearchResultEnum = null;
         DateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
         long highestdeltaSyncGroupTime = deltaSyncGroupTime;
@@ -610,7 +628,7 @@ public class LdapUserGroupBuilder implements 
UserGroupSource {
                                extendedGroupSearchFilter = 
extendedGroupSearchFilter + customFilter;
                        }
 
-                       if (!config.isDeltaSyncEnabled()) {
+                       if (!config.isDeltaSyncEnabled() || (computeDeletes)) {
                                // Perform full sync when incremental sync is 
not enabled
                                deltaSyncGroupTime = 0;
                                deltaSyncGroupTimeStamp = dateFormat.format(new 
Date(0));
@@ -649,8 +667,10 @@ public class LdapUserGroupBuilder implements 
UserGroupSource {
                                                        String groupFullName = 
(groupEntry.getNameInNamespace());
                                                        String gName = (String) 
groupNameAttr.get();
                                                        Map<String, String> 
groupAttrMap = new HashMap<>();
-                                                       
groupAttrMap.put("original_name", gName);
-                                                       
groupAttrMap.put("full_name", groupFullName);
+                                                       
groupAttrMap.put(UgsyncCommonConstants.ORIGINAL_NAME, gName);
+                                                       
groupAttrMap.put(UgsyncCommonConstants.FULL_NAME, groupFullName);
+                                                       
groupAttrMap.put(UgsyncCommonConstants.SYNC_SOURCE, currentSyncSource);
+                                                       
groupAttrMap.put(UgsyncCommonConstants.LDAP_URL, config.getLdapUrl());
                                                        Attribute 
groupCloudIdAttr = attributes.get(groupCloudIdAttribute);
                                                        if (groupCloudIdAttr != 
null) {
                                                                
addToAttrMap(groupAttrMap, "cloud_id", groupCloudIdAttr, 
config.getGroupCloudIdAttributeDataType());
@@ -870,8 +890,10 @@ public class LdapUserGroupBuilder implements 
UserGroupSource {
 
 
                                                        Map<String, String> 
groupAttrMap = new HashMap<>();
-                                                       
groupAttrMap.put("original_name", gName);
-                                                       
groupAttrMap.put("full_name", groupFullName);
+                                                       
groupAttrMap.put(UgsyncCommonConstants.ORIGINAL_NAME, gName);
+                                                       
groupAttrMap.put(UgsyncCommonConstants.FULL_NAME, groupFullName);
+                                                       
groupAttrMap.put(UgsyncCommonConstants.SYNC_SOURCE, currentSyncSource);
+                                                       
groupAttrMap.put(UgsyncCommonConstants.LDAP_URL, config.getLdapUrl());
                                                        for (String 
otherGroupAttribute : otherGroupAttributes) {
                                                                Attribute 
otherGroupAttr = groupEntry.getAttributes().get(otherGroupAttribute);
                                                                if 
(otherGroupAttr != null) {
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 5d5ad58..31e15a1 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
@@ -61,7 +61,7 @@ public class UserGroupSyncConfig  {
        
        public static final String UGSYNC_UNIX_GROUP_FILE = 
"ranger.usersync.unix.group.file";
        public static final String  DEFAULT_UGSYNC_UNIX_GROUP_FILE =   
"/etc/group";
-       
+
        public static final String  UGSYNC_MIN_USERID_PROP  =   
"ranger.usersync.unix.minUserId";
 
        public static final String  UGSYNC_MIN_GROUPID_PROP =   
"ranger.usersync.unix.minGroupId";
@@ -72,7 +72,7 @@ public class UserGroupSyncConfig  {
        public static final String  UGSYNC_MOCK_RUN_PROP  =     
"ranger.usersync.policymanager.mockrun";
 
        public static final String  UGSYNC_TEST_RUN_PROP  =     
"ranger.usersync.policymanager.testrun";
-       
+
        public static final String UGSYNC_SOURCE_FILE_PROC =    
"ranger.usersync.filesource.file";
 
        public static final String UGSYNC_SOURCE_FILE_DELIMITER = 
"ranger.usersync.filesource.text.delimiter";
@@ -113,7 +113,7 @@ public class UserGroupSyncConfig  {
        private static final String LGSYNC_SOURCE_CLASS = 
"org.apache.ranger.ldapusersync.process.LdapUserGroupBuilder";
 
        private static final String LGSYNC_LDAP_URL = 
"ranger.usersync.ldap.url";
-       
+
        private static final String LGSYNC_LDAP_DELTASYNC_ENABLED = 
"ranger.usersync.ldap.deltasync";
        private static final boolean DEFAULT_LGSYNC_LDAP_DELTASYNC_ENABLED = 
false;
 
@@ -269,6 +269,11 @@ public class UserGroupSyncConfig  {
     private static final long    
DEFAULT_UGSYNC_METRICS_FREQUENCY_TIME_IN_MILLIS = 10000L;
     public static final String   UGSYNC_METRICS_ENABLED_PROP = 
"ranger.usersync.metrics.enabled";
 
+       private static final String UGSYNC_DELETES_ENABLED = 
"ranger.usersync.deletes.enabled";
+       private static final boolean DEFAULT_UGSYNC_DELETES_ENABLED = false;
+       private static final String  UGSYNC_DELETES_FREQUENCY = 
"ranger.usersync.deletes.frequency";
+       private static final long    DEFAULT_UGSYNC_DELETES_FREQUENCY = 10L; // 
After every 10 sync cycles
+
     private Properties prop = new Properties();
 
        private static volatile UserGroupSyncConfig me = null;
@@ -322,7 +327,7 @@ public class UserGroupSyncConfig  {
                }
                return val;
        }
-       
+
        public String getUnixPasswordFile() {
                String val = prop.getProperty(UGSYNC_UNIX_PASSWORD_FILE);
                if ( val == null ) {
@@ -331,7 +336,7 @@ public class UserGroupSyncConfig  {
 
                return val;
        }
-       
+
        public String getUnixGroupFile() {
                String val = prop.getProperty(UGSYNC_UNIX_GROUP_FILE);
                if ( val == null ) {
@@ -368,7 +373,7 @@ public class UserGroupSyncConfig  {
                String val = prop.getProperty(UGSYNC_MOCK_RUN_PROP);
                return (val != null && val.trim().equalsIgnoreCase("true"));
        }
-       
+
        public boolean isTestRunEnabled() {
                String val = prop.getProperty(UGSYNC_TEST_RUN_PROP);
                return (val != null && val.trim().equalsIgnoreCase("true"));
@@ -505,7 +510,7 @@ public class UserGroupSyncConfig  {
        private String getUserGroupSourceClassName() {
                String val =  prop.getProperty(UGSYNC_SOURCE_CLASS_PARAM);
                String className = UGSYNC_SOURCE_CLASS;
-               
+
                String syncSource = null;
 
                if(val == null || val.trim().isEmpty()) {
@@ -524,11 +529,11 @@ public class UserGroupSyncConfig  {
                        className = UGSYNC_SOURCE_CLASS;
                }else if(syncSource!=null && 
syncSource.equalsIgnoreCase("LDAP")){
                        className = LGSYNC_SOURCE_CLASS;
-               } 
+               }
 
                return className;
        }
-       
+
        public UserGroupSource getUserGroupSource() throws Throwable {
 
                String className = getUserGroupSourceClassName();
@@ -1078,7 +1083,7 @@ public class UserGroupSyncConfig  {
                }
                return starttlsEnabled;
        }
-       
+
        public boolean isDeltaSyncEnabled() {
                boolean deltaSyncEnabled;
                String val = prop.getProperty(LGSYNC_LDAP_DELTASYNC_ENABLED);
@@ -1149,11 +1154,11 @@ public class UserGroupSyncConfig  {
        public void setGroupObjectClass(String groupObjectClass) {
                prop.setProperty(LGSYNC_GROUP_OBJECT_CLASS, groupObjectClass);
        }
-       
+
        /* Used only for unit testing */
        public void setDeltaSync(boolean deltaSyncEnabled) {
                prop.setProperty(LGSYNC_LDAP_DELTASYNC_ENABLED, 
String.valueOf(deltaSyncEnabled));
-       }       
+       }
 
        /* Used only for unit testing */
        public void setUserNameAttribute(String userNameAttr) {
@@ -1217,4 +1222,49 @@ public class UserGroupSyncConfig  {
                String val = prop.getProperty(UGSYNC_METRICS_ENABLED_PROP);
                return "true".equalsIgnoreCase(StringUtils.trimToEmpty(val));
        }
+
+
+       public boolean isUserSyncDeletesEnabled() {
+               boolean isUserSyncDeletesEnabled;
+               String val = prop.getProperty(UGSYNC_DELETES_ENABLED);
+               if(StringUtils.isEmpty(val)) {
+                       isUserSyncDeletesEnabled = 
DEFAULT_UGSYNC_DELETES_ENABLED;
+               } else {
+                       isUserSyncDeletesEnabled  = Boolean.valueOf(val);
+               }
+               return isUserSyncDeletesEnabled;
+       }
+
+       /*
+        * This is the frequency of computing deleted users/groups from the 
sync source.
+        * Default and minimum value is 8hrs
+        * If the delete frequency interval value is less than sync interval 
and greater than 8hrs,
+        * then deleted objects are computed at every sync cycle.
+        */
+       public long getUserSyncDeletesFrequency() throws Throwable {
+               long ret = 1;
+
+               String val = prop.getProperty(UGSYNC_DELETES_FREQUENCY);
+               if (StringUtils.isNotBlank(val)) {
+                       ret = Long.valueOf(val);
+                       if (!isTestRunEnabled() && ret < 
DEFAULT_UGSYNC_DELETES_FREQUENCY) {
+                               LOG.info("Frequency of computing deletes cannot 
be set below " + DEFAULT_UGSYNC_DELETES_FREQUENCY);
+                               ret = DEFAULT_UGSYNC_DELETES_FREQUENCY;
+                       }
+               }
+               return ret;
+       }
+
+       public String getCurrentSyncSource() throws Throwable{
+               String currentSyncSource;
+               String className = getUserGroupSource().getClass().getName();
+               if (LGSYNC_SOURCE_CLASS.equals(className)) {
+                       currentSyncSource = "LDAP/AD";
+               } else if (UGSYNC_SOURCE_CLASS.equalsIgnoreCase(className)){
+                       currentSyncSource = "Unix";
+               } else {
+                       currentSyncSource = "File";
+               }
+               return currentSyncSource;
+       }
 }
diff --git 
a/ugsync/src/main/java/org/apache/ranger/unixusersync/process/FileSourceUserGroupBuilder.java
 
b/ugsync/src/main/java/org/apache/ranger/unixusersync/process/FileSourceUserGroupBuilder.java
index 5f3523e..0a4de66 100644
--- 
a/ugsync/src/main/java/org/apache/ranger/unixusersync/process/FileSourceUserGroupBuilder.java
+++ 
b/ugsync/src/main/java/org/apache/ranger/unixusersync/process/FileSourceUserGroupBuilder.java
@@ -37,6 +37,7 @@ import org.apache.commons.csv.CSVFormat;
 import org.apache.commons.csv.CSVParser;
 import org.apache.commons.csv.CSVRecord;
 import org.apache.log4j.Logger;
+import org.apache.ranger.ugsyncutil.util.UgsyncCommonConstants;
 import org.apache.ranger.unixusersync.config.UserGroupSyncConfig;
 import org.apache.ranger.ugsyncutil.model.FileSyncSourceInfo;
 import org.apache.ranger.ugsyncutil.model.UgsyncAuditInfo;
@@ -62,6 +63,9 @@ public class FileSourceUserGroupBuilder extends 
AbstractUserGroupSource  impleme
        private boolean isStartupFlag = false;
 
        private boolean isUpdateSinkSucc = true;
+       private int deleteCycles;
+       private boolean computeDeletes = false;
+       private String currentSyncSource;
 
        public static void main(String[] args) throws Throwable {
                FileSourceUserGroupBuilder filesourceUGBuilder = new 
FileSourceUserGroupBuilder();
@@ -90,12 +94,14 @@ public class FileSourceUserGroupBuilder extends 
AbstractUserGroupSource  impleme
        @Override
        public void init() throws Throwable {
                isStartupFlag = true;
+               deleteCycles = 1;
+               currentSyncSource = config.getCurrentSyncSource();
                if(userGroupFilename == null) {
                        userGroupFilename = config.getUserSyncFileSource();
                }
                ugsyncAuditInfo = new UgsyncAuditInfo();
                fileSyncSourceInfo = new FileSyncSourceInfo();
-               ugsyncAuditInfo.setSyncSource("File");
+               ugsyncAuditInfo.setSyncSource(currentSyncSource);
                ugsyncAuditInfo.setFileSyncSourceInfo(fileSyncSourceInfo);
                fileSyncSourceInfo.setFileName(userGroupFilename);
                buildUserGroupInfo();
@@ -103,13 +109,29 @@ public class FileSourceUserGroupBuilder extends 
AbstractUserGroupSource  impleme
        
        @Override
        public boolean isChanged() {
+               computeDeletes = false;
                // If previous update to Ranger admin fails, 
                // we want to retry the sync process even if there are no 
changes to the sync files
                if (!isUpdateSinkSucc) {
                        LOG.info("Previous updateSink failed and hence 
retry!!");
                        return true;
                }
-               
+               try {
+                       if (config.isUserSyncDeletesEnabled() && deleteCycles 
>= config.getUserSyncDeletesFrequency()) {
+                               deleteCycles = 1;
+                               computeDeletes = true;
+                               if (LOG.isDebugEnabled()) {
+                                       LOG.debug("Compute deleted users/groups 
is enabled for this sync cycle");
+                               }
+                               return true;
+                       }
+               } catch (Throwable t) {
+                       LOG.error("Failed to get information about usersync 
delete frequency", t);
+               }
+               if (config.isUserSyncDeletesEnabled()) {
+                       deleteCycles++;
+               }
+
                long TempUserGroupFileModifedAt = new 
File(userGroupFilename).lastModified();
                if (usergroupFileModified != TempUserGroupFileModifedAt) {
                        return true;
@@ -132,15 +154,17 @@ public class FileSourceUserGroupBuilder extends 
AbstractUserGroupSource  impleme
                        for (Map.Entry<String, List<String>> entry : 
user2GroupListMap.entrySet()) {
                                String userName = entry.getKey();
                                Map<String, String> userAttrMap = new 
HashMap<>();
-                               userAttrMap.put("original_name", userName);
-                               userAttrMap.put("full_name", userName);
+                               
userAttrMap.put(UgsyncCommonConstants.ORIGINAL_NAME, userName);
+                               
userAttrMap.put(UgsyncCommonConstants.FULL_NAME, userName);
+                               
userAttrMap.put(UgsyncCommonConstants.SYNC_SOURCE, currentSyncSource);
                                sourceUsers.put(userName, userAttrMap);
                                List<String> groups = entry.getValue();
                                if (groups != null) {
                                        for(String groupName : groups) {
                                                Map<String, String> 
groupAttrMap = new HashMap<>();
-                                               
groupAttrMap.put("original_name", groupName);
-                                               groupAttrMap.put("full_name", 
groupName);
+                                               
groupAttrMap.put(UgsyncCommonConstants.ORIGINAL_NAME, groupName);
+                                               
groupAttrMap.put(UgsyncCommonConstants.FULL_NAME, groupName);
+                                               
groupAttrMap.put(UgsyncCommonConstants.SYNC_SOURCE, currentSyncSource);
                                                sourceGroups.put(groupName, 
groupAttrMap);
                                                Set<String> groupUsers = 
sourceGroupUsers.get(groupName);
                                                if 
(CollectionUtils.isNotEmpty(groupUsers)) {
@@ -161,7 +185,7 @@ public class FileSourceUserGroupBuilder extends 
AbstractUserGroupSource  impleme
                        }
 
                        try {
-                               sink.addOrUpdateUsersGroups(sourceGroups, 
sourceUsers, sourceGroupUsers);
+                               sink.addOrUpdateUsersGroups(sourceGroups, 
sourceUsers, sourceGroupUsers, computeDeletes);
                        } catch (Throwable t) {
                                LOG.error("Failed to update ranger admin. Will 
retry in next sync cycle!!", t);
                                isUpdateSinkSucc = false;
diff --git 
a/ugsync/src/main/java/org/apache/ranger/unixusersync/process/PolicyMgrUserGroupBuilder.java
 
b/ugsync/src/main/java/org/apache/ranger/unixusersync/process/PolicyMgrUserGroupBuilder.java
index 556d976..15a7a38 100644
--- 
a/ugsync/src/main/java/org/apache/ranger/unixusersync/process/PolicyMgrUserGroupBuilder.java
+++ 
b/ugsync/src/main/java/org/apache/ranger/unixusersync/process/PolicyMgrUserGroupBuilder.java
@@ -44,6 +44,7 @@ import org.apache.commons.lang.StringUtils;
 import org.apache.hadoop.security.SecureClientLogin;
 import org.apache.log4j.Level;
 import org.apache.log4j.Logger;
+import org.apache.ranger.ugsyncutil.util.UgsyncCommonConstants;
 import org.apache.ranger.unixusersync.config.UserGroupSyncConfig;
 import org.apache.ranger.unixusersync.model.GetXGroupListResponse;
 import org.apache.ranger.unixusersync.model.GetXUserListResponse;
@@ -57,7 +58,7 @@ import org.apache.ranger.usergroupsync.UserGroupSink;
 
 public class PolicyMgrUserGroupBuilder extends AbstractUserGroupSource 
implements UserGroupSink {
 
-private static final Logger LOG = 
Logger.getLogger(PolicyMgrUserGroupBuilder.class);
+       private static final Logger LOG = 
Logger.getLogger(PolicyMgrUserGroupBuilder.class);
 
        private static final String AUTHENTICATION_TYPE = 
"hadoop.security.authentication";
        private String AUTH_KERBEROS = "kerberos";
@@ -80,8 +81,14 @@ private static final Logger LOG = 
Logger.getLogger(PolicyMgrUserGroupBuilder.cla
 
        public static final String PM_UPDATE_USERS_ROLES_URI  = 
"/service/xusers/users/roleassignments";        // PUT
 
+       private static final String PM_UPDATE_DELETED_GROUPS_URI = 
"/service/xusers/ugsync/groups/visibility";  // POST
+
+       private static final String PM_UPDATE_DELETED_USERS_URI = 
"/service/xusers/ugsync/users/visibility";    // POST
+
        private static final String SOURCE_EXTERNAL ="1";
        private static final String STATUS_ENABLED = "1";
+       private static final String ISVISIBLE = "1";
+       private static final String ISHIDDEN = "0";
 
        private static String LOCAL_HOSTNAME = "unknown";
        private String recordsToPullPerCall = "10";
@@ -107,6 +114,9 @@ private static final Logger LOG = 
Logger.getLogger(PolicyMgrUserGroupBuilder.cla
        private Map<String, Set<String>> deltaGroupUsers;
        private Set<String> computeRolesForUsers;
 
+       private Map<String, XGroupInfo> deletedGroups;
+       private Map<String, XUserInfo> deletedUsers;
+
        private int noOfNewUsers;
        private int noOfNewGroups;
        private int noOfModifiedUsers;
@@ -116,16 +126,18 @@ private static final Logger LOG = 
Logger.getLogger(PolicyMgrUserGroupBuilder.cla
        private boolean groupNameCaseConversionFlag;
        private boolean userNameLowerCaseFlag = false;
        private boolean groupNameLowerCaseFlag = false;
+       private String currentSyncSource;
+       private String ldapUrl;
 
        private String authenticationType = null;
        String principal;
        String keytab;
        String nameRules;
-    Map<String, String> userMap = new LinkedHashMap<String, String>();
-    Map<String, String> groupMap = new LinkedHashMap<>();
+       Map<String, String> userMap = new LinkedHashMap<String, String>();
+       Map<String, String> groupMap = new LinkedHashMap<>();
 
-    private boolean isRangerCookieEnabled;
-    private String rangerCookieName;
+       private boolean isRangerCookieEnabled;
+       private String rangerCookieName;
        static {
                try {
                        LOCAL_HOSTNAME = 
java.net.InetAddress.getLocalHost().getCanonicalHostName();
@@ -176,6 +188,11 @@ private static final Logger LOG = 
Logger.getLogger(PolicyMgrUserGroupBuilder.cla
                groupCache = new HashMap<>();
                groupUsersCache = new HashMap<>();
                isStartupFlag = true;
+               ldapUrl = null;
+               currentSyncSource = config.getCurrentSyncSource();
+               if (StringUtils.equalsIgnoreCase(currentSyncSource, "LDAP/AD")) 
{
+                       ldapUrl = config.getLdapUrl();
+               }
 
                if (isMockRun) {
                        LOG.setLevel(Level.DEBUG);
@@ -191,7 +208,7 @@ private static final Logger LOG = 
Logger.getLogger(PolicyMgrUserGroupBuilder.cla
                try {
                        principal = 
SecureClientLogin.getPrincipal(config.getProperty(PRINCIPAL,""), 
LOCAL_HOSTNAME);
                } catch (IOException ignored) {
-                        // do nothing
+                       // do nothing
                }
                keytab = config.getProperty(KEYTAB,"");
                nameRules = config.getProperty(NAME_RULE,"DEFAULT");
@@ -199,17 +216,17 @@ private static final Logger LOG = 
Logger.getLogger(PolicyMgrUserGroupBuilder.cla
                                trustStoreFile, trustStoreFilepwd, 
trustStoreType, authenticationType, principal, keytab,
                                config.getPolicyMgrUserName(), 
config.getPolicyMgrPassword());
 
-        String userGroupRoles = config.getGroupRoleRules();
-        if (userGroupRoles != null && !userGroupRoles.isEmpty()) {
-            getRoleForUserGroups(userGroupRoles);
-        }
+               String userGroupRoles = config.getGroupRoleRules();
+               if (userGroupRoles != null && !userGroupRoles.isEmpty()) {
+                       getRoleForUserGroups(userGroupRoles);
+               }
                buildUserGroupInfo();
 
-        if (LOG.isDebugEnabled()) {
+               if (LOG.isDebugEnabled()) {
                        LOG.debug("PolicyMgrUserGroupBuilderOld.init()==> 
PolMgrBaseUrl : "+policyMgrBaseUrl+" KeyStore File : "+keyStoreFile+" 
TrustStore File : "+trustStoreFile+ "Authentication Type : 
"+authenticationType);
                }
 
-    }
+       }
 
        @Override
        public void postUserGroupAuditInfo(UgsyncAuditInfo ugsyncAuditInfo) 
throws Throwable {
@@ -245,7 +262,8 @@ private static final Logger LOG = 
Logger.getLogger(PolicyMgrUserGroupBuilder.cla
        @Override
        public void addOrUpdateUsersGroups(Map<String, Map<String, String>> 
sourceGroups,
                                                                           
Map<String, Map<String, String>> sourceUsers,
-                                                                          
Map<String, Set<String>> sourceGroupUsers) throws Throwable {
+                                                                          
Map<String, Set<String>> sourceGroupUsers,
+                                                                          
boolean computeDeletes) throws Throwable {
 
                noOfNewUsers = 0;
                noOfNewGroups = 0;
@@ -253,6 +271,27 @@ private static final Logger LOG = 
Logger.getLogger(PolicyMgrUserGroupBuilder.cla
                noOfModifiedGroups = 0;
                computeRolesForUsers = new HashSet<>();
 
+               if (!isStartupFlag && computeDeletes) {
+                       LOG.info("Computing deleted users/groups");
+                       if (LOG.isDebugEnabled()) {
+                               LOG.debug("Computing deleted users/groups");
+                       }
+                       if (MapUtils.isNotEmpty(sourceGroups)) {
+                               updateDeletedGroups(sourceGroups);
+                       }
+                       if (MapUtils.isNotEmpty(sourceUsers)) {
+                               updateDeletedUsers(sourceUsers);
+                       }
+
+                       if (MapUtils.isNotEmpty(deletedGroups)) {
+                               groupCache.putAll(deletedGroups);
+                       }
+
+                       if (MapUtils.isNotEmpty(deletedUsers)) {
+                               userCache.putAll(deletedUsers);
+                       }
+               }
+
                if (MapUtils.isNotEmpty(sourceGroups)) {
                        addOrUpdateGroups(sourceGroups);
                }
@@ -387,6 +426,7 @@ private static final Logger LOG = 
Logger.getLogger(PolicyMgrUserGroupBuilder.cla
                                                LOG.debug("GROUP:  Id:" + 
g.getId() + ", Name: " + g.getName() + ", Description: "
                                                                + 
g.getDescription());
                                        }
+                                       
g.setOtherAttrsMap(gson.fromJson(g.getOtherAttributes(), Map.class));
                                        groupCache.put(g.getName(), g);
                                }
                                retrievedCount = groupCache.size();
@@ -440,6 +480,7 @@ private static final Logger LOG = 
Logger.getLogger(PolicyMgrUserGroupBuilder.cla
                                                LOG.debug("USER: Id:" + 
u.getId() + ", Name: " + u.getName() + ", Description: "
                                                                + 
u.getDescription());
                                        }
+                                       
u.setOtherAttrsMap(gson.fromJson(u.getOtherAttributes(), Map.class));
                                        userCache.put(u.getName(), u);
                                }
                                retrievedCount = userCache.size();
@@ -458,34 +499,34 @@ private static final Logger LOG = 
Logger.getLogger(PolicyMgrUserGroupBuilder.cla
                String relativeUrl = PM_GET_ALL_GROUP_USER_MAP_LIST_URI;
 
                String response = null;
-                       ClientResponse clientResp = null;
+               ClientResponse clientResp = null;
 
-                       Gson gson = new GsonBuilder().create();
-                       if (isRangerCookieEnabled) {
-                               response = cookieBasedGetEntity(relativeUrl, 0);
-                       } else {
-                               try {
-                                       clientResp = 
ldapUgSyncClient.get(relativeUrl, null);
-                                       if (clientResp != null) {
-                                               response = 
clientResp.getEntity(String.class);
-                                       }
-                               } catch (Exception e) {
-                                       LOG.error("Failed to get response, 
group user mappings from Ranger admin. Error is : " + e.getMessage());
-                                       throw e;
+               Gson gson = new GsonBuilder().create();
+               if (isRangerCookieEnabled) {
+                       response = cookieBasedGetEntity(relativeUrl, 0);
+               } else {
+                       try {
+                               clientResp = ldapUgSyncClient.get(relativeUrl, 
null);
+                               if (clientResp != null) {
+                                       response = 
clientResp.getEntity(String.class);
                                }
+                       } catch (Exception e) {
+                               LOG.error("Failed to get response, group user 
mappings from Ranger admin. Error is : " + e.getMessage());
+                               throw e;
                        }
-                       if (LOG.isDebugEnabled()) {
-                               LOG.debug("RESPONSE: [" + response + "]");
-                       }
+               }
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("RESPONSE: [" + response + "]");
+               }
 
-                       groupUsersCache = gson.fromJson(response, Map.class);
-                       if (MapUtils.isEmpty(groupUsersCache)) {
-                               groupUsersCache = new HashMap<>();
-                       }
+               groupUsersCache = gson.fromJson(response, Map.class);
+               if (MapUtils.isEmpty(groupUsersCache)) {
+                       groupUsersCache = new HashMap<>();
+               }
 
-                       if (LOG.isDebugEnabled()) {
-                               LOG.debug("Group User List : " + 
groupUsersCache.values());
-                       }
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("Group User List : " + 
groupUsersCache.values());
+               }
                if (LOG.isDebugEnabled()) {
                        LOG.debug("<== 
PolicyMgrUserGroupBuilder.buildGroupUserLinkList()");
                }
@@ -548,27 +589,42 @@ private static final Logger LOG = 
Logger.getLogger(PolicyMgrUserGroupBuilder.cla
                deltaGroups = new HashMap<>();
                // Check if the group exists in cache. If not, mark as new 
group.
                // else check if other attributes are updated and mark as 
updated group
-
+               Gson gson = new Gson();
                for (String groupDN : sourceGroups.keySet()) {
                        Map<String, String> newGroupAttrs = 
sourceGroups.get(groupDN);
-                       Gson gson = new Gson();
                        String newGroupAttrsStr = gson.toJson(newGroupAttrs);
                        String groupName = groupNameMap.get(groupDN);
                        if (StringUtils.isEmpty(groupName)) {
-                               groupName = 
groupNameTransform(newGroupAttrs.get("original_name"));
-                               groupNameMap.put(groupDN, groupName);
+                               groupName = 
groupNameTransform(newGroupAttrs.get(UgsyncCommonConstants.ORIGINAL_NAME));
+                               if (StringUtils.isNotEmpty(groupName) && 
!groupNameMap.containsValue(groupName)) {
+                                       // This is to avoid updating same 
groupName with different DN that already exists
+                                       groupNameMap.put(groupDN, groupName);
+                               }
                        }
                        if (!groupCache.containsKey(groupName)) {
-                               XGroupInfo newGroup = addXGroupInfo(groupName, 
newGroupAttrsStr);
+                               XGroupInfo newGroup = addXGroupInfo(groupName, 
newGroupAttrs, newGroupAttrsStr);
                                deltaGroups.put(groupName, newGroup);
                                noOfNewGroups++;
                        } else {
                                XGroupInfo oldGroup = groupCache.get(groupName);
-                               String oldGroupAttrs = 
oldGroup.getOtherAttributes();
-                               if 
(!StringUtils.equalsIgnoreCase(oldGroupAttrs, newGroupAttrsStr)) {
-                                       
oldGroup.setOtherAttributes(newGroupAttrsStr);
-                                       deltaGroups.put(groupName, oldGroup);
-                                       noOfModifiedGroups++;
+                               Map<String, String> oldGroupAttrs = 
oldGroup.getOtherAttrsMap();
+                               String oldGroupDN = 
oldGroupAttrs.get(UgsyncCommonConstants.FULL_NAME);
+                               //LOG.info("DN from source = " + groupDN + " 
saved DN = " + oldGroupDN);
+                               //LOG.info("OldGroupAttr = " + oldGroupAttrs + 
" newGroupAttrs = " + newGroupAttrs);
+                               if (StringUtils.equalsIgnoreCase(groupDN, 
oldGroupDN)
+                                               && 
StringUtils.equalsIgnoreCase(oldGroupAttrs.get(UgsyncCommonConstants.SYNC_SOURCE),
 newGroupAttrs.get(UgsyncCommonConstants.SYNC_SOURCE))
+                                               && 
StringUtils.equalsIgnoreCase(oldGroupAttrs.get(UgsyncCommonConstants.LDAP_URL), 
newGroupAttrs.get(UgsyncCommonConstants.LDAP_URL))) {
+                                       String oldGroupAttrsStr = 
gson.toJson(oldGroupAttrs);
+                                       
if(!StringUtils.equalsIgnoreCase(oldGroupAttrsStr, newGroupAttrsStr)) {
+                                               
oldGroup.setOtherAttributes(newGroupAttrsStr);
+                                               
oldGroup.setOtherAttrsMap(newGroupAttrs);
+                                               deltaGroups.put(groupName, 
oldGroup);
+                                               noOfModifiedGroups++;
+                                       }
+                               } else {
+                                       if (LOG.isDebugEnabled()) {
+                                               LOG.debug("Skipping to update " 
+ groupName + " as same group name with different DN already exists");
+                                       }
                                }
                        }
                }
@@ -584,31 +640,42 @@ private static final Logger LOG = 
Logger.getLogger(PolicyMgrUserGroupBuilder.cla
                deltaUsers = new HashMap<>();
                // Check if the user exists in cache. If not, mark as new user.
                // else check if other attributes are updated and mark as 
updated user
-
+               Gson gson = new Gson();
                for (String userDN : sourceUsers.keySet()) {
                        Map<String, String> newUserAttrs = 
sourceUsers.get(userDN);
-                       Gson gson = new Gson();
                        String newUserAttrsStr = gson.toJson(newUserAttrs);
-
                        String userName = userNameMap.get(userDN);
                        if (StringUtils.isEmpty(userName)) {
-                               userName = 
userNameTransform(newUserAttrs.get("original_name"));
-                               userNameMap.put(userDN, userName);
+                               userName = 
userNameTransform(newUserAttrs.get(UgsyncCommonConstants.ORIGINAL_NAME));
+                               if (StringUtils.isNotEmpty(userName) && 
!userNameMap.containsValue(userName)) {
+                                       // This is to avoid updating same 
username with different DN that already exists
+                                       userNameMap.put(userDN, userName);
+                               }
                        }
 
                        if (!userCache.containsKey(userName)) {
 
-                               XUserInfo newUser = addXUserInfo(userName, 
newUserAttrsStr);
+                               XUserInfo newUser = addXUserInfo(userName, 
newUserAttrs, newUserAttrsStr);
                                deltaUsers.put(userName, newUser);
                                noOfNewUsers++;
                        } else {
-                               // Update other attributes if changed
                                XUserInfo oldUser = userCache.get(userName);
-                               String oldUserAttrs = 
oldUser.getOtherAttributes();
-                               if (!StringUtils.equalsIgnoreCase(oldUserAttrs, 
newUserAttrsStr)) {
-                                       
oldUser.setOtherAttributes(newUserAttrsStr);
-                                       deltaUsers.put(userName, oldUser);
-                                       noOfModifiedUsers++;
+                               Map<String, String> oldUserAttrs = 
oldUser.getOtherAttrsMap();
+                               String oldUserDN = 
oldUserAttrs.get(UgsyncCommonConstants.FULL_NAME);
+                               if (StringUtils.equalsIgnoreCase(userDN, 
oldUserDN)
+                                               && 
StringUtils.equalsIgnoreCase(oldUserAttrs.get(UgsyncCommonConstants.SYNC_SOURCE),
 newUserAttrs.get(UgsyncCommonConstants.SYNC_SOURCE))
+                                               && 
StringUtils.equalsIgnoreCase(oldUserAttrs.get(UgsyncCommonConstants.LDAP_URL), 
newUserAttrs.get(UgsyncCommonConstants.LDAP_URL))) {
+                                       String oldUserAttrsStr = 
gson.toJson(oldUserAttrs);
+                                       if( 
!StringUtils.equalsIgnoreCase(oldUserAttrsStr, newUserAttrsStr)) {
+                                               
oldUser.setOtherAttributes(newUserAttrsStr);
+                                               
oldUser.setOtherAttrsMap(newUserAttrs);
+                                               deltaUsers.put(userName, 
oldUser);
+                                               noOfModifiedUsers++;
+                                       }
+                               } else {
+                                       if (LOG.isDebugEnabled()) {
+                                               LOG.debug("Skipping to update " 
+ userName + " as same username with different DN already exists");
+                                       }
                                }
                        }
                }
@@ -691,12 +758,13 @@ private static final Logger LOG = 
Logger.getLogger(PolicyMgrUserGroupBuilder.cla
                return deltaGroupUserInfoList;
        }
 
-       private XUserInfo addXUserInfo(String aUserName, String 
otherAttributes) {
+       private XUserInfo addXUserInfo(String aUserName, Map<String, String> 
otherAttrsMap, String otherAttributes) {
                XUserInfo xuserInfo = new XUserInfo();
                xuserInfo.setName(aUserName);
                xuserInfo.setDescription(aUserName + " - add from Unix box");
                xuserInfo.setUserSource(SOURCE_EXTERNAL);
                xuserInfo.setStatus(STATUS_ENABLED);
+               xuserInfo.setIsVisible(ISVISIBLE);
                List<String> roleList = new ArrayList<String>();
                if (userMap.containsKey(aUserName)) {
                        roleList.add(userMap.get(aUserName));
@@ -705,12 +773,13 @@ private static final Logger LOG = 
Logger.getLogger(PolicyMgrUserGroupBuilder.cla
                }
                xuserInfo.setUserRoleList(roleList);
                xuserInfo.setOtherAttributes(otherAttributes);
+               xuserInfo.setOtherAttrsMap(otherAttrsMap);
 
                return xuserInfo;
        }
 
 
-       private XGroupInfo addXGroupInfo(String aGroupName, String 
otherAttributes) {
+       private XGroupInfo addXGroupInfo(String aGroupName, Map<String, String> 
otherAttrsMap, String otherAttributes) {
 
                XGroupInfo addGroup = new XGroupInfo();
 
@@ -719,9 +788,10 @@ private static final Logger LOG = 
Logger.getLogger(PolicyMgrUserGroupBuilder.cla
                addGroup.setDescription(aGroupName + " - add from Unix box");
 
                addGroup.setGroupType("1");
-
+               addGroup.setIsVisible(ISVISIBLE);
                addGroup.setGroupSource(SOURCE_EXTERNAL);
                addGroup.setOtherAttributes(otherAttributes);
+               addGroup.setOtherAttrsMap(otherAttrsMap);
 
                return addGroup;
        }
@@ -817,7 +887,7 @@ private static final Logger LOG = 
Logger.getLogger(PolicyMgrUserGroupBuilder.cla
                                }
                        } else {
                                LOG.error("Failed to addOrUpdateUsers " + 
uploadedCount );
-                               throw new Exception("Failed to addOrUpdateUsers 
" + uploadedCount);
+                               throw new Exception("Failed to 
addOrUpdateUsers" + uploadedCount);
                        }
                        LOG.info("ret = " + ret + " No. of users uploaded to 
ranger admin= " + (uploadedCount>totalCount?totalCount:uploadedCount));
                }
@@ -1270,7 +1340,7 @@ private static final Logger LOG = 
Logger.getLogger(PolicyMgrUserGroupBuilder.cla
                String jsonString = gson.toJson(obj);
 
                if ( LOG.isDebugEnabled() ) {
-                  LOG.debug("USER GROUP MAPPING" + jsonString);
+                       LOG.debug("USER GROUP MAPPING" + jsonString);
                }
                try{
                        clientResp = ldapUgSyncClient.post(apiURL, null, obj);
@@ -1408,74 +1478,74 @@ private static final Logger LOG = 
Logger.getLogger(PolicyMgrUserGroupBuilder.cla
                return response;
        }
 
-    private void getRoleForUserGroups(String userGroupRolesData) {
-        String roleDelimiter = config.getRoleDelimiter();
-        String userGroupDelimiter = config.getUserGroupDelimiter();
-        String userNameDelimiter = config.getUserGroupNameDelimiter();
-        if (roleDelimiter == null || roleDelimiter.isEmpty()) {
-            roleDelimiter = "&";
-        }
-        if (userGroupDelimiter == null || userGroupDelimiter.isEmpty()) {
-            userGroupDelimiter = ":";
-        }
-        if (userNameDelimiter == null || userNameDelimiter.isEmpty()) {
-            userNameDelimiter = ",";
-        }
-        StringTokenizer str = new StringTokenizer(userGroupRolesData,
-                roleDelimiter);
-        int flag = 0;
-        String userGroupCheck = null;
-        String roleName = null;
-        while (str.hasMoreTokens()) {
-            flag = 0;
-            String tokens = str.nextToken();
-            if (tokens != null && !tokens.isEmpty()) {
-                StringTokenizer userGroupRoles = new StringTokenizer(tokens,
-                        userGroupDelimiter);
-                if (userGroupRoles != null) {
-                    while (userGroupRoles.hasMoreElements()) {
-                        String userGroupRolesTokens = userGroupRoles
-                                .nextToken();
-                        if (userGroupRolesTokens != null
-                                && !userGroupRolesTokens.isEmpty()) {
-                            flag++;
-                            switch (flag) {
-                            case 1:
-                                roleName = userGroupRolesTokens;
-                                break;
-                            case 2:
-                                userGroupCheck = userGroupRolesTokens;
-                                break;
-                            case 3:
-                                StringTokenizer userGroupNames = new 
StringTokenizer(
-                                        userGroupRolesTokens, 
userNameDelimiter);
-                                if (userGroupNames != null) {
-                                    while (userGroupNames.hasMoreElements()) {
-                                        String userGroup = userGroupNames
-                                                .nextToken();
-                                        if (userGroup != null
-                                                && !userGroup.isEmpty()) {
-                                            if 
(userGroupCheck.trim().equalsIgnoreCase("u")) {
-                                                userMap.put(userGroup.trim(), 
roleName.trim());
-                                            } else if 
(userGroupCheck.trim().equalsIgnoreCase("g")) {
-                                                groupMap.put(userGroup.trim(),
-                                                        roleName.trim());
-                                            }
-                                        }
-                                    }
-                                }
-                                break;
-                            default:
-                                userMap.clear();
-                                groupMap.clear();
-                                break;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
+       private void getRoleForUserGroups(String userGroupRolesData) {
+               String roleDelimiter = config.getRoleDelimiter();
+               String userGroupDelimiter = config.getUserGroupDelimiter();
+               String userNameDelimiter = config.getUserGroupNameDelimiter();
+               if (roleDelimiter == null || roleDelimiter.isEmpty()) {
+                       roleDelimiter = "&";
+               }
+               if (userGroupDelimiter == null || userGroupDelimiter.isEmpty()) 
{
+                       userGroupDelimiter = ":";
+               }
+               if (userNameDelimiter == null || userNameDelimiter.isEmpty()) {
+                       userNameDelimiter = ",";
+               }
+               StringTokenizer str = new StringTokenizer(userGroupRolesData,
+                               roleDelimiter);
+               int flag = 0;
+               String userGroupCheck = null;
+               String roleName = null;
+               while (str.hasMoreTokens()) {
+                       flag = 0;
+                       String tokens = str.nextToken();
+                       if (tokens != null && !tokens.isEmpty()) {
+                               StringTokenizer userGroupRoles = new 
StringTokenizer(tokens,
+                                               userGroupDelimiter);
+                               if (userGroupRoles != null) {
+                                       while 
(userGroupRoles.hasMoreElements()) {
+                                               String userGroupRolesTokens = 
userGroupRoles
+                                                               .nextToken();
+                                               if (userGroupRolesTokens != null
+                                                               && 
!userGroupRolesTokens.isEmpty()) {
+                                                       flag++;
+                                                       switch (flag) {
+                                                               case 1:
+                                                                       
roleName = userGroupRolesTokens;
+                                                                       break;
+                                                               case 2:
+                                                                       
userGroupCheck = userGroupRolesTokens;
+                                                                       break;
+                                                               case 3:
+                                                                       
StringTokenizer userGroupNames = new StringTokenizer(
+                                                                               
        userGroupRolesTokens, userNameDelimiter);
+                                                                       if 
(userGroupNames != null) {
+                                                                               
while (userGroupNames.hasMoreElements()) {
+                                                                               
        String userGroup = userGroupNames
+                                                                               
                        .nextToken();
+                                                                               
        if (userGroup != null
+                                                                               
                        && !userGroup.isEmpty()) {
+                                                                               
                if (userGroupCheck.trim().equalsIgnoreCase("u")) {
+                                                                               
                        userMap.put(userGroup.trim(), roleName.trim());
+                                                                               
                } else if (userGroupCheck.trim().equalsIgnoreCase("g")) {
+                                                                               
                        groupMap.put(userGroup.trim(),
+                                                                               
                                        roleName.trim());
+                                                                               
                }
+                                                                               
        }
+                                                                               
}
+                                                                       }
+                                                                       break;
+                                                               default:
+                                                                       
userMap.clear();
+                                                                       
groupMap.clear();
+                                                                       break;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
 
        protected String userNameTransform(String userName) {
                if (userNameCaseConversionFlag) {
@@ -1511,4 +1581,232 @@ private static final Logger LOG = 
Logger.getLogger(PolicyMgrUserGroupBuilder.cla
                return groupName;
        }
 
+       private void updateDeletedGroups(Map<String, Map<String, String>> 
sourceGroups) throws Throwable {
+               computeDeletedGroups(sourceGroups);
+               if (MapUtils.isNotEmpty(deletedGroups)) {
+                       if (updateDeletedGroups() == 0) {
+                               String msg = "Failed to update deleted groups 
to ranger admin";
+                               LOG.error(msg);
+                               throw new Exception(msg);
+                       }
+               }
+       }
+
+       private void computeDeletedGroups(Map<String, Map<String, String>> 
sourceGroups) {
+               if (LOG.isDebugEnabled()) {
+                       
LOG.debug("PolicyMgrUserGroupBuilder.computeDeletedGroups(" + 
sourceGroups.keySet() + ")");
+               }
+               deletedGroups = new HashMap<>();
+               // Check if the group from cache exists in the sourceGroups. If 
not, mark as deleted group.
+               for (XGroupInfo groupInfo : groupCache.values()) {
+                       Map<String, String> groupOtherAttrs = 
groupInfo.getOtherAttrsMap();
+                       String groupDN = groupOtherAttrs != null ? 
groupOtherAttrs.get(UgsyncCommonConstants.FULL_NAME) : null;
+                       if (StringUtils.isNotEmpty(groupDN) && 
!sourceGroups.containsKey(groupDN)
+                                       && 
StringUtils.equalsIgnoreCase(groupOtherAttrs.get(UgsyncCommonConstants.SYNC_SOURCE),
 currentSyncSource)
+                                       && 
StringUtils.equalsIgnoreCase(groupOtherAttrs.get(UgsyncCommonConstants.LDAP_URL),
 ldapUrl)) {
+                               groupInfo.setIsVisible(ISHIDDEN);
+                               deletedGroups.put(groupInfo.getName(), 
groupInfo);
+                       }
+               }
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("<== 
PolicyMgrUserGroupBuilder.computeDeletedGroups(" + deletedGroups + ")");
+               }
+       }
+
+       private int updateDeletedGroups() throws Throwable{
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("==> 
PolicyMgrUserGroupBuilder.updateDeletedGroups(" + deletedGroups + ")");
+               }
+               int ret = 0;
+
+               if (authenticationType != null
+                               && 
AUTH_KERBEROS.equalsIgnoreCase(authenticationType)
+                               && 
SecureClientLogin.isKerberosCredentialExists(principal,
+                               keytab)) {
+                       try {
+                               Subject sub = 
SecureClientLogin.loginUserFromKeytab(principal, keytab, nameRules);
+                               ret = Subject.doAs(sub, new 
PrivilegedAction<Integer>() {
+                                       @Override
+                                       public Integer run() {
+                                               try {
+                                                       return 
getDeletedGroups();
+                                               } catch (Throwable e) {
+                                                       LOG.error("Failed to 
add or update deleted groups : ", e);
+                                               }
+                                               return 0;
+                                       }
+                               });
+                       } catch (Exception e) {
+                               LOG.error("Failed to add or update deleted 
groups : " , e);
+                               throw e;
+                       }
+               } else {
+                       ret = getDeletedGroups();
+               }
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("<== 
PolicyMgrUserGroupBuilder.updateDeletedGroups(" + deletedGroups + ")");
+               }
+               return ret;
+       }
+
+
+       private int getDeletedGroups() throws Throwable{
+               if(LOG.isDebugEnabled()){
+                       LOG.debug("==> 
PolicyMgrUserGroupBuilder.getDeletedGroups()");
+               }
+               int ret = 0;
+               String response = null;
+               ClientResponse clientRes = null;
+               String relativeUrl = PM_UPDATE_DELETED_GROUPS_URI;
+
+               if(isRangerCookieEnabled){
+                       response = 
cookieBasedUploadEntity(deletedGroups.keySet(), relativeUrl);
+               }
+               else {
+                       try {
+                               clientRes = ldapUgSyncClient.post(relativeUrl, 
null, deletedGroups.keySet());
+                               if (clientRes != null) {
+                                       response = 
clientRes.getEntity(String.class);
+                               }
+                       }
+                       catch(Throwable t){
+                               LOG.error("Failed to get response, Error is : 
", t);
+                       }
+               }
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("RESPONSE[" + response + "]");
+               }
+               if (response != null) {
+                       try {
+                               ret = Integer.valueOf(response);
+                       } catch (NumberFormatException e) {
+                               LOG.error("Failed to update deleted groups", e 
);
+                               throw e;
+                       }
+               } else {
+                       LOG.error("Failed to update deleted groups ");
+                       throw new Exception("Failed to update deleted groups ");
+               }
+
+               if(LOG.isDebugEnabled()){
+                       LOG.debug("<== 
PolicyMgrUserGroupBuilder.getDeletedGroups()" + ret);
+               }
+
+               return ret;
+       }
+
+
+       private void updateDeletedUsers(Map<String, Map<String, String>> 
sourceUsers) throws Throwable {
+               computeDeletedUsers(sourceUsers);
+               if (MapUtils.isNotEmpty(deletedUsers)) {
+                       if (updateDeletedUsers() == 0) {
+                               String msg = "Failed to update deleted users to 
ranger admin";
+                               LOG.error(msg);
+                               throw new Exception(msg);
+                       }
+               }
+       }
+
+       private void computeDeletedUsers(Map<String, Map<String, String>> 
sourceUsers) {
+               if (LOG.isDebugEnabled()) {
+                       
LOG.debug("PolicyMgrUserGroupBuilder.computeDeletedUsers(" + 
sourceUsers.keySet() + ")");
+               }
+               deletedUsers = new HashMap<>();
+               // Check if the group from cache exists in the sourceGroups. If 
not, mark as deleted group.
+               for (XUserInfo userInfo : userCache.values()) {
+                       Map<String, String> userOtherAttrs = 
userInfo.getOtherAttrsMap();
+                       String userDN = userOtherAttrs != null ? 
userOtherAttrs.get(UgsyncCommonConstants.FULL_NAME) : null;
+                       if (StringUtils.isNotEmpty(userDN) && 
!sourceUsers.containsKey(userDN)
+                                       && 
StringUtils.equalsIgnoreCase(userOtherAttrs.get(UgsyncCommonConstants.SYNC_SOURCE),
 currentSyncSource)
+                                       && 
StringUtils.equalsIgnoreCase(userOtherAttrs.get(UgsyncCommonConstants.LDAP_URL),
 ldapUrl)) {
+                               userInfo.setIsVisible(ISHIDDEN);
+                               deletedUsers.put(userInfo.getName(), userInfo);
+                       }
+               }
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("<== 
PolicyMgrUserGroupBuilder.computeDeletedUsers(" + deletedUsers + ")");
+               }
+       }
+
+       private int updateDeletedUsers() throws Throwable{
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("==> 
PolicyMgrUserGroupBuilder.updateDeletedUsers(" + deletedUsers + ")");
+               }
+               int ret = 0;
+
+               if (authenticationType != null
+                               && 
AUTH_KERBEROS.equalsIgnoreCase(authenticationType)
+                               && 
SecureClientLogin.isKerberosCredentialExists(principal,
+                               keytab)) {
+                       try {
+                               Subject sub = 
SecureClientLogin.loginUserFromKeytab(principal, keytab, nameRules);
+                               ret = Subject.doAs(sub, new 
PrivilegedAction<Integer>() {
+                                       @Override
+                                       public Integer run() {
+                                               try {
+                                                       return 
getDeletedUsers();
+                                               } catch (Throwable e) {
+                                                       LOG.error("Failed to 
add or update deleted users : ", e);
+                                               }
+                                               return 0;
+                                       }
+                               });
+                       } catch (Exception e) {
+                               LOG.error("Failed to add or update deleted 
users : " , e);
+                               throw e;
+                       }
+               } else {
+                       ret = getDeletedUsers();
+               }
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("<== 
PolicyMgrUserGroupBuilder.updateDeletedUsers(" + deletedUsers + ")");
+               }
+               return ret;
+       }
+
+
+       private int getDeletedUsers() throws Throwable{
+               if(LOG.isDebugEnabled()){
+                       LOG.debug("==> 
PolicyMgrUserGroupBuilder.getDeletedUsers()");
+               }
+               int ret = 0;
+               String response = null;
+               ClientResponse clientRes = null;
+               String relativeUrl = PM_UPDATE_DELETED_USERS_URI;
+
+               if(isRangerCookieEnabled){
+                       response = 
cookieBasedUploadEntity(deletedUsers.keySet(), relativeUrl);
+               }
+               else {
+                       try {
+                               clientRes = ldapUgSyncClient.post(relativeUrl, 
null, deletedUsers.keySet());
+                               if (clientRes != null) {
+                                       response = 
clientRes.getEntity(String.class);
+                               }
+                       }
+                       catch(Throwable t){
+                               LOG.error("Failed to get response, Error is : 
", t);
+                       }
+               }
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("RESPONSE[" + response + "]");
+               }
+               if (response != null) {
+                       try {
+                               ret = Integer.valueOf(response);
+                       } catch (NumberFormatException e) {
+                               LOG.error("Failed to update deleted users", e );
+                               throw e;
+                       }
+               } else {
+                       LOG.error("Failed to update deleted users ");
+                       throw new Exception("Failed to update deleted users ");
+               }
+
+               if(LOG.isDebugEnabled()){
+                       LOG.debug("<== 
PolicyMgrUserGroupBuilder.getDeletedUsers()" + ret);
+               }
+
+               return ret;
+       }
 }
diff --git 
a/ugsync/src/main/java/org/apache/ranger/unixusersync/process/UnixUserGroupBuilder.java
 
b/ugsync/src/main/java/org/apache/ranger/unixusersync/process/UnixUserGroupBuilder.java
index 597cbf8..b33812e 100644
--- 
a/ugsync/src/main/java/org/apache/ranger/unixusersync/process/UnixUserGroupBuilder.java
+++ 
b/ugsync/src/main/java/org/apache/ranger/unixusersync/process/UnixUserGroupBuilder.java
@@ -40,12 +40,13 @@ import com.google.common.collect.Table;
 import org.apache.log4j.Logger;
 import org.apache.ranger.ugsyncutil.model.UgsyncAuditInfo;
 import org.apache.ranger.ugsyncutil.model.UnixSyncSourceInfo;
+import org.apache.ranger.ugsyncutil.util.UgsyncCommonConstants;
 import org.apache.ranger.unixusersync.config.UserGroupSyncConfig;
 import org.apache.ranger.usergroupsync.UserGroupSink;
 import org.apache.ranger.usergroupsync.UserGroupSource;
 
 public class UnixUserGroupBuilder implements UserGroupSource {
-       
+
        private static final Logger LOG = 
Logger.getLogger(UnixUserGroupBuilder.class);
        private final static String OS = System.getProperty("os.name");
 
@@ -96,6 +97,9 @@ public class UnixUserGroupBuilder implements UserGroupSource {
        private UgsyncAuditInfo ugsyncAuditInfo;
        private UnixSyncSourceInfo unixSyncSourceInfo;
        private boolean isStartupFlag = false;
+       private int deleteCycles;
+       private String currentSyncSource;
+       private boolean computeDeletes = false;
        Set<String> allGroups = new HashSet<>();
 
 
@@ -104,20 +108,13 @@ public class UnixUserGroupBuilder implements 
UserGroupSource {
                ugbuilder.init();
                ugbuilder.print();
        }
-       
+
        public UnixUserGroupBuilder() {
                isStartupFlag = true;
                minimumUserId = Integer.parseInt(config.getMinUserId());
                minimumGroupId = Integer.parseInt(config.getMinGroupId());
                unixPasswordFile = config.getUnixPasswordFile();
                unixGroupFile = config.getUnixGroupFile();
-               ugsyncAuditInfo = new UgsyncAuditInfo();
-               unixSyncSourceInfo = new UnixSyncSourceInfo();
-               ugsyncAuditInfo.setSyncSource("Unix");
-               ugsyncAuditInfo.setUnixSyncSourceInfo(unixSyncSourceInfo);
-               unixSyncSourceInfo.setFileName(unixPasswordFile);
-               unixSyncSourceInfo.setMinUserId(config.getMinUserId());
-               unixSyncSourceInfo.setMinGroupId(config.getMinGroupId());
 
                if (LOG.isDebugEnabled()) {
                        LOG.debug("Minimum UserId: " + minimumUserId + ", 
minimum GroupId: " + minimumGroupId);
@@ -126,6 +123,21 @@ public class UnixUserGroupBuilder implements 
UserGroupSource {
                timeout = config.getUpdateMillisMin();
                enumerateGroupMembers = config.isGroupEnumerateEnabled();
 
+       }
+
+       @Override
+       public void init() throws Throwable {
+               deleteCycles = 1;
+
+               currentSyncSource = config.getCurrentSyncSource();
+
+               ugsyncAuditInfo = new UgsyncAuditInfo();
+               unixSyncSourceInfo = new UnixSyncSourceInfo();
+               ugsyncAuditInfo.setSyncSource(currentSyncSource);
+               ugsyncAuditInfo.setUnixSyncSourceInfo(unixSyncSourceInfo);
+               unixSyncSourceInfo.setFileName(unixPasswordFile);
+               unixSyncSourceInfo.setMinUserId(config.getMinUserId());
+               unixSyncSourceInfo.setMinGroupId(config.getMinGroupId());
                if (!config.getUnixBackend().equalsIgnoreCase(BACKEND_PASSWD)) {
                        useNss = true;
                        unixSyncSourceInfo.setUnixBackend("nss");
@@ -134,23 +146,34 @@ public class UnixUserGroupBuilder implements 
UserGroupSource {
                                        "instead of standard system 
mechanisms.");
                        unixSyncSourceInfo.setUnixBackend(BACKEND_PASSWD);
                }
-
-       }
-
-       @Override
-       public void init() throws Throwable {
                buildUserGroupInfo();
        }
 
        @Override
        public boolean isChanged() {
-               // If previous update to Ranger admin fails, 
+               computeDeletes = false;
+               // If previous update to Ranger admin fails,
                // we want to retry the sync process even if there are no 
changes to the sync files
                if (!isUpdateSinkSucc) {
                        LOG.info("Previous updateSink failed and hence 
retry!!");
                        return true;
                }
-               
+               try {
+                       if (config.isUserSyncDeletesEnabled() && deleteCycles 
>= config.getUserSyncDeletesFrequency()) {
+                               deleteCycles = 1;
+                               computeDeletes = true;
+                               if (LOG.isDebugEnabled()) {
+                                       LOG.debug("Compute deleted users/groups 
is enabled for this sync cycle");
+                               }
+                               return true;
+                       }
+               } catch (Throwable t) {
+                       LOG.error("Failed to get information about usersync 
delete frequency", t);
+               }
+               if (config.isUserSyncDeletesEnabled()) {
+                       deleteCycles++;
+               }
+
                if (useNss)
                        return System.currentTimeMillis() - lastUpdateTime > 
timeout;
 
@@ -185,7 +208,7 @@ public class UnixUserGroupBuilder implements 
UserGroupSource {
                        }
 
                        try {
-                               sink.addOrUpdateUsersGroups(sourceGroups, 
sourceUsers, sourceGroupUsers);
+                               sink.addOrUpdateUsersGroups(sourceGroups, 
sourceUsers, sourceGroupUsers, computeDeletes);
                        } catch (Throwable t) {
                                LOG.error("Failed to update ranger admin. Will 
retry in next sync cycle!!", t);
                                isUpdateSinkSucc = false;
@@ -198,8 +221,8 @@ public class UnixUserGroupBuilder implements 
UserGroupSource {
                }
                isStartupFlag = false;
        }
-       
-       
+
+
        private void buildUserGroupInfo() throws Throwable {
                groupId2groupNameMap = new HashMap<String, String>();
                sourceUsers = new HashMap<>();
@@ -239,7 +262,7 @@ public class UnixUserGroupBuilder implements 
UserGroupSource {
                        print();
                }
        }
-       
+
        private void print() {
                for(String user : sourceUsers.keySet()) {
                        if (LOG.isDebugEnabled()) {
@@ -255,7 +278,7 @@ public class UnixUserGroupBuilder implements 
UserGroupSource {
                        }
                }
        }
-       
+
        private void buildUnixUserList(String command) throws Throwable {
                BufferedReader reader = null;
                Map<String, String> userName2uid = new HashMap<String, 
String>();
@@ -316,8 +339,9 @@ public class UnixUserGroupBuilder implements 
UserGroupSource {
                                        String groupName = 
groupId2groupNameMap.get(groupId);
                                        if (groupName != null) {
                                                Map<String, String> userAttrMap 
= new HashMap<>();
-                                               
userAttrMap.put("original_name", userName);
-                                               userAttrMap.put("full_name", 
userName);
+                                               
userAttrMap.put(UgsyncCommonConstants.ORIGINAL_NAME, userName);
+                                               
userAttrMap.put(UgsyncCommonConstants.FULL_NAME, userName);
+                                               
userAttrMap.put(UgsyncCommonConstants.SYNC_SOURCE, currentSyncSource);
                                                sourceUsers.put(userName, 
userAttrMap);
                                                groupUserTable.put(groupName, 
userName, groupId);
                                        } else {
@@ -403,8 +427,9 @@ public class UnixUserGroupBuilder implements 
UserGroupSource {
                                        }
                                }
                                Map<String, String> userAttrMap = new 
HashMap<>();
-                               userAttrMap.put("original_name", userName);
-                               userAttrMap.put("full_name", userName);
+                               
userAttrMap.put(UgsyncCommonConstants.ORIGINAL_NAME, userName);
+                               
userAttrMap.put(UgsyncCommonConstants.FULL_NAME, userName);
+                               
userAttrMap.put(UgsyncCommonConstants.SYNC_SOURCE, currentSyncSource);
                                sourceUsers.put(userName, userAttrMap);
                        }
                        if (LOG.isDebugEnabled()) {
@@ -439,8 +464,9 @@ public class UnixUserGroupBuilder implements 
UserGroupSource {
 
                groupId2groupNameMap.put(groupId, groupName);
                Map<String, String> groupAttrMap = new HashMap<>();
-               groupAttrMap.put("original_name", groupName);
-               groupAttrMap.put("full_name", groupName);
+               groupAttrMap.put(UgsyncCommonConstants.ORIGINAL_NAME, 
groupName);
+               groupAttrMap.put(UgsyncCommonConstants.FULL_NAME, groupName);
+               groupAttrMap.put(UgsyncCommonConstants.SYNC_SOURCE, 
currentSyncSource);
                sourceGroups.put(groupName, groupAttrMap);
 
                if (groupMembers != null && !groupMembers.trim().isEmpty()) {
diff --git 
a/ugsync/src/main/java/org/apache/ranger/usergroupsync/UserGroupSink.java 
b/ugsync/src/main/java/org/apache/ranger/usergroupsync/UserGroupSink.java
index 794bc81..e79fcf7 100644
--- a/ugsync/src/main/java/org/apache/ranger/usergroupsync/UserGroupSink.java
+++ b/ugsync/src/main/java/org/apache/ranger/usergroupsync/UserGroupSink.java
@@ -31,6 +31,7 @@ public interface UserGroupSink {
 
        void addOrUpdateUsersGroups(Map<String, Map<String, String>> 
sourceGroups,
                                                                Map<String, 
Map<String, String>> sourceUsers,
-                                                               Map<String, 
Set<String>> sourceGroupUsers) throws Throwable;
+                                                               Map<String, 
Set<String>> sourceGroupUsers,
+                                                               boolean 
computeDeletes) throws Throwable;
 
 }
diff --git 
a/ugsync/src/test/java/org/apache/ranger/usergroupsync/PolicyMgrUserGroupBuilderTest.java
 
b/ugsync/src/test/java/org/apache/ranger/usergroupsync/PolicyMgrUserGroupBuilderTest.java
index 5d2e62c..4fb6b6c 100644
--- 
a/ugsync/src/test/java/org/apache/ranger/usergroupsync/PolicyMgrUserGroupBuilderTest.java
+++ 
b/ugsync/src/test/java/org/apache/ranger/usergroupsync/PolicyMgrUserGroupBuilderTest.java
@@ -72,7 +72,8 @@ public class PolicyMgrUserGroupBuilderTest extends 
PolicyMgrUserGroupBuilder {
         @Override
         public void addOrUpdateUsersGroups(Map<String, Map<String, String>> 
sourceGroups,
                                            Map<String, Map<String, String>> 
sourceUsers,
-                                           Map<String, Set<String>> 
sourceGroupUsers) throws Throwable {
+                                           Map<String, Set<String>> 
sourceGroupUsers,
+                                           boolean computeDeletes) throws 
Throwable {
 
                 for (String userdn : sourceUsers.keySet()) {
                         //System.out.println("Username: " + 
sourceUsers.get(userdn).get("original_name"));

Reply via email to