HADOOP-15255. Upper/Lower case conversion support for group names in 
LdapGroupsMapping. Contributed by Nanda kumar.


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

Branch: refs/heads/branch-3.1
Commit: 83ac13a59ad2cca0d9536b98b2a37f6756c749ba
Parents: de7a079
Author: Arpit Agarwal <a...@apache.org>
Authored: Fri Feb 23 15:37:17 2018 -0800
Committer: Arpit Agarwal <a...@apache.org>
Committed: Fri Feb 23 15:37:41 2018 -0800

----------------------------------------------------------------------
 .../security/RuleBasedLdapGroupsMapping.java    | 91 ++++++++++++++++++
 .../src/main/resources/core-default.xml         | 13 +++
 .../conf/TestCommonConfigurationFields.java     |  4 +-
 .../TestRuleBasedLdapGroupsMapping.java         | 99 ++++++++++++++++++++
 4 files changed, 206 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hadoop/blob/83ac13a5/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/RuleBasedLdapGroupsMapping.java
----------------------------------------------------------------------
diff --git 
a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/RuleBasedLdapGroupsMapping.java
 
b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/RuleBasedLdapGroupsMapping.java
new file mode 100644
index 0000000..6accf2f
--- /dev/null
+++ 
b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/RuleBasedLdapGroupsMapping.java
@@ -0,0 +1,91 @@
+/**
+ * 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.hadoop.security;
+
+import com.google.common.annotations.VisibleForTesting;
+import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * This class uses {@link LdapGroupsMapping} for group lookup and applies the
+ * rule configured on the group names.
+ */
+@InterfaceAudience.LimitedPrivate({"HDFS"})
+@InterfaceStability.Evolving
+public class RuleBasedLdapGroupsMapping extends LdapGroupsMapping {
+
+  public static final String CONVERSION_RULE_KEY = LDAP_CONFIG_PREFIX +
+      ".conversion.rule";
+
+  private static final String CONVERSION_RULE_DEFAULT = "none";
+  private static final Logger LOG =
+      LoggerFactory.getLogger(RuleBasedLdapGroupsMapping.class);
+
+  private Rule rule;
+
+  /**
+   * Supported rules applicable for group name modification.
+   */
+  private enum Rule {
+    TO_UPPER, TO_LOWER, NONE
+  }
+
+  @Override
+  public synchronized void setConf(Configuration conf) {
+    super.setConf(conf);
+    String value = conf.get(CONVERSION_RULE_KEY, CONVERSION_RULE_DEFAULT);
+    try {
+      rule = Rule.valueOf(value.toUpperCase());
+    } catch (IllegalArgumentException iae) {
+      LOG.warn("Invalid {} configured: '{}'. Using default value: '{}'",
+          CONVERSION_RULE_KEY, value, CONVERSION_RULE_DEFAULT);
+    }
+  }
+
+    /**
+     * Returns list of groups for a user.
+     * This calls {@link LdapGroupsMapping}'s getGroups and applies the
+     * configured rules on group names before returning.
+     *
+     * @param user get groups for this user
+     * @return list of groups for a given user
+     */
+  @Override
+  public synchronized List<String> getGroups(String user) {
+    List<String> groups = super.getGroups(user);
+    switch (rule) {
+    case TO_UPPER:
+      return groups.stream().map(StringUtils::toUpperCase).collect(
+          Collectors.toList());
+    case TO_LOWER:
+      return groups.stream().map(StringUtils::toLowerCase).collect(
+          Collectors.toList());
+    case NONE:
+    default:
+      return groups;
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/83ac13a5/hadoop-common-project/hadoop-common/src/main/resources/core-default.xml
----------------------------------------------------------------------
diff --git 
a/hadoop-common-project/hadoop-common/src/main/resources/core-default.xml 
b/hadoop-common-project/hadoop-common/src/main/resources/core-default.xml
index 1008331..a01abde 100644
--- a/hadoop-common-project/hadoop-common/src/main/resources/core-default.xml
+++ b/hadoop-common-project/hadoop-common/src/main/resources/core-default.xml
@@ -276,6 +276,19 @@
 </property>
 
 <property>
+  <name>hadoop.security.group.mapping.ldap.conversion.rule</name>
+  <value>none</value>
+  <description>
+    The rule is applied on the group names received from LDAP when
+    RuleBasedLdapGroupsMapping is configured.
+    Supported rules are "to_upper", "to_lower" and "none".
+    to_upper: This will convert all the group names to uppercase.
+    to_lower: This will convert all the group names to lowercase.
+    none: This will retain the source formatting, this is default value.
+  </description>
+</property>
+
+<property>
   <name>hadoop.security.credential.clear-text-fallback</name>
   <value>true</value>
   <description>

http://git-wip-us.apache.org/repos/asf/hadoop/blob/83ac13a5/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/conf/TestCommonConfigurationFields.java
----------------------------------------------------------------------
diff --git 
a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/conf/TestCommonConfigurationFields.java
 
b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/conf/TestCommonConfigurationFields.java
index 6677716..6ca9c78 100644
--- 
a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/conf/TestCommonConfigurationFields.java
+++ 
b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/conf/TestCommonConfigurationFields.java
@@ -34,6 +34,7 @@ import org.apache.hadoop.io.nativeio.NativeIO;
 import org.apache.hadoop.security.CompositeGroupsMapping;
 import org.apache.hadoop.security.HttpCrossOriginFilterInitializer;
 import org.apache.hadoop.security.LdapGroupsMapping;
+import org.apache.hadoop.security.RuleBasedLdapGroupsMapping;
 import org.apache.hadoop.security.http.CrossOriginFilter;
 import org.apache.hadoop.security.ssl.SSLFactory;
 
@@ -74,7 +75,8 @@ public class TestCommonConfigurationFields extends 
TestConfigurationFieldsBase {
         ZKFailoverController.class,
         SSLFactory.class,
         CompositeGroupsMapping.class,
-        CodecUtil.class
+        CodecUtil.class,
+        RuleBasedLdapGroupsMapping.class
         };
 
     // Initialize used variables

http://git-wip-us.apache.org/repos/asf/hadoop/blob/83ac13a5/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestRuleBasedLdapGroupsMapping.java
----------------------------------------------------------------------
diff --git 
a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestRuleBasedLdapGroupsMapping.java
 
b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestRuleBasedLdapGroupsMapping.java
new file mode 100644
index 0000000..6592c79
--- /dev/null
+++ 
b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestRuleBasedLdapGroupsMapping.java
@@ -0,0 +1,99 @@
+/**
+ * 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.hadoop.security;
+
+import org.apache.hadoop.conf.Configuration;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+import javax.naming.NamingException;
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.apache.hadoop.security.RuleBasedLdapGroupsMapping
+    .CONVERSION_RULE_KEY;
+import static org.mockito.Matchers.anyInt;
+import static org.mockito.Matchers.eq;
+
+/**
+ * Test cases to verify the rules supported by RuleBasedLdapGroupsMapping.
+ */
+public class TestRuleBasedLdapGroupsMapping  {
+
+  @Test
+  public void testGetGroupsToUpper() throws NamingException {
+    RuleBasedLdapGroupsMapping groupsMapping = Mockito.spy(
+        new RuleBasedLdapGroupsMapping());
+    List<String> groups = new ArrayList<>();
+    groups.add("group1");
+    groups.add("group2");
+    Mockito.doReturn(groups).when((LdapGroupsMapping) groupsMapping)
+        .doGetGroups(eq("admin"), anyInt());
+
+    Configuration conf = new Configuration();
+    conf.set(LdapGroupsMapping.LDAP_URL_KEY, "ldap://test";);
+    conf.set(CONVERSION_RULE_KEY, "to_upper");
+    groupsMapping.setConf(conf);
+
+    List<String> groupsUpper = new ArrayList<>();
+    groupsUpper.add("GROUP1");
+    groupsUpper.add("GROUP2");
+    Assert.assertEquals(groupsUpper, groupsMapping.getGroups("admin"));
+  }
+
+  @Test
+  public void testGetGroupsToLower() throws NamingException {
+    RuleBasedLdapGroupsMapping groupsMapping = Mockito.spy(
+        new RuleBasedLdapGroupsMapping());
+    List<String> groups = new ArrayList<>();
+    groups.add("GROUP1");
+    groups.add("GROUP2");
+    Mockito.doReturn(groups).when((LdapGroupsMapping) groupsMapping)
+        .doGetGroups(eq("admin"), anyInt());
+
+    Configuration conf = new Configuration();
+    conf.set(LdapGroupsMapping.LDAP_URL_KEY, "ldap://test";);
+    conf.set(CONVERSION_RULE_KEY, "to_lower");
+    groupsMapping.setConf(conf);
+
+    List<String> groupsLower = new ArrayList<>();
+    groupsLower.add("group1");
+    groupsLower.add("group2");
+    Assert.assertEquals(groupsLower, groupsMapping.getGroups("admin"));
+  }
+
+  @Test
+  public void testGetGroupsInvalidRule() throws NamingException {
+    RuleBasedLdapGroupsMapping groupsMapping = Mockito.spy(
+        new RuleBasedLdapGroupsMapping());
+    List<String> groups = new ArrayList<>();
+    groups.add("group1");
+    groups.add("GROUP2");
+    Mockito.doReturn(groups).when((LdapGroupsMapping) groupsMapping)
+        .doGetGroups(eq("admin"), anyInt());
+
+    Configuration conf = new Configuration();
+    conf.set(LdapGroupsMapping.LDAP_URL_KEY, "ldap://test";);
+    conf.set(CONVERSION_RULE_KEY, "none");
+    groupsMapping.setConf(conf);
+
+    Assert.assertEquals(groups, groupsMapping.getGroups("admin"));
+  }
+
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: common-commits-unsubscr...@hadoop.apache.org
For additional commands, e-mail: common-commits-h...@hadoop.apache.org

Reply via email to