Ranger-684: Added support for Ranger Usersync to transform AD usernames and/or 
group names to linux compliant format

Signed-off-by: Velmurugan Periasamy <[email protected]>


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

Branch: refs/heads/master
Commit: a57740e277bf777e78cc0807349a9bcd96a80f3e
Parents: f1135ea
Author: Sailaja Polavarapu <[email protected]>
Authored: Wed Oct 28 13:14:24 2015 -0700
Committer: Velmurugan Periasamy <[email protected]>
Committed: Fri Oct 30 18:32:07 2015 -0400

----------------------------------------------------------------------
 ugsync/pom.xml                                  |  5 ++
 .../process/LdapUserGroupBuilder.java           | 50 +++++++++++
 .../config/UserGroupSyncConfig.java             | 47 +++++++++++
 .../ranger/usergroupsync/AbstractMapper.java    | 40 +++++++++
 .../org/apache/ranger/usergroupsync/Mapper.java | 26 ++++++
 .../org/apache/ranger/usergroupsync/RegEx.java  | 83 ++++++++++++++++++
 .../apache/ranger/usergroupsync/RegExTest.java  | 89 ++++++++++++++++++++
 7 files changed, 340 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/a57740e2/ugsync/pom.xml
----------------------------------------------------------------------
diff --git a/ugsync/pom.xml b/ugsync/pom.xml
index c72eeee..d0ecb2f 100644
--- a/ugsync/pom.xml
+++ b/ugsync/pom.xml
@@ -105,6 +105,11 @@
         <version>${project.version}</version>
       </dependency>
 
+         <dependency>
+               <groupId>junit</groupId>
+               <artifactId>junit</artifactId>
+               <scope>test</scope>
+         </dependency>
 
     </dependencies>
 

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/a57740e2/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 63643c0..911c5d5 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
@@ -42,6 +42,7 @@ import javax.naming.ldap.PagedResultsResponseControl;
 
 import org.apache.log4j.Logger;
 import org.apache.ranger.unixusersync.config.UserGroupSyncConfig;
+import org.apache.ranger.usergroupsync.AbstractMapper;
 import org.apache.ranger.usergroupsync.UserGroupSink;
 import org.apache.ranger.usergroupsync.UserGroupSource;
 
@@ -91,6 +92,9 @@ public class LdapUserGroupBuilder implements UserGroupSource {
        private boolean groupNameLowerCaseFlag = false ;
 
   private boolean  groupUserMapSyncEnabled = false;
+  
+  AbstractMapper userNameRegExInst = null;
+  AbstractMapper groupNameRegExInst = null;
 
        public static void main(String[] args) throws Throwable {
                LdapUserGroupBuilder  ugBuilder = new LdapUserGroupBuilder();
@@ -120,6 +124,39 @@ public class LdapUserGroupBuilder implements 
UserGroupSource {
                    groupNameLowerCaseFlag = 
UserGroupSyncConfig.UGSYNC_LOWER_CASE_CONVERSION_VALUE.equalsIgnoreCase(groupNameCaseConversion)
 ;
                }
                
+               String mappingUserNameHandler = 
config.getUserSyncMappingUserNameHandler();
+               try {
+                       if (mappingUserNameHandler != null) {
+                               Class<AbstractMapper> regExClass = 
(Class<AbstractMapper>)Class.forName(mappingUserNameHandler);
+                               userNameRegExInst = regExClass.newInstance();
+                               if (userNameRegExInst != null) {
+                                       
userNameRegExInst.init(UserGroupSyncConfig.SYNC_MAPPING_USERNAME);
+                               } else {
+                                       LOG.error("RegEx handler instance for 
username is null!");
+                               }
+                       }
+               } catch (ClassNotFoundException cne) {
+                       LOG.error("Failed to load " + mappingUserNameHandler + 
" " + cne);
+               } catch (Throwable te) {
+                       LOG.error("Failed to instantiate " + 
mappingUserNameHandler + " " + te);
+               }
+
+               String mappingGroupNameHandler = 
config.getUserSyncMappingGroupNameHandler();
+               try {
+                       if (mappingGroupNameHandler != null) {
+                               Class<AbstractMapper> regExClass = 
(Class<AbstractMapper>)Class.forName(mappingGroupNameHandler);
+                               groupNameRegExInst = regExClass.newInstance();
+                               if (groupNameRegExInst != null) {
+                                       
groupNameRegExInst.init(UserGroupSyncConfig.SYNC_MAPPING_GROUPNAME);
+                               } else {
+                                       LOG.error("RegEx handler instance for 
groupname is null!");
+                               }
+                       }
+               } catch (ClassNotFoundException cne) {
+                       LOG.error("Failed to load " + mappingGroupNameHandler + 
" " + cne);
+               } catch (Throwable te) {
+                       LOG.error("Failed to instantiate " + 
mappingGroupNameHandler + " " + te);
+               }               
        }
 
        @Override
@@ -320,6 +357,10 @@ public class LdapUserGroupBuilder implements 
UserGroupSource {
                                                        userName = 
userName.toUpperCase() ;
                                                }
                                        }
+                                       
+                                       if (userNameRegExInst != null) {
+                        userName = userNameRegExInst.transform(userName);
+                                       }
 
           Set<String> groups = new HashSet<String>();
 
@@ -337,6 +378,9 @@ public class LdapUserGroupBuilder implements 
UserGroupSource {
                     gName = gName.toUpperCase();
                   }
                 }
+                if (groupNameRegExInst != null) {
+                    gName = groupNameRegExInst.transform(gName);
+                }
                 groups.add(gName);
               }
             }
@@ -361,6 +405,9 @@ public class LdapUserGroupBuilder implements 
UserGroupSource {
                     gName = gName.toUpperCase();
                   }
                 }
+                if (groupNameRegExInst != null) {
+                    gName = groupNameRegExInst.transform(gName);
+                }
                 computedGroups.add(gName);
               }
             }
@@ -453,6 +500,9 @@ public class LdapUserGroupBuilder implements 
UserGroupSource {
               gName = gName.toUpperCase();
             }
           }
+          if (groupNameRegExInst != null) {
+              gName = groupNameRegExInst.transform(gName);
+          }
           groupNames.add(gName);
         }
         if (LOG.isInfoEnabled())  {

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/a57740e2/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 c1b305b..ceeb836 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
@@ -24,7 +24,10 @@ import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Enumeration;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Properties;
 import java.util.Set;
 import java.util.StringTokenizer;
@@ -174,6 +177,17 @@ public class UserGroupSyncConfig  {
        private static final String SYNC_SOURCE = "ranger.usersync.sync.source";
        private static final String LGSYNC_REFERRAL = 
"ranger.usersync.ldap.referral";
        private static final String DEFAULT_LGSYNC_REFERRAL = "ignore";
+       
+       public static final String SYNC_MAPPING_USERNAME = 
"ranger.usersync.mapping.username.regex";
+
+    public static final String SYNC_MAPPING_GROUPNAME = 
"ranger.usersync.mapping.groupname.regex";
+
+    private static final String SYNC_MAPPING_USERNAME_HANDLER = 
"ranger.usersync.mapping.username.handler";
+    private static final String DEFAULT_SYNC_MAPPING_USERNAME_HANDLER = 
"org.apache.ranger.usergroupsync.RegEx";
+
+    private static final String SYNC_MAPPING_GROUPNAME_HANDLER = 
"ranger.usersync.mapping.groupname.handler";
+    private static final String DEFAULT_SYNC_MAPPING_GROUPNAME_HANDLER = 
"org.apache.ranger.usergroupsync.RegEx";
+    
        private Properties prop = new Properties() ;
        
        private static volatile UserGroupSyncConfig me = null ;
@@ -738,4 +752,37 @@ public class UserGroupSyncConfig  {
                }
                return referral;
        }
+       
+       public List<String> getAllRegexPatterns(String baseProperty) {
+               List<String> regexPatterns = new ArrayList<String>();
+               if (prop != null) {
+                       Enumeration<?> propertyNames = prop.propertyNames();
+                       while (propertyNames != null && 
propertyNames.hasMoreElements()) {
+                               String propertyName = 
(String)propertyNames.nextElement();
+                               if (propertyName != null && 
propertyName.contains(baseProperty)) {
+                                       
regexPatterns.add(prop.getProperty(propertyName));
+                               }
+                       }
+
+               }
+               return regexPatterns;
+       }
+
+       public String getUserSyncMappingUserNameHandler() {
+               String val =  prop.getProperty(SYNC_MAPPING_USERNAME_HANDLER) ;
+
+               if(val == null) {
+                       val = DEFAULT_SYNC_MAPPING_USERNAME_HANDLER;
+               }
+               return val;
+       }
+
+       public String getUserSyncMappingGroupNameHandler() {
+               String val =  prop.getProperty(SYNC_MAPPING_GROUPNAME_HANDLER) ;
+
+               if(val == null) {
+                       val = DEFAULT_SYNC_MAPPING_GROUPNAME_HANDLER;
+               }
+               return val;
+       }
 }

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/a57740e2/ugsync/src/main/java/org/apache/ranger/usergroupsync/AbstractMapper.java
----------------------------------------------------------------------
diff --git 
a/ugsync/src/main/java/org/apache/ranger/usergroupsync/AbstractMapper.java 
b/ugsync/src/main/java/org/apache/ranger/usergroupsync/AbstractMapper.java
new file mode 100644
index 0000000..fc5d10b
--- /dev/null
+++ b/ugsync/src/main/java/org/apache/ranger/usergroupsync/AbstractMapper.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.usergroupsync;
+
+import org.apache.log4j.Logger;
+
+public abstract class AbstractMapper implements Mapper {
+       
+       static Logger logger = Logger.getLogger(AbstractMapper.class);
+
+       @Override
+       public void init(String baseProperty) {
+               // TODO Auto-generated method stub
+
+       }
+
+       @Override
+       public String transform(String attrValue) {
+               // TODO Auto-generated method stub
+               return null;
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/a57740e2/ugsync/src/main/java/org/apache/ranger/usergroupsync/Mapper.java
----------------------------------------------------------------------
diff --git a/ugsync/src/main/java/org/apache/ranger/usergroupsync/Mapper.java 
b/ugsync/src/main/java/org/apache/ranger/usergroupsync/Mapper.java
new file mode 100644
index 0000000..820fe20
--- /dev/null
+++ b/ugsync/src/main/java/org/apache/ranger/usergroupsync/Mapper.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.usergroupsync;
+
+public interface Mapper {
+       public void init(String baseProperty);
+
+    public String transform(String attrValue);
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/a57740e2/ugsync/src/main/java/org/apache/ranger/usergroupsync/RegEx.java
----------------------------------------------------------------------
diff --git a/ugsync/src/main/java/org/apache/ranger/usergroupsync/RegEx.java 
b/ugsync/src/main/java/org/apache/ranger/usergroupsync/RegEx.java
new file mode 100644
index 0000000..b655536
--- /dev/null
+++ b/ugsync/src/main/java/org/apache/ranger/usergroupsync/RegEx.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.usergroupsync;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.ranger.unixusersync.config.UserGroupSyncConfig;
+
+public class RegEx extends AbstractMapper {
+       private UserGroupSyncConfig config = UserGroupSyncConfig.getInstance();
+       private LinkedHashMap<String, String> replacementPattern;
+
+       public LinkedHashMap<String, String> getReplacementPattern() {
+               return replacementPattern;
+       }
+
+       @Override
+       public void init (String baseProperty) {
+               logger.info("Initializing for " + baseProperty);
+               List<String> regexPatterns = 
config.getAllRegexPatterns(baseProperty);
+               populateReplacementPatterns(baseProperty, regexPatterns);
+       }
+
+       protected void populateReplacementPatterns(String baseProperty, 
List<String> regexPatterns) {
+               replacementPattern = new LinkedHashMap<String, String>();
+               Pattern p = Pattern.compile("s/([^/]*)/([^/]*)/(g)?");
+               for (String regexPattern : regexPatterns) {
+                       Matcher m = p.matcher(regexPattern);
+                       if (!m.matches()) {
+                               logger.warn("Invalid RegEx " + regexPattern + " 
and hence skipping this regex property");
+                       }
+                       m = m.reset();
+                       while (m.find()) {
+                               String matchPattern = m.group(1);
+                               String replacement = m.group(2);
+                               if (matchPattern != null && 
!matchPattern.isEmpty() && replacement != null) {
+                                       replacementPattern.put(matchPattern, 
Matcher.quoteReplacement(replacement));
+                                       if (logger.isDebugEnabled()) {
+                                               logger.debug(baseProperty + " 
match pattern = " + matchPattern + " and replacement string = " + replacement);
+                                       }
+                               }
+                       }
+               }
+       }
+
+       @Override
+       public String transform (String attrValue) {
+               String result = attrValue;
+               if (replacementPattern != null && 
!replacementPattern.isEmpty()) {
+                       for (String matchPattern : replacementPattern.keySet()) 
{
+                               Pattern p = Pattern.compile(matchPattern);
+                               Matcher m = p.matcher(result);
+                               if (m.find()) {
+                                       String replacement = 
replacementPattern.get(matchPattern);
+                                       if (replacement != null) {
+                                               result = 
m.replaceAll(replacement);
+                                       }
+                               }
+                       }
+               }
+               return result;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-ranger/blob/a57740e2/ugsync/src/test/java/org/apache/ranger/usergroupsync/RegExTest.java
----------------------------------------------------------------------
diff --git 
a/ugsync/src/test/java/org/apache/ranger/usergroupsync/RegExTest.java 
b/ugsync/src/test/java/org/apache/ranger/usergroupsync/RegExTest.java
new file mode 100644
index 0000000..d74eb2b
--- /dev/null
+++ b/ugsync/src/test/java/org/apache/ranger/usergroupsync/RegExTest.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.usergroupsync;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+
+public class RegExTest {
+       protected String userNameBaseProperty = 
"ranger.usersync.mapping.username.regex";
+    protected String groupNameBaseProperty = 
"ranger.usersync.mapping.groupname.regex";
+    protected RegEx userNameRegEx = null;
+    protected RegEx groupNameRegEx = null;
+    List<String> userRegexPatterns = null;
+    List<String> groupRegexPatterns = null;
+
+       @Before
+       public void setUp() throws Exception {
+               userNameRegEx = new RegEx();
+        //userNameRegEx.init(userNameBaseProperty);
+        userRegexPatterns = new ArrayList<String>();
+        groupNameRegEx = new RegEx();
+        //groupNameRegEx.init(groupNameBaseProperty);
+        groupRegexPatterns = new ArrayList<String>();
+       }
+
+       @Test
+    public void testUserNameTransform() {
+            userRegexPatterns.add("s/\\s/_/");
+            userNameRegEx.populateReplacementPatterns(userNameBaseProperty, 
userRegexPatterns);
+            assertEquals("test_user", userNameRegEx.transform("test user"));
+    }
+
+    @Test
+    public void testGroupNameTransform() {
+            groupRegexPatterns.add("s/\\s/_/g");
+            groupRegexPatterns.add("s/_/$/g");
+            groupNameRegEx.populateReplacementPatterns(userNameBaseProperty, 
groupRegexPatterns);
+            assertEquals("ldap$grp", groupNameRegEx.transform("ldap grp"));
+    }
+
+    @Test
+    public void testEmptyTransform() {
+            assertEquals("test user", userNameRegEx.transform("test user"));
+            assertEquals("ldap grp", groupNameRegEx.transform("ldap grp"));
+    }
+
+    @Test
+    public void testTransform() {
+            userRegexPatterns.add("s/\\s/_/g");
+            userNameRegEx.populateReplacementPatterns(userNameBaseProperty, 
userRegexPatterns);
+            assertEquals("test_user", userNameRegEx.transform("test user"));
+            assertEquals("ldap grp", groupNameRegEx.transform("ldap grp"));
+    }
+
+    @Test
+    public void testTransform1() {
+            userRegexPatterns.add("s/\\\\/ /g");
+            userRegexPatterns.add("s//_/g");
+            userNameRegEx.populateReplacementPatterns(userNameBaseProperty, 
userRegexPatterns);
+            groupRegexPatterns.add("s/\\s//g");
+            groupRegexPatterns.add("s/\\s");
+            groupNameRegEx.populateReplacementPatterns(userNameBaseProperty, 
groupRegexPatterns);
+            assertEquals("test user", userNameRegEx.transform("test\\user"));
+            assertEquals("ldapgrp", groupNameRegEx.transform("ldap grp"));
+    }
+
+}

Reply via email to