Author: arp
Date: Thu May 29 23:38:07 2014
New Revision: 1598440
URL: http://svn.apache.org/r1598440
Log:
HADOOP-9968 and HADOOP-10448. Merging r1570934 and 1598396 from trunk to
branch-2.
Added:
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/DefaultImpersonationProvider.java
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/ImpersonationProvider.java
Modified:
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/CHANGES.txt
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/CommonConfigurationKeysPublic.java
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/ProxyUsers.java
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/resources/core-default.xml
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ipc/MiniRPCBenchmark.java
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestDoAsEffectiveUser.java
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/authorize/TestProxyUsers.java
Modified:
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/CHANGES.txt
URL:
http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/CHANGES.txt?rev=1598440&r1=1598439&r2=1598440&view=diff
==============================================================================
---
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/CHANGES.txt
(original)
+++
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/CHANGES.txt
Thu May 29 23:38:07 2014
@@ -60,6 +60,12 @@ Release 2.5.0 - UNRELEASED
HADOOP-10566. Refactor proxyservers out of ProxyUsers. (Benoy Antony via
Arpit Agarwal)
+ HDFS-9968. ProxyUsers does not work with NetGroups. (Benoy Antony via
+ Devaraj Das)
+
+ HADOOP-10448. Support pluggable mechanism to specify proxy user settings.
+ (Benoy Antony via Arpit Agarwal)
+
OPTIMIZATIONS
BUG FIXES
Modified:
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/CommonConfigurationKeysPublic.java
URL:
http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/CommonConfigurationKeysPublic.java?rev=1598440&r1=1598439&r2=1598440&view=diff
==============================================================================
---
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/CommonConfigurationKeysPublic.java
(original)
+++
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/CommonConfigurationKeysPublic.java
Thu May 29 23:38:07 2014
@@ -290,5 +290,8 @@ public class CommonConfigurationKeysPubl
/** Class to override Sasl Properties for a connection */
public static final String HADOOP_SECURITY_SASL_PROPS_RESOLVER_CLASS =
"hadoop.security.saslproperties.resolver.class";
+ /** Class to override Impersonation provider */
+ public static final String HADOOP_SECURITY_IMPERSONATION_PROVIDER_CLASS =
+ "hadoop.security.impersonation.provider.class";
}
Added:
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/DefaultImpersonationProvider.java
URL:
http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/DefaultImpersonationProvider.java?rev=1598440&view=auto
==============================================================================
---
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/DefaultImpersonationProvider.java
(added)
+++
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/DefaultImpersonationProvider.java
Thu May 29 23:38:07 2014
@@ -0,0 +1,210 @@
+/**
+ * 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.authorize;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.security.Groups;
+import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.util.StringUtils;
+
+import com.google.common.annotations.VisibleForTesting;
+
+public class DefaultImpersonationProvider implements ImpersonationProvider {
+ private static final String CONF_HOSTS = ".hosts";
+ private static final String CONF_USERS = ".users";
+ private static final String CONF_GROUPS = ".groups";
+ private static final String CONF_HADOOP_PROXYUSER = "hadoop.proxyuser.";
+ private static final String CONF_HADOOP_PROXYUSER_RE =
"hadoop\\.proxyuser\\.";
+ // list of users, groups and hosts per proxyuser
+ private Map<String, Collection<String>> proxyUsers =
+ new HashMap<String, Collection<String>>();
+ private Map<String, Collection<String>> proxyGroups =
+ new HashMap<String, Collection<String>>();
+ private Map<String, Collection<String>> proxyHosts =
+ new HashMap<String, Collection<String>>();
+ private Configuration conf;
+
+ @Override
+ public void setConf(Configuration conf) {
+ this.conf = conf;
+
+ // get all the new keys for users
+ String regex = CONF_HADOOP_PROXYUSER_RE+"[^.]*\\"+CONF_USERS;
+ Map<String,String> allMatchKeys = conf.getValByRegex(regex);
+ for(Entry<String, String> entry : allMatchKeys.entrySet()) {
+ Collection<String> users =
StringUtils.getTrimmedStringCollection(entry.getValue());
+ proxyUsers.put(entry.getKey(), users);
+ }
+
+ // get all the new keys for groups
+ regex = CONF_HADOOP_PROXYUSER_RE+"[^.]*\\"+CONF_GROUPS;
+ allMatchKeys = conf.getValByRegex(regex);
+ for(Entry<String, String> entry : allMatchKeys.entrySet()) {
+ Collection<String> groups =
StringUtils.getTrimmedStringCollection(entry.getValue());
+ proxyGroups.put(entry.getKey(), groups);
+ //cache the groups. This is needed for NetGroups
+ Groups.getUserToGroupsMappingService(conf).cacheGroupsAdd(
+ new ArrayList<String>(groups));
+ }
+
+ // now hosts
+ regex = CONF_HADOOP_PROXYUSER_RE+"[^.]*\\"+CONF_HOSTS;
+ allMatchKeys = conf.getValByRegex(regex);
+ for(Entry<String, String> entry : allMatchKeys.entrySet()) {
+ proxyHosts.put(entry.getKey(),
+ StringUtils.getTrimmedStringCollection(entry.getValue()));
+ }
+ }
+
+ @Override
+ public Configuration getConf() {
+ return conf;
+ }
+
+ @Override
+ public void authorize(UserGroupInformation user,
+ String remoteAddress) throws AuthorizationException {
+
+ if (user.getRealUser() == null) {
+ return;
+ }
+ boolean userAuthorized = false;
+ boolean ipAuthorized = false;
+ UserGroupInformation superUser = user.getRealUser();
+
+ Collection<String> allowedUsers = proxyUsers.get(
+ getProxySuperuserUserConfKey(superUser.getShortUserName()));
+
+ if (isWildcardList(allowedUsers)) {
+ userAuthorized = true;
+ } else if (allowedUsers != null && !allowedUsers.isEmpty()) {
+ if (allowedUsers.contains(user.getShortUserName())) {
+ userAuthorized = true;
+ }
+ }
+
+ if (!userAuthorized){
+ Collection<String> allowedUserGroups = proxyGroups.get(
+ getProxySuperuserGroupConfKey(superUser.getShortUserName()));
+
+ if (isWildcardList(allowedUserGroups)) {
+ userAuthorized = true;
+ } else if (allowedUserGroups != null && !allowedUserGroups.isEmpty()) {
+ for (String group : user.getGroupNames()) {
+ if (allowedUserGroups.contains(group)) {
+ userAuthorized = true;
+ break;
+ }
+ }
+ }
+
+ if (!userAuthorized) {
+ throw new AuthorizationException("User: " + superUser.getUserName()
+ + " is not allowed to impersonate " + user.getUserName());
+ }
+ }
+
+ Collection<String> ipList = proxyHosts.get(
+ getProxySuperuserIpConfKey(superUser.getShortUserName()));
+
+ if (isWildcardList(ipList)) {
+ ipAuthorized = true;
+ } else if (ipList != null && !ipList.isEmpty()) {
+ for (String allowedHost : ipList) {
+ InetAddress hostAddr;
+ try {
+ hostAddr = InetAddress.getByName(allowedHost);
+ } catch (UnknownHostException e) {
+ continue;
+ }
+ if (hostAddr.getHostAddress().equals(remoteAddress)) {
+ // Authorization is successful
+ ipAuthorized = true;
+ }
+ }
+ }
+ if(!ipAuthorized) {
+ throw new AuthorizationException("Unauthorized connection for
super-user: "
+ + superUser.getUserName() + " from IP " + remoteAddress);
+ }
+ }
+
+ /**
+ * Return true if the configuration specifies the special configuration value
+ * "*", indicating that any group or host list is allowed to use this
configuration.
+ */
+ private boolean isWildcardList(Collection<String> list) {
+ return (list != null) &&
+ (list.size() == 1) &&
+ (list.contains("*"));
+ }
+
+ /**
+ * Returns configuration key for effective usergroups allowed for a superuser
+ *
+ * @param userName name of the superuser
+ * @return configuration key for superuser usergroups
+ */
+ public static String getProxySuperuserUserConfKey(String userName) {
+ return CONF_HADOOP_PROXYUSER+userName+CONF_USERS;
+ }
+
+ /**
+ * Returns configuration key for effective groups allowed for a superuser
+ *
+ * @param userName name of the superuser
+ * @return configuration key for superuser groups
+ */
+ public static String getProxySuperuserGroupConfKey(String userName) {
+ return CONF_HADOOP_PROXYUSER+userName+CONF_GROUPS;
+ }
+
+ /**
+ * Return configuration key for superuser ip addresses
+ *
+ * @param userName name of the superuser
+ * @return configuration key for superuser ip-addresses
+ */
+ public static String getProxySuperuserIpConfKey(String userName) {
+ return CONF_HADOOP_PROXYUSER+userName+CONF_HOSTS;
+ }
+
+ @VisibleForTesting
+ public Map<String, Collection<String>> getProxyUsers() {
+ return proxyUsers;
+ }
+
+ @VisibleForTesting
+ public Map<String, Collection<String>> getProxyGroups() {
+ return proxyGroups;
+ }
+
+ @VisibleForTesting
+ public Map<String, Collection<String>> getProxyHosts() {
+ return proxyHosts;
+ }
+}
Added:
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/ImpersonationProvider.java
URL:
http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/ImpersonationProvider.java?rev=1598440&view=auto
==============================================================================
---
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/ImpersonationProvider.java
(added)
+++
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/ImpersonationProvider.java
Thu May 29 23:38:07 2014
@@ -0,0 +1,34 @@
+/**
+ * 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.authorize;
+
+import org.apache.hadoop.conf.Configurable;
+import org.apache.hadoop.security.UserGroupInformation;
+
+public interface ImpersonationProvider extends Configurable {
+ /**
+ * Authorize the superuser which is doing doAs
+ *
+ * @param user ugi of the effective or proxy user which contains a real user
+ * @param remoteAddress the ip address of client
+ * @throws AuthorizationException
+ */
+ public void authorize(UserGroupInformation user, String remoteAddress)
+ throws AuthorizationException;
+}
\ No newline at end of file
Modified:
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/ProxyUsers.java
URL:
http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/ProxyUsers.java?rev=1598440&r1=1598439&r2=1598440&view=diff
==============================================================================
---
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/ProxyUsers.java
(original)
+++
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/authorize/ProxyUsers.java
Thu May 29 23:38:07 2014
@@ -18,42 +18,35 @@
package org.apache.hadoop.security.authorize;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.UnknownHostException;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Map.Entry;
-
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
import org.apache.hadoop.security.UserGroupInformation;
-import org.apache.hadoop.util.StringUtils;
+import org.apache.hadoop.util.ReflectionUtils;
import com.google.common.annotations.VisibleForTesting;
@InterfaceAudience.LimitedPrivate({"HDFS", "MapReduce", "HBase", "Hive"})
public class ProxyUsers {
- private static final String CONF_HOSTS = ".hosts";
- private static final String CONF_USERS = ".users";
- private static final String CONF_GROUPS = ".groups";
- private static final String CONF_HADOOP_PROXYUSER = "hadoop.proxyuser.";
- private static final String CONF_HADOOP_PROXYUSER_RE =
"hadoop\\.proxyuser\\.";
-
- private static boolean init = false;
- //list of users, groups and hosts per proxyuser
- private static Map<String, Collection<String>> proxyUsers =
- new HashMap<String, Collection<String>>();
- private static Map<String, Collection<String>> proxyGroups =
- new HashMap<String, Collection<String>>();
- private static Map<String, Collection<String>> proxyHosts =
- new HashMap<String, Collection<String>>();
+ private static volatile ImpersonationProvider sip ;
/**
- * reread the conf and get new values for
"hadoop.proxyuser.*.groups/users/hosts"
+ * Returns an instance of ImpersonationProvider.
+ * Looks up the configuration to see if there is custom class specified.
+ * @param conf
+ * @return ImpersonationProvider
+ */
+ private static ImpersonationProvider getInstance(Configuration conf) {
+ Class<? extends ImpersonationProvider> clazz =
+ conf.getClass(
+
CommonConfigurationKeysPublic.HADOOP_SECURITY_IMPERSONATION_PROVIDER_CLASS,
+ DefaultImpersonationProvider.class, ImpersonationProvider.class);
+ return ReflectionUtils.newInstance(clazz, conf);
+ }
+
+ /**
+ * refresh Impersonation rules
*/
public static void refreshSuperUserGroupsConfiguration() {
//load server side configuration;
@@ -64,146 +57,28 @@ public class ProxyUsers {
* refresh configuration
* @param conf
*/
- public static synchronized void
refreshSuperUserGroupsConfiguration(Configuration conf) {
-
- // remove all existing stuff
- proxyGroups.clear();
- proxyHosts.clear();
- proxyUsers.clear();
-
- // get all the new keys for users
- String regex = CONF_HADOOP_PROXYUSER_RE+"[^.]*\\"+CONF_USERS;
- Map<String,String> allMatchKeys = conf.getValByRegex(regex);
- for(Entry<String, String> entry : allMatchKeys.entrySet()) {
- Collection<String> users =
StringUtils.getTrimmedStringCollection(entry.getValue());
- proxyUsers.put(entry.getKey(), users);
- }
-
- // get all the new keys for groups
- regex = CONF_HADOOP_PROXYUSER_RE+"[^.]*\\"+CONF_GROUPS;
- allMatchKeys = conf.getValByRegex(regex);
- for(Entry<String, String> entry : allMatchKeys.entrySet()) {
- proxyGroups.put(entry.getKey(),
- StringUtils.getTrimmedStringCollection(entry.getValue()));
- }
-
- // now hosts
- regex = CONF_HADOOP_PROXYUSER_RE+"[^.]*\\"+CONF_HOSTS;
- allMatchKeys = conf.getValByRegex(regex);
- for(Entry<String, String> entry : allMatchKeys.entrySet()) {
- proxyHosts.put(entry.getKey(),
- StringUtils.getTrimmedStringCollection(entry.getValue()));
- }
- init = true;
+ public static void refreshSuperUserGroupsConfiguration(Configuration conf) {
+ // sip is volatile. Any assignment to it as well as the object's state
+ // will be visible to all the other threads.
+ sip = getInstance(conf);
ProxyServers.refresh(conf);
}
/**
- * Returns configuration key for effective users allowed for a superuser
- *
- * @param userName name of the superuser
- * @return configuration key for superuser users
- */
- public static String getProxySuperuserUserConfKey(String userName) {
- return ProxyUsers.CONF_HADOOP_PROXYUSER+userName+ProxyUsers.CONF_USERS;
- }
-
- /**
- * Returns configuration key for effective user groups allowed for a
superuser
- *
- * @param userName name of the superuser
- * @return configuration key for superuser groups
- */
- public static String getProxySuperuserGroupConfKey(String userName) {
- return ProxyUsers.CONF_HADOOP_PROXYUSER+userName+ProxyUsers.CONF_GROUPS;
- }
-
- /**
- * Return configuration key for superuser ip addresses
- *
- * @param userName name of the superuser
- * @return configuration key for superuser ip-addresses
- */
- public static String getProxySuperuserIpConfKey(String userName) {
- return ProxyUsers.CONF_HADOOP_PROXYUSER+userName+ProxyUsers.CONF_HOSTS;
- }
-
- /**
* Authorize the superuser which is doing doAs
*
* @param user ugi of the effective or proxy user which contains a real user
* @param remoteAddress the ip address of client
* @throws AuthorizationException
*/
- public static synchronized void authorize(UserGroupInformation user,
+ public static void authorize(UserGroupInformation user,
String remoteAddress) throws AuthorizationException {
-
- if(!init) {
+ if (sip==null) {
+ // In a race situation, It is possible for multiple threads to satisfy
this condition.
+ // The last assignment will prevail.
refreshSuperUserGroupsConfiguration();
}
-
- if (user.getRealUser() == null) {
- return;
- }
- boolean userAuthorized = false;
- boolean ipAuthorized = false;
- UserGroupInformation superUser = user.getRealUser();
-
- Collection<String> allowedUsers = proxyUsers.get(
- getProxySuperuserUserConfKey(superUser.getShortUserName()));
-
- if (isWildcardList(allowedUsers)) {
- userAuthorized = true;
- } else if (allowedUsers != null && !allowedUsers.isEmpty()) {
- if (allowedUsers.contains(user.getShortUserName())) {
- userAuthorized = true;
- }
- }
-
- if (!userAuthorized) {
- Collection<String> allowedUserGroups = proxyGroups.get(
- getProxySuperuserGroupConfKey(superUser.getShortUserName()));
-
- if (isWildcardList(allowedUserGroups)) {
- userAuthorized = true;
- } else if (allowedUserGroups != null && !allowedUserGroups.isEmpty()) {
- for (String group : user.getGroupNames()) {
- if (allowedUserGroups.contains(group)) {
- userAuthorized = true;
- break;
- }
- }
- }
-
- if (!userAuthorized) {
- throw new AuthorizationException("User: " + superUser.getUserName()
- + " is not allowed to impersonate " + user.getUserName());
- }
- }
-
- Collection<String> ipList = proxyHosts.get(
- getProxySuperuserIpConfKey(superUser.getShortUserName()));
-
- if (isWildcardList(ipList)) {
- ipAuthorized = true;
- } else if (ipList != null && !ipList.isEmpty()) {
- for (String allowedHost : ipList) {
- InetAddress hostAddr;
- try {
- hostAddr = InetAddress.getByName(allowedHost);
- } catch (UnknownHostException e) {
- continue;
- }
- if (hostAddr.getHostAddress().equals(remoteAddress)) {
- // Authorization is successful
- ipAuthorized = true;
- }
- }
- }
- if (!ipAuthorized) {
- throw new AuthorizationException("Unauthorized connection for
super-user: "
- + superUser.getUserName() + " from IP " + remoteAddress);
- }
+ sip.authorize(user, remoteAddress);
}
/**
@@ -215,33 +90,14 @@ public class ProxyUsers {
* @deprecated use {@link #authorize(UserGroupInformation, String) instead.
*/
@Deprecated
- public static synchronized void authorize(UserGroupInformation user,
+ public static void authorize(UserGroupInformation user,
String remoteAddress, Configuration conf) throws AuthorizationException {
authorize(user,remoteAddress);
}
-
- /**
- * Return true if the configuration specifies the special configuration value
- * "*", indicating that any group or host list is allowed to use this
configuration.
- */
- private static boolean isWildcardList(Collection<String> list) {
- return (list != null) &&
- (list.size() == 1) &&
- (list.contains("*"));
- }
-
- @VisibleForTesting
- public static Map<String, Collection<String>> getProxyUsers() {
- return proxyUsers;
- }
-
- @VisibleForTesting
- public static Map<String, Collection<String>> getProxyGroups() {
- return proxyGroups;
- }
-
- @VisibleForTesting
- public static Map<String, Collection<String>> getProxyHosts() {
- return proxyHosts;
+
+ @VisibleForTesting
+ public static DefaultImpersonationProvider getDefaultImpersonationProvider()
{
+ return ((DefaultImpersonationProvider)sip);
}
+
}
Modified:
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/resources/core-default.xml
URL:
http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/resources/core-default.xml?rev=1598440&r1=1598439&r2=1598440&view=diff
==============================================================================
---
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/resources/core-default.xml
(original)
+++
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/main/resources/core-default.xml
Thu May 29 23:38:07 2014
@@ -715,6 +715,17 @@
<!-- Proxy Configuration -->
<property>
+ <name>hadoop.security.impersonation.provider.class</name>
+ <value></value>
+ <description>A class which implements ImpersonationProvider interface, used
to
+ authorize whether one user can impersonate a specific user.
+ If not specified, the DefaultImpersonationProvider will be used.
+ If a class is specified, then that class will be used to determine
+ the impersonation capability.
+ </description>
+</property>
+
+<property>
<name>hadoop.rpc.socket.factory.class.default</name>
<value>org.apache.hadoop.net.StandardSocketFactory</value>
<description> Default SocketFactory to use. This parameter is expected to be
Modified:
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ipc/MiniRPCBenchmark.java
URL:
http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ipc/MiniRPCBenchmark.java?rev=1598440&r1=1598439&r2=1598440&view=diff
==============================================================================
---
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ipc/MiniRPCBenchmark.java
(original)
+++
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/ipc/MiniRPCBenchmark.java
Thu May 29 23:38:07 2014
@@ -35,6 +35,7 @@ import org.apache.hadoop.net.NetUtils;
import org.apache.hadoop.security.KerberosInfo;
import org.apache.hadoop.security.SecurityUtil;
import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.security.authorize.DefaultImpersonationProvider;
import org.apache.hadoop.security.authorize.ProxyUsers;
import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.security.token.TokenInfo;
@@ -326,7 +327,7 @@ public class MiniRPCBenchmark {
String shortUserName =
UserGroupInformation.createRemoteUser(user).getShortUserName();
try {
- conf.setStrings(ProxyUsers.getProxySuperuserGroupConfKey(shortUserName),
+
conf.setStrings(DefaultImpersonationProvider.getProxySuperuserGroupConfKey(shortUserName),
GROUP_NAME_1);
configureSuperUserIPAddresses(conf, shortUserName);
// start the server
@@ -410,7 +411,7 @@ public class MiniRPCBenchmark {
}
builder.append("127.0.1.1,");
builder.append(InetAddress.getLocalHost().getCanonicalHostName());
- conf.setStrings(ProxyUsers.getProxySuperuserIpConfKey(superUserShortName),
+
conf.setStrings(DefaultImpersonationProvider.getProxySuperuserIpConfKey(superUserShortName),
builder.toString());
}
}
Modified:
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestDoAsEffectiveUser.java
URL:
http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestDoAsEffectiveUser.java?rev=1598440&r1=1598439&r2=1598440&view=diff
==============================================================================
---
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestDoAsEffectiveUser.java
(original)
+++
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestDoAsEffectiveUser.java
Thu May 29 23:38:07 2014
@@ -35,6 +35,7 @@ import org.apache.hadoop.ipc.Server;
import org.apache.hadoop.ipc.VersionedProtocol;
import org.apache.hadoop.net.NetUtils;
import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
+import org.apache.hadoop.security.authorize.DefaultImpersonationProvider;
import org.apache.hadoop.security.authorize.ProxyUsers;
import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.security.token.TokenInfo;
@@ -100,7 +101,7 @@ public class TestDoAsEffectiveUser {
builder.append("127.0.1.1,");
builder.append(InetAddress.getLocalHost().getCanonicalHostName());
LOG.info("Local Ip addresses: "+builder.toString());
- conf.setStrings(ProxyUsers.getProxySuperuserIpConfKey(superUserShortName),
+
conf.setStrings(DefaultImpersonationProvider.getProxySuperuserIpConfKey(superUserShortName),
builder.toString());
}
@@ -180,7 +181,7 @@ public class TestDoAsEffectiveUser {
@Test(timeout=4000)
public void testRealUserSetup() throws IOException {
final Configuration conf = new Configuration();
- conf.setStrings(ProxyUsers
+ conf.setStrings(DefaultImpersonationProvider
.getProxySuperuserGroupConfKey(REAL_USER_SHORT_NAME), "group1");
configureSuperUserIPAddresses(conf, REAL_USER_SHORT_NAME);
Server server = new RPC.Builder(conf).setProtocol(TestProtocol.class)
@@ -213,7 +214,7 @@ public class TestDoAsEffectiveUser {
public void testRealUserAuthorizationSuccess() throws IOException {
final Configuration conf = new Configuration();
configureSuperUserIPAddresses(conf, REAL_USER_SHORT_NAME);
-
conf.setStrings(ProxyUsers.getProxySuperuserGroupConfKey(REAL_USER_SHORT_NAME),
+
conf.setStrings(DefaultImpersonationProvider.getProxySuperuserGroupConfKey(REAL_USER_SHORT_NAME),
"group1");
Server server = new RPC.Builder(conf).setProtocol(TestProtocol.class)
.setInstance(new TestImpl()).setBindAddress(ADDRESS).setPort(0)
@@ -247,9 +248,9 @@ public class TestDoAsEffectiveUser {
@Test
public void testRealUserIPAuthorizationFailure() throws IOException {
final Configuration conf = new Configuration();
-
conf.setStrings(ProxyUsers.getProxySuperuserIpConfKey(REAL_USER_SHORT_NAME),
+
conf.setStrings(DefaultImpersonationProvider.getProxySuperuserIpConfKey(REAL_USER_SHORT_NAME),
"20.20.20.20"); //Authorized IP address
-
conf.setStrings(ProxyUsers.getProxySuperuserGroupConfKey(REAL_USER_SHORT_NAME),
+
conf.setStrings(DefaultImpersonationProvider.getProxySuperuserGroupConfKey(REAL_USER_SHORT_NAME),
"group1");
Server server = new RPC.Builder(conf).setProtocol(TestProtocol.class)
.setInstance(new TestImpl()).setBindAddress(ADDRESS).setPort(0)
@@ -292,7 +293,7 @@ public class TestDoAsEffectiveUser {
@Test
public void testRealUserIPNotSpecified() throws IOException {
final Configuration conf = new Configuration();
- conf.setStrings(ProxyUsers
+ conf.setStrings(DefaultImpersonationProvider
.getProxySuperuserGroupConfKey(REAL_USER_SHORT_NAME), "group1");
Server server = new RPC.Builder(conf).setProtocol(TestProtocol.class)
.setInstance(new TestImpl()).setBindAddress(ADDRESS).setPort(0)
@@ -376,7 +377,7 @@ public class TestDoAsEffectiveUser {
public void testRealUserGroupAuthorizationFailure() throws IOException {
final Configuration conf = new Configuration();
configureSuperUserIPAddresses(conf, REAL_USER_SHORT_NAME);
-
conf.setStrings(ProxyUsers.getProxySuperuserGroupConfKey(REAL_USER_SHORT_NAME),
+
conf.setStrings(DefaultImpersonationProvider.getProxySuperuserGroupConfKey(REAL_USER_SHORT_NAME),
"group3");
Server server = new RPC.Builder(conf).setProtocol(TestProtocol.class)
.setInstance(new TestImpl()).setBindAddress(ADDRESS).setPort(0)
Modified:
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/authorize/TestProxyUsers.java
URL:
http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/authorize/TestProxyUsers.java?rev=1598440&r1=1598439&r2=1598440&view=diff
==============================================================================
---
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/authorize/TestProxyUsers.java
(original)
+++
hadoop/common/branches/branch-2/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/authorize/TestProxyUsers.java
Thu May 29 23:38:07 2014
@@ -17,34 +17,126 @@
*/
package org.apache.hadoop.security.authorize;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
-import org.apache.hadoop.util.StringUtils;
+import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
+import org.apache.hadoop.security.Groups;
import org.apache.hadoop.security.UserGroupInformation;
-
+import org.apache.hadoop.util.NativeCodeLoader;
+import org.apache.hadoop.util.StringUtils;
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 AUTHORIZED_PROXY_USER_NAME =
"authorized_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[] SUDO_GROUP_NAMES =
+ new String[] { "sudo_proxied_user" };
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(
+
DefaultImpersonationProvider.getProxySuperuserGroupConfKey(REAL_USER_NAME),
+ StringUtils.join(",", Arrays.asList(NETGROUP_NAMES)));
+ conf.set(
+
DefaultImpersonationProvider.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();
conf.set(
- ProxyUsers.getProxySuperuserGroupConfKey(REAL_USER_NAME),
+
DefaultImpersonationProvider.getProxySuperuserGroupConfKey(REAL_USER_NAME),
StringUtils.join(",", Arrays.asList(GROUP_NAMES)));
conf.set(
- ProxyUsers.getProxySuperuserIpConfKey(REAL_USER_NAME),
+ DefaultImpersonationProvider.getProxySuperuserIpConfKey(REAL_USER_NAME),
PROXY_IP);
ProxyUsers.refreshSuperUserGroupsConfiguration(conf);
@@ -75,11 +167,11 @@ public class TestProxyUsers {
public void testProxyUsersWithUserConf() throws Exception {
Configuration conf = new Configuration();
conf.set(
- ProxyUsers.getProxySuperuserUserConfKey(REAL_USER_NAME),
- StringUtils.join(",", Arrays.asList(AUTHORIZED_PROXY_USER_NAME)));
+
DefaultImpersonationProvider.getProxySuperuserUserConfKey(REAL_USER_NAME),
+ StringUtils.join(",", Arrays.asList(AUTHORIZED_PROXY_USER_NAME)));
conf.set(
- ProxyUsers.getProxySuperuserIpConfKey(REAL_USER_NAME),
- PROXY_IP);
+
DefaultImpersonationProvider.getProxySuperuserIpConfKey(REAL_USER_NAME),
+ PROXY_IP);
ProxyUsers.refreshSuperUserGroupsConfiguration(conf);
@@ -109,10 +201,10 @@ public class TestProxyUsers {
public void testWildcardGroup() {
Configuration conf = new Configuration();
conf.set(
- ProxyUsers.getProxySuperuserGroupConfKey(REAL_USER_NAME),
+
DefaultImpersonationProvider.getProxySuperuserGroupConfKey(REAL_USER_NAME),
"*");
conf.set(
- ProxyUsers.getProxySuperuserIpConfKey(REAL_USER_NAME),
+ DefaultImpersonationProvider.getProxySuperuserIpConfKey(REAL_USER_NAME),
PROXY_IP);
ProxyUsers.refreshSuperUserGroupsConfiguration(conf);
@@ -143,10 +235,10 @@ public class TestProxyUsers {
public void testWildcardUser() {
Configuration conf = new Configuration();
conf.set(
- ProxyUsers.getProxySuperuserUserConfKey(REAL_USER_NAME),
+
DefaultImpersonationProvider.getProxySuperuserUserConfKey(REAL_USER_NAME),
"*");
conf.set(
- ProxyUsers.getProxySuperuserIpConfKey(REAL_USER_NAME),
+ DefaultImpersonationProvider.getProxySuperuserIpConfKey(REAL_USER_NAME),
PROXY_IP);
ProxyUsers.refreshSuperUserGroupsConfiguration(conf);
@@ -177,10 +269,10 @@ public class TestProxyUsers {
public void testWildcardIP() {
Configuration conf = new Configuration();
conf.set(
- ProxyUsers.getProxySuperuserGroupConfKey(REAL_USER_NAME),
+
DefaultImpersonationProvider.getProxySuperuserGroupConfKey(REAL_USER_NAME),
StringUtils.join(",", Arrays.asList(GROUP_NAMES)));
conf.set(
- ProxyUsers.getProxySuperuserIpConfKey(REAL_USER_NAME),
+ DefaultImpersonationProvider.getProxySuperuserIpConfKey(REAL_USER_NAME),
"*");
ProxyUsers.refreshSuperUserGroupsConfiguration(conf);
@@ -208,15 +300,16 @@ public class TestProxyUsers {
public void testWithDuplicateProxyGroups() throws Exception {
Configuration conf = new Configuration();
conf.set(
- ProxyUsers.getProxySuperuserGroupConfKey(REAL_USER_NAME),
+
DefaultImpersonationProvider.getProxySuperuserGroupConfKey(REAL_USER_NAME),
StringUtils.join(",", Arrays.asList(GROUP_NAMES,GROUP_NAMES)));
conf.set(
- ProxyUsers.getProxySuperuserIpConfKey(REAL_USER_NAME),
+ DefaultImpersonationProvider.getProxySuperuserIpConfKey(REAL_USER_NAME),
PROXY_IP);
ProxyUsers.refreshSuperUserGroupsConfiguration(conf);
- Collection<String> groupsToBeProxied = ProxyUsers.getProxyGroups().get(
- ProxyUsers.getProxySuperuserGroupConfKey(REAL_USER_NAME));
+ Collection<String> groupsToBeProxied =
+ ProxyUsers.getDefaultImpersonationProvider().getProxyGroups().get(
+
DefaultImpersonationProvider.getProxySuperuserGroupConfKey(REAL_USER_NAME));
assertEquals (1,groupsToBeProxied.size());
}
@@ -225,18 +318,51 @@ public class TestProxyUsers {
public void testWithDuplicateProxyHosts() throws Exception {
Configuration conf = new Configuration();
conf.set(
- ProxyUsers.getProxySuperuserGroupConfKey(REAL_USER_NAME),
+
DefaultImpersonationProvider.getProxySuperuserGroupConfKey(REAL_USER_NAME),
StringUtils.join(",", Arrays.asList(GROUP_NAMES)));
conf.set(
- ProxyUsers.getProxySuperuserIpConfKey(REAL_USER_NAME),
+ DefaultImpersonationProvider.getProxySuperuserIpConfKey(REAL_USER_NAME),
StringUtils.join(",", Arrays.asList(PROXY_IP,PROXY_IP)));
ProxyUsers.refreshSuperUserGroupsConfiguration(conf);
- Collection<String> hosts = ProxyUsers.getProxyHosts().get(
- ProxyUsers.getProxySuperuserIpConfKey(REAL_USER_NAME));
+ Collection<String> hosts =
+ ProxyUsers.getDefaultImpersonationProvider().getProxyHosts().get(
+
DefaultImpersonationProvider.getProxySuperuserIpConfKey(REAL_USER_NAME));
assertEquals (1,hosts.size());
}
+
+ @Test
+ public void testProxyUsersWithProviderOverride() throws Exception {
+ Configuration conf = new Configuration();
+ conf.set(
+
CommonConfigurationKeysPublic.HADOOP_SECURITY_IMPERSONATION_PROVIDER_CLASS,
+
"org.apache.hadoop.security.authorize.TestProxyUsers$TestDummyImpersonationProvider");
+ ProxyUsers.refreshSuperUserGroupsConfiguration(conf);
+
+ // First try proxying a group that's allowed
+ UserGroupInformation realUserUgi = UserGroupInformation
+ .createUserForTesting(REAL_USER_NAME, SUDO_GROUP_NAMES);
+ UserGroupInformation proxyUserUgi =
UserGroupInformation.createProxyUserForTesting(
+ PROXY_USER_NAME, realUserUgi, GROUP_NAMES);
+
+ // From good IP
+ assertAuthorized(proxyUserUgi, "1.2.3.4");
+ // From bad IP
+ assertAuthorized(proxyUserUgi, "1.2.3.5");
+
+ // Now try proxying a group that's not allowed
+ realUserUgi = UserGroupInformation
+ .createUserForTesting(REAL_USER_NAME, GROUP_NAMES);
+ proxyUserUgi = UserGroupInformation.createProxyUserForTesting(
+ PROXY_USER_NAME, realUserUgi, GROUP_NAMES);
+
+ // From good IP
+ assertNotAuthorized(proxyUserUgi, "1.2.3.4");
+ // From bad IP
+ assertNotAuthorized(proxyUserUgi, "1.2.3.5");
+ }
+
private void assertNotAuthorized(UserGroupInformation proxyUgi, String host)
{
try {
@@ -254,4 +380,32 @@ public class TestProxyUsers {
fail("Did not allow authorization of " + proxyUgi + " from " + host);
}
}
+
+ static class TestDummyImpersonationProvider implements ImpersonationProvider
{
+ /**
+ * Authorize a user (superuser) to impersonate another user (user1) if the
+ * superuser belongs to the group "sudo_user1" .
+ */
+
+ public void authorize(UserGroupInformation user,
+ String remoteAddress) throws AuthorizationException{
+ UserGroupInformation superUser = user.getRealUser();
+
+ String sudoGroupName = "sudo_" + user.getShortUserName();
+ if (!Arrays.asList(superUser.getGroupNames()).contains(sudoGroupName)){
+ throw new AuthorizationException("User: " + superUser.getUserName()
+ + " is not allowed to impersonate " + user.getUserName());
+ }
+ }
+
+ @Override
+ public void setConf(Configuration conf) {
+
+ }
+
+ @Override
+ public Configuration getConf() {
+ return null;
+ }
+ }
}