YARN-2715. Fixed ResourceManager to respect common configurations for proxy users/groups beyond just the YARN level config. Contributed by Zhijie Shen.

This commit is contained in:
Vinod Kumar Vavilapalli 2014-10-21 20:09:40 -07:00
parent b2942762d7
commit c0e034336c
9 changed files with 184 additions and 12 deletions

View File

@ -622,6 +622,9 @@ Release 2.6.0 - UNRELEASED
test-failures: added a dummy in-memory labels-manager. (Wangda Tan via test-failures: added a dummy in-memory labels-manager. (Wangda Tan via
vinodkv) vinodkv)
YARN-2715. Fixed ResourceManager to respect common configurations for proxy
users/groups beyond just the YARN level config. (Zhijie Shen via vinodkv)
BREAKDOWN OF YARN-1051 SUBTASKS AND RELATED JIRAS BREAKDOWN OF YARN-1051 SUBTASKS AND RELATED JIRAS
YARN-1707. Introduce APIs to add/remove/resize queues in the YARN-1707. Introduce APIs to add/remove/resize queues in the

View File

@ -31,6 +31,7 @@ import org.apache.hadoop.classification.InterfaceStability.Unstable;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.http.HttpConfig; import org.apache.hadoop.http.HttpConfig;
import org.apache.hadoop.net.NetUtils; import org.apache.hadoop.net.NetUtils;
import org.apache.hadoop.security.authorize.ProxyUsers;
import org.apache.hadoop.util.StringUtils; import org.apache.hadoop.util.StringUtils;
import org.apache.hadoop.yarn.api.ApplicationConstants; import org.apache.hadoop.yarn.api.ApplicationConstants;
@ -560,6 +561,11 @@ public class YarnConfiguration extends Configuration {
public static final String DEFAULT_RM_NODEMANAGER_MINIMUM_VERSION = public static final String DEFAULT_RM_NODEMANAGER_MINIMUM_VERSION =
"NONE"; "NONE";
/**
* RM proxy users' prefix
*/
public static final String RM_PROXY_USER_PREFIX = RM_PREFIX + "proxyuser.";
//////////////////////////////// ////////////////////////////////
// Node Manager Configs // Node Manager Configs
//////////////////////////////// ////////////////////////////////

View File

@ -35,6 +35,7 @@ import org.apache.hadoop.security.SecurityUtil;
import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.authentication.server.AuthenticationFilter; import org.apache.hadoop.security.authentication.server.AuthenticationFilter;
import org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler; import org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler;
import org.apache.hadoop.security.authorize.ProxyUsers;
import org.apache.hadoop.security.token.delegation.web.DelegationTokenAuthenticationHandler; import org.apache.hadoop.security.token.delegation.web.DelegationTokenAuthenticationHandler;
import org.apache.hadoop.yarn.security.client.RMDelegationTokenIdentifier; import org.apache.hadoop.yarn.security.client.RMDelegationTokenIdentifier;
@ -42,14 +43,12 @@ import org.apache.hadoop.yarn.security.client.RMDelegationTokenIdentifier;
public class RMAuthenticationFilterInitializer extends FilterInitializer { public class RMAuthenticationFilterInitializer extends FilterInitializer {
String configPrefix; String configPrefix;
String proxyPrefix;
String signatureSecretFileProperty; String signatureSecretFileProperty;
String kerberosPrincipalProperty; String kerberosPrincipalProperty;
String cookiePath; String cookiePath;
public RMAuthenticationFilterInitializer() { public RMAuthenticationFilterInitializer() {
this.configPrefix = "hadoop.http.authentication."; this.configPrefix = "hadoop.http.authentication.";
this.proxyPrefix = "yarn.resourcemanager.webapp.proxyuser.";
this.signatureSecretFileProperty = this.signatureSecretFileProperty =
AuthenticationFilter.SIGNATURE_SECRET + ".file"; AuthenticationFilter.SIGNATURE_SECRET + ".file";
this.kerberosPrincipalProperty = KerberosAuthenticationHandler.PRINCIPAL; this.kerberosPrincipalProperty = KerberosAuthenticationHandler.PRINCIPAL;
@ -62,15 +61,18 @@ public class RMAuthenticationFilterInitializer extends FilterInitializer {
// setting the cookie path to root '/' so it is used for all resources. // setting the cookie path to root '/' so it is used for all resources.
filterConfig.put(AuthenticationFilter.COOKIE_PATH, cookiePath); filterConfig.put(AuthenticationFilter.COOKIE_PATH, cookiePath);
// Before conf object is passed in, RM has already processed it and used RM
// specific configs to overwrite hadoop common ones. Hence we just need to
// source hadoop.proxyuser configs here.
for (Map.Entry<String, String> entry : conf) { for (Map.Entry<String, String> entry : conf) {
String propName = entry.getKey(); String propName = entry.getKey();
if (propName.startsWith(configPrefix)) { if (propName.startsWith(configPrefix)) {
String value = conf.get(propName); String value = conf.get(propName);
String name = propName.substring(configPrefix.length()); String name = propName.substring(configPrefix.length());
filterConfig.put(name, value); filterConfig.put(name, value);
} else if (propName.startsWith(proxyPrefix)) { } else if (propName.startsWith(ProxyUsers.CONF_HADOOP_PROXYUSER)) {
String value = conf.get(propName); String value = conf.get(propName);
String name = propName.substring("yarn.resourcemanager.webapp.".length()); String name = propName.substring("hadoop.".length());
filterConfig.put(name, value); filterConfig.put(name, value);
} }
} }

View File

@ -421,9 +421,13 @@ public class AdminService extends CompositeService implements
throwStandbyException(); throwStandbyException();
} }
// Accept hadoop common configs in core-site.xml as well as RM specific
// configurations in yarn-site.xml
Configuration conf = Configuration conf =
getConfiguration(new Configuration(false), getConfiguration(new Configuration(false),
YarnConfiguration.CORE_SITE_CONFIGURATION_FILE); YarnConfiguration.CORE_SITE_CONFIGURATION_FILE,
YarnConfiguration.YARN_SITE_CONFIGURATION_FILE);
RMServerUtils.processRMProxyUsersConf(conf);
ProxyUsers.refreshSuperUserGroupsConfiguration(conf); ProxyUsers.refreshSuperUserGroupsConfiguration(conf);
RMAuditLogger.logSuccess(user.getShortUserName(), RMAuditLogger.logSuccess(user.getShortUserName(),
argName, "AdminService"); argName, "AdminService");
@ -594,11 +598,13 @@ public class AdminService extends CompositeService implements
} }
private synchronized Configuration getConfiguration(Configuration conf, private synchronized Configuration getConfiguration(Configuration conf,
String confFileName) throws YarnException, IOException { String... confFileNames) throws YarnException, IOException {
InputStream confFileInputStream = this.rmContext.getConfigurationProvider() for (String confFileName : confFileNames) {
.getConfigurationInputStream(conf, confFileName); InputStream confFileInputStream = this.rmContext.getConfigurationProvider()
if (confFileInputStream != null) { .getConfigurationInputStream(conf, confFileName);
conf.addResource(confFileInputStream); if (confFileInputStream != null) {
conf.addResource(confFileInputStream);
}
} }
return conf; return conf;
} }

View File

@ -21,12 +21,16 @@ package org.apache.hadoop.yarn.server.resourcemanager;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.AccessControlException; import org.apache.hadoop.security.AccessControlException;
import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.authorize.AccessControlList; import org.apache.hadoop.security.authorize.AccessControlList;
import org.apache.hadoop.security.authorize.ProxyUsers;
import org.apache.hadoop.yarn.api.records.ApplicationAttemptId; import org.apache.hadoop.yarn.api.records.ApplicationAttemptId;
import org.apache.hadoop.yarn.api.records.ApplicationResourceUsageReport; import org.apache.hadoop.yarn.api.records.ApplicationResourceUsageReport;
import org.apache.hadoop.yarn.api.records.ContainerId; import org.apache.hadoop.yarn.api.records.ContainerId;
@ -36,6 +40,7 @@ import org.apache.hadoop.yarn.api.records.ResourceBlacklistRequest;
import org.apache.hadoop.yarn.api.records.ResourceRequest; import org.apache.hadoop.yarn.api.records.ResourceRequest;
import org.apache.hadoop.yarn.api.records.YarnApplicationAttemptState; import org.apache.hadoop.yarn.api.records.YarnApplicationAttemptState;
import org.apache.hadoop.yarn.api.records.YarnApplicationState; import org.apache.hadoop.yarn.api.records.YarnApplicationState;
import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.apache.hadoop.yarn.exceptions.InvalidContainerReleaseException; import org.apache.hadoop.yarn.exceptions.InvalidContainerReleaseException;
import org.apache.hadoop.yarn.exceptions.InvalidResourceBlacklistRequestException; import org.apache.hadoop.yarn.exceptions.InvalidResourceBlacklistRequestException;
import org.apache.hadoop.yarn.exceptions.InvalidResourceRequestException; import org.apache.hadoop.yarn.exceptions.InvalidResourceRequestException;
@ -248,4 +253,26 @@ public class RMServerUtils {
BuilderUtils.newApplicationResourceUsageReport(-1, -1, BuilderUtils.newApplicationResourceUsageReport(-1, -1,
Resources.createResource(-1, -1), Resources.createResource(-1, -1), Resources.createResource(-1, -1), Resources.createResource(-1, -1),
Resources.createResource(-1, -1), 0, 0); Resources.createResource(-1, -1), 0, 0);
/**
* Find all configs whose name starts with
* YarnConfiguration.RM_PROXY_USER_PREFIX, and add a record for each one by
* replacing the prefix with ProxyUsers.CONF_HADOOP_PROXYUSER
*/
public static void processRMProxyUsersConf(Configuration conf) {
Map<String, String> rmProxyUsers = new HashMap<String, String>();
for (Map.Entry<String, String> entry : conf) {
String propName = entry.getKey();
if (propName.startsWith(YarnConfiguration.RM_PROXY_USER_PREFIX)) {
rmProxyUsers.put(ProxyUsers.CONF_HADOOP_PROXYUSER + "." +
propName.substring(YarnConfiguration.RM_PROXY_USER_PREFIX.length()),
entry.getValue());
}
}
for (Map.Entry<String, String> entry : rmProxyUsers.entrySet()) {
conf.set(entry.getKey(), entry.getValue());
}
}
} }

View File

@ -23,7 +23,9 @@ import java.io.InputStream;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.security.PrivilegedExceptionAction; import java.security.PrivilegedExceptionAction;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue; import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
@ -212,6 +214,9 @@ public class ResourceManager extends CompositeService implements Recoverable {
.refresh(); .refresh();
// Do refreshSuperUserGroupsConfiguration with loaded core-site.xml // Do refreshSuperUserGroupsConfiguration with loaded core-site.xml
// Or use RM specific configurations to overwrite the common ones first
// if they exist
RMServerUtils.processRMProxyUsersConf(conf);
ProxyUsers.refreshSuperUserGroupsConfiguration(this.conf); ProxyUsers.refreshSuperUserGroupsConfiguration(this.conf);
// load yarn-site.xml // load yarn-site.xml

View File

@ -357,6 +357,24 @@ public class TestRMAdminService {
.get("hadoop.proxyuser.test.hosts").size() == 1); .get("hadoop.proxyuser.test.hosts").size() == 1);
Assert.assertTrue(ProxyUsers.getDefaultImpersonationProvider().getProxyHosts() Assert.assertTrue(ProxyUsers.getDefaultImpersonationProvider().getProxyHosts()
.get("hadoop.proxyuser.test.hosts").contains("test_hosts")); .get("hadoop.proxyuser.test.hosts").contains("test_hosts"));
Configuration yarnConf = new Configuration(false);
yarnConf.set("yarn.resourcemanager.proxyuser.test.groups", "test_groups_1");
yarnConf.set("yarn.resourcemanager.proxyuser.test.hosts", "test_hosts_1");
uploadConfiguration(yarnConf, "yarn-site.xml");
// RM specific configs will overwrite the common ones
rm.adminService.refreshSuperUserGroupsConfiguration(
RefreshSuperUserGroupsConfigurationRequest.newInstance());
Assert.assertTrue(ProxyUsers.getDefaultImpersonationProvider().getProxyGroups()
.get("hadoop.proxyuser.test.groups").size() == 1);
Assert.assertTrue(ProxyUsers.getDefaultImpersonationProvider().getProxyGroups()
.get("hadoop.proxyuser.test.groups").contains("test_groups_1"));
Assert.assertTrue(ProxyUsers.getDefaultImpersonationProvider().getProxyHosts()
.get("hadoop.proxyuser.test.hosts").size() == 1);
Assert.assertTrue(ProxyUsers.getDefaultImpersonationProvider().getProxyHosts()
.get("hadoop.proxyuser.test.hosts").contains("test_hosts_1"));
} }
@Test @Test

View File

@ -0,0 +1,105 @@
/**
* 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.yarn.server.resourcemanager;
import java.util.Arrays;
import java.util.Collection;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.authorize.AuthorizationException;
import org.apache.hadoop.security.authorize.ProxyUsers;
import org.apache.hadoop.yarn.conf.YarnConfiguration;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
@RunWith(Parameterized.class)
public class TestRMProxyUsersConf {
private static final UserGroupInformation FOO_USER =
UserGroupInformation.createUserForTesting("foo", new String[] { "foo_group" });
private static final UserGroupInformation BAR_USER =
UserGroupInformation.createUserForTesting("bar", new String[] { "bar_group" });
@Parameterized.Parameters
public static Collection<Object[]> headers() {
return Arrays.asList(new Object[][] { { 0 }, { 1 }, { 2 } });
}
private Configuration conf;
public TestRMProxyUsersConf(int round) {
conf = new YarnConfiguration();
switch (round) {
case 0:
// hadoop.proxyuser prefix
conf.set("hadoop.proxyuser.foo.hosts", "localhost");
conf.set("hadoop.proxyuser.foo.users", "bar");
conf.set("hadoop.proxyuser.foo.groups", "bar_group");
break;
case 1:
// yarn.resourcemanager.proxyuser prefix
conf.set("yarn.resourcemanager.proxyuser.foo.hosts", "localhost");
conf.set("yarn.resourcemanager.proxyuser.foo.users", "bar");
conf.set("yarn.resourcemanager.proxyuser.foo.groups", "bar_group");
break;
case 2:
// hadoop.proxyuser prefix has been overwritten by
// yarn.resourcemanager.proxyuser prefix
conf.set("hadoop.proxyuser.foo.hosts", "xyz");
conf.set("hadoop.proxyuser.foo.users", "xyz");
conf.set("hadoop.proxyuser.foo.groups", "xyz");
conf.set("yarn.resourcemanager.proxyuser.foo.hosts", "localhost");
conf.set("yarn.resourcemanager.proxyuser.foo.users", "bar");
conf.set("yarn.resourcemanager.proxyuser.foo.groups", "bar_group");
break;
default:
break;
}
}
@Test
public void testProxyUserConfiguration() throws Exception {
MockRM rm = null;
try {
rm = new MockRM(conf);
rm.start();
// wait for web server starting
Thread.sleep(10000);
UserGroupInformation proxyUser =
UserGroupInformation.createProxyUser(
BAR_USER.getShortUserName(), FOO_USER);
try {
ProxyUsers.getDefaultImpersonationProvider().authorize(proxyUser,
"localhost");
} catch (AuthorizationException e) {
// Exception is not expected
Assert.fail();
}
} finally {
if (rm != null) {
rm.stop();
rm.close();
}
}
}
}

View File

@ -158,8 +158,8 @@ public class TestRMWebServicesDelegationTokenAuthentication {
rmconf.set(YarnConfiguration.NM_WEBAPP_SPNEGO_KEYTAB_FILE_KEY, rmconf.set(YarnConfiguration.NM_WEBAPP_SPNEGO_KEYTAB_FILE_KEY,
httpSpnegoKeytabFile.getAbsolutePath()); httpSpnegoKeytabFile.getAbsolutePath());
rmconf.setBoolean("mockrm.webapp.enabled", true); rmconf.setBoolean("mockrm.webapp.enabled", true);
rmconf.set("yarn.resourcemanager.webapp.proxyuser.client.hosts", "*"); rmconf.set("yarn.resourcemanager.proxyuser.client.hosts", "*");
rmconf.set("yarn.resourcemanager.webapp.proxyuser.client.groups", "*"); rmconf.set("yarn.resourcemanager.proxyuser.client.groups", "*");
UserGroupInformation.setConfiguration(rmconf); UserGroupInformation.setConfiguration(rmconf);
rm = new MockRM(rmconf); rm = new MockRM(rmconf);
rm.start(); rm.start();