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 1a5f90a..7c57aa5 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 @@ -728,6 +728,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 0b1af0d..a132126 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; @@ -73,6 +74,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); @@ -90,7 +94,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 74452c9..8faafdf 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 7dbc4cc..27a0c8b 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; @@ -282,7 +283,7 @@ protected void submitApplication( return; } } - + if (UserGroupInformation.isSecurityEnabled()) { Credentials credentials = null; try { @@ -302,6 +303,26 @@ protected void submitApplication( applicationId, credentials, submissionContext.getCancelTokensWhenComplete(), isRecovered); } 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); + } + } this.rmContext.getDispatcher().getEventHandler() .handle(new RMAppEvent(applicationId, isRecovered ? RMAppEventType.RECOVER : RMAppEventType.START));