diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java index 0a11948..4c132ca 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-api/src/main/java/org/apache/hadoop/yarn/conf/YarnConfiguration.java @@ -816,6 +816,15 @@ public static final String DEFAULT_NM_NONSECURE_MODE_LOCAL_USER = "nobody"; /** + * Should containers be impersonated in insecure mode. + * If true, then nonsecure-mode.local-user used, and real user otherwise. + */ + public static final String NM_NONSECURE_MODE_IMPERSONATE = NM_PREFIX + + "linux-container-executor.nonsecure-mode.impersonate"; + + public static final boolean DEFAULT_NM_NONSECURE_MODE_IMPERSONATE = true; + + /** * The allowed pattern for UNIX user names enforced by * Linux-container-executor when used in nonsecure mode (use case for this * is using cgroups). The default value is taken from /usr/sbin/adduser diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java index cbdcb13..59845a9 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/LinuxContainerExecutor.java @@ -52,6 +52,7 @@ private String nonsecureLocalUser; private Pattern nonsecureLocalUserPattern; + private boolean nonsecureImpersonate; private String containerExecutorExe; private LCEResourcesHandler resourcesHandler; private boolean containerSchedPriorityIsSet = false; @@ -74,6 +75,9 @@ public void setConf(Configuration conf) { .getInt(YarnConfiguration.NM_CONTAINER_EXECUTOR_SCHED_PRIORITY, YarnConfiguration.DEFAULT_NM_CONTAINER_EXECUTOR_SCHED_PRIORITY); } + nonsecureImpersonate = conf.getBoolean( + YarnConfiguration.NM_NONSECURE_MODE_IMPERSONATE, + YarnConfiguration.DEFAULT_NM_NONSECURE_MODE_IMPERSONATE); nonsecureLocalUser = conf.get( YarnConfiguration.NM_NONSECURE_MODE_LOCAL_USER_KEY, YarnConfiguration.DEFAULT_NM_NONSECURE_MODE_LOCAL_USER); @@ -91,7 +95,10 @@ void verifyUsernamePattern(String user) { } String getRunAsUser(String user) { - return UserGroupInformation.isSecurityEnabled() ? user : nonsecureLocalUser; + if (!nonsecureImpersonate || UserGroupInformation.isSecurityEnabled()) + return user; + else + return nonsecureLocalUser; } /** diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutor.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutor.java index f840730..b697898 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutor.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/TestLinuxContainerExecutor.java @@ -279,6 +279,12 @@ public void testLocalUser() throws Exception { lce.setConf(conf); Assert.assertEquals("bar", lce.getRunAsUser("foo")); + //nonsecure impersonate + conf.set(YarnConfiguration.NM_NONSECURE_MODE_IMPERSONATE, "false"); + lce = new LinuxContainerExecutor(); + lce.setConf(conf); + Assert.assertEquals("foo", lce.getRunAsUser("foo")); + //secure conf = new YarnConfiguration(); conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHENTICATION, diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMAppManager.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMAppManager.java index 51024cf..abd3e94 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMAppManager.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMAppManager.java @@ -27,6 +27,7 @@ import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.io.DataInputByteBuffer; import org.apache.hadoop.security.Credentials; +import org.apache.hadoop.security.Groups; import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.util.StringUtils; import org.apache.hadoop.yarn.api.records.ApplicationId; @@ -289,6 +290,26 @@ protected void submitApplication( throw RPCUtil.getRemoteException(e); } } else { + // ensure that user actually exists in case of applications running + // under real user, + boolean impersonate = conf.getBoolean( + YarnConfiguration.NM_NONSECURE_MODE_IMPERSONATE, + YarnConfiguration.DEFAULT_NM_NONSECURE_MODE_IMPERSONATE); + if (!impersonate) { + try { + Groups.getUserToGroupsMappingService().getGroups(user); + } catch (IOException e) { + LOG.warn( + "Unknown user " + user, e); + // Sending APP_REJECTED is fine, since we assume that the + // RMApp is in NEW state and thus we haven't yet informed the + // scheduler about the existence of the application + assert application.getState() == RMAppState.NEW; + this.rmContext.getDispatcher().getEventHandler().handle( + new RMAppRejectedEvent(applicationId, "Unknown user " + user)); + throw RPCUtil.getRemoteException(e); + } + } // Dispatcher is not yet started at this time, so these START events // enqueued should be guaranteed to be first processed when dispatcher // gets started.