diff --git a/hadoop-common-project/hadoop-common/CHANGES.txt b/hadoop-common-project/hadoop-common/CHANGES.txt index 74bc315ae0c..95d8f40ecc3 100644 --- a/hadoop-common-project/hadoop-common/CHANGES.txt +++ b/hadoop-common-project/hadoop-common/CHANGES.txt @@ -124,6 +124,8 @@ Trunk (Unreleased) HADOOP-10342. Add a new method to UGI to use a Kerberos login subject to build a new UGI. (Larry McCay via omalley) + HADOOP-9968. Makes ProxyUsers to work with NetGroups (Benoy Antony via ddas) + BUG FIXES HADOOP-9451. Fault single-layer config if node group topology is enabled. diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/ProxyUsers.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/ProxyUsers.java index 52952588739..15ddcdca13f 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/ProxyUsers.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/ProxyUsers.java @@ -20,6 +20,7 @@ import java.net.InetAddress; import java.net.UnknownHostException; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Map; @@ -27,6 +28,7 @@ import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.security.Groups; import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.util.StringUtils; @@ -68,8 +70,11 @@ public static synchronized void refreshSuperUserGroupsConfiguration(Configuratio String regex = CONF_HADOOP_PROXYUSER_RE+"[^.]*\\"+CONF_GROUPS; Map allMatchKeys = conf.getValByRegex(regex); for(Entry entry : allMatchKeys.entrySet()) { - proxyGroups.put(entry.getKey(), - StringUtils.getStringCollection(entry.getValue())); + Collection groups = StringUtils.getStringCollection(entry.getValue()); + proxyGroups.put(entry.getKey(), groups ); + //cache the groups. This is needed for NetGroups + Groups.getUserToGroupsMappingService(conf).cacheGroupsAdd( + new ArrayList(groups)); } // now hosts diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/authorize/TestProxyUsers.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/authorize/TestProxyUsers.java index 6f346a117c1..edb9f7781d0 100644 --- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/authorize/TestProxyUsers.java +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/authorize/TestProxyUsers.java @@ -17,23 +17,113 @@ */ package org.apache.hadoop.security.authorize; +import java.io.IOException; import java.util.Arrays; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.CommonConfigurationKeysPublic; +import org.apache.hadoop.util.NativeCodeLoader; import org.apache.hadoop.util.StringUtils; +import org.apache.hadoop.security.Groups; import org.apache.hadoop.security.UserGroupInformation; import org.junit.Test; import static org.junit.Assert.*; + public class TestProxyUsers { + private static final Log LOG = + LogFactory.getLog(TestProxyUsers.class); private static final String REAL_USER_NAME = "proxier"; private static final String PROXY_USER_NAME = "proxied_user"; private static final String[] GROUP_NAMES = new String[] { "foo_group" }; + private static final String[] NETGROUP_NAMES = + new String[] { "@foo_group" }; private static final String[] OTHER_GROUP_NAMES = new String[] { "bar_group" }; private static final String PROXY_IP = "1.2.3.4"; + /** + * Test the netgroups (groups in ACL rules that start with @) + * + * This is a manual test because it requires: + * - host setup + * - native code compiled + * - specify the group mapping class + * + * Host setup: + * + * /etc/nsswitch.conf should have a line like this: + * netgroup: files + * + * /etc/netgroup should be (the whole file): + * foo_group (,proxied_user,) + * + * To run this test: + * + * export JAVA_HOME='path/to/java' + * mvn test \ + * -Dtest=TestProxyUsers \ + * -DTestProxyUsersGroupMapping=$className \ + * + * where $className is one of the classes that provide group + * mapping services, i.e. classes that implement + * GroupMappingServiceProvider interface, at this time: + * - org.apache.hadoop.security.JniBasedUnixGroupsNetgroupMapping + * - org.apache.hadoop.security.ShellBasedUnixGroupsNetgroupMapping + * + */ + + @Test + public void testNetgroups () throws IOException{ + + if(!NativeCodeLoader.isNativeCodeLoaded()) { + LOG.info("Not testing netgroups, " + + "this test only runs when native code is compiled"); + return; + } + + String groupMappingClassName = + System.getProperty("TestProxyUsersGroupMapping"); + + if(groupMappingClassName == null) { + LOG.info("Not testing netgroups, no group mapping class specified, " + + "use -DTestProxyUsersGroupMapping=$className to specify " + + "group mapping class (must implement GroupMappingServiceProvider " + + "interface and support netgroups)"); + return; + } + + LOG.info("Testing netgroups using: " + groupMappingClassName); + + Configuration conf = new Configuration(); + conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_GROUP_MAPPING, + groupMappingClassName); + + conf.set( + ProxyUsers.getProxySuperuserGroupConfKey(REAL_USER_NAME), + StringUtils.join(",", Arrays.asList(NETGROUP_NAMES))); + conf.set( + ProxyUsers.getProxySuperuserIpConfKey(REAL_USER_NAME), + PROXY_IP); + + ProxyUsers.refreshSuperUserGroupsConfiguration(conf); + Groups groups = Groups.getUserToGroupsMappingService(conf); + + // try proxying a group that's allowed + UserGroupInformation realUserUgi = UserGroupInformation + .createRemoteUser(REAL_USER_NAME); + + UserGroupInformation proxyUserUgi = UserGroupInformation.createProxyUserForTesting( + PROXY_USER_NAME, realUserUgi, groups.getGroups(PROXY_USER_NAME).toArray( + new String[groups.getGroups(PROXY_USER_NAME).size()])); + + assertAuthorized(proxyUserUgi, PROXY_IP); + } + @Test public void testProxyUsers() throws Exception { Configuration conf = new Configuration();