svn merge -c 1457763 FIXES: HADOOP-9299. kerberos name resolution is kicking in even when kerberos is not configured (daryn)

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/branches/branch-2@1457770 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Daryn Sharp 2013-03-18 14:05:09 +00:00
parent 7319e42239
commit 8e2098fd2f
5 changed files with 192 additions and 55 deletions

View File

@ -383,9 +383,25 @@ public String getShortName() throws IOException {
* @param ruleString the rules string. * @param ruleString the rules string.
*/ */
public static void setRules(String ruleString) { public static void setRules(String ruleString) {
rules = parseRules(ruleString); rules = (ruleString != null) ? parseRules(ruleString) : null;
} }
/**
* Get the rules.
* @return String of configured rules, or null if not yet configured
*/
public static String getRules() {
String ruleString = null;
if (rules != null) {
StringBuilder sb = new StringBuilder();
for (Rule rule : rules) {
sb.append(rule.toString()).append("\n");
}
ruleString = sb.toString().trim();
}
return ruleString;
}
/** /**
* Indicates if the name rules have been set. * Indicates if the name rules have been set.
* *

View File

@ -85,6 +85,9 @@ Release 2.0.5-beta - UNRELEASED
HADOOP-9407. commons-daemon 1.0.3 dependency has bad group id causing HADOOP-9407. commons-daemon 1.0.3 dependency has bad group id causing
build issues. (Sangjin Lee via suresh) build issues. (Sangjin Lee via suresh)
HADOOP-9299. kerberos name resolution is kicking in even when kerberos
is not configured (daryn)
Release 2.0.4-alpha - UNRELEASED Release 2.0.4-alpha - UNRELEASED
INCOMPATIBLE CHANGES INCOMPATIBLE CHANGES

View File

@ -18,6 +18,8 @@
package org.apache.hadoop.security; package org.apache.hadoop.security;
import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTH_TO_LOCAL;
import java.io.IOException; import java.io.IOException;
import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceAudience;
@ -25,7 +27,6 @@
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.authentication.util.KerberosName; import org.apache.hadoop.security.authentication.util.KerberosName;
import org.apache.hadoop.security.authentication.util.KerberosUtil; import org.apache.hadoop.security.authentication.util.KerberosUtil;
import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
/** /**
* This class implements parsing and handling of Kerberos principal names. In * This class implements parsing and handling of Kerberos principal names. In
* particular, it splits them apart and translates them down into local * particular, it splits them apart and translates them down into local
@ -36,15 +37,6 @@
@InterfaceStability.Evolving @InterfaceStability.Evolving
public class HadoopKerberosName extends KerberosName { public class HadoopKerberosName extends KerberosName {
static {
try {
KerberosUtil.getDefaultRealm();
} catch (Exception ke) {
if(UserGroupInformation.isSecurityEnabled())
throw new IllegalArgumentException("Can't get Kerberos configuration",ke);
}
}
/** /**
* Create a name from the full Kerberos principal name. * Create a name from the full Kerberos principal name.
* @param name * @param name
@ -63,7 +55,23 @@ public HadoopKerberosName(String name) {
* @throws IOException * @throws IOException
*/ */
public static void setConfiguration(Configuration conf) throws IOException { public static void setConfiguration(Configuration conf) throws IOException {
String ruleString = conf.get(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTH_TO_LOCAL, "DEFAULT"); final String defaultRule;
switch (SecurityUtil.getAuthenticationMethod(conf)) {
case KERBEROS:
case KERBEROS_SSL:
try {
KerberosUtil.getDefaultRealm();
} catch (Exception ke) {
throw new IllegalArgumentException("Can't get Kerberos realm", ke);
}
defaultRule = "DEFAULT";
break;
default:
// just extract the simple user name
defaultRule = "RULE:[1:$1] RULE:[2:$1]";
break;
}
String ruleString = conf.get(HADOOP_SECURITY_AUTH_TO_LOCAL, defaultRule);
setRules(ruleString); setRules(ruleString);
} }

View File

@ -51,14 +51,12 @@
import org.apache.hadoop.classification.InterfaceAudience; import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceStability; import org.apache.hadoop.classification.InterfaceStability;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.Text; import org.apache.hadoop.io.Text;
import org.apache.hadoop.metrics2.annotation.Metric; import org.apache.hadoop.metrics2.annotation.Metric;
import org.apache.hadoop.metrics2.annotation.Metrics; import org.apache.hadoop.metrics2.annotation.Metrics;
import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem; import org.apache.hadoop.metrics2.lib.DefaultMetricsSystem;
import org.apache.hadoop.metrics2.lib.MutableRate; import org.apache.hadoop.metrics2.lib.MutableRate;
import org.apache.hadoop.security.SaslRpcServer.AuthMethod; import org.apache.hadoop.security.SaslRpcServer.AuthMethod;
import org.apache.hadoop.security.authentication.util.KerberosName;
import org.apache.hadoop.security.authentication.util.KerberosUtil; import org.apache.hadoop.security.authentication.util.KerberosUtil;
import org.apache.hadoop.security.token.Token; import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.security.token.TokenIdentifier; import org.apache.hadoop.security.token.TokenIdentifier;
@ -190,8 +188,6 @@ public boolean logout() throws LoginException {
/** Metrics to track UGI activity */ /** Metrics to track UGI activity */
static UgiMetrics metrics = UgiMetrics.create(); static UgiMetrics metrics = UgiMetrics.create();
/** Are the static variables that depend on configuration initialized? */
private static boolean isInitialized = false;
/** The auth method to use */ /** The auth method to use */
private static AuthenticationMethod authenticationMethod; private static AuthenticationMethod authenticationMethod;
/** Server-side groups fetching service */ /** Server-side groups fetching service */
@ -212,8 +208,8 @@ public boolean logout() throws LoginException {
* Must be called before useKerberos or groups is used. * Must be called before useKerberos or groups is used.
*/ */
private static synchronized void ensureInitialized() { private static synchronized void ensureInitialized() {
if (!isInitialized) { if (conf == null) {
initialize(new Configuration(), KerberosName.hasRulesBeenSet()); initialize(new Configuration(), false);
} }
} }
@ -221,30 +217,21 @@ private static synchronized void ensureInitialized() {
* Initialize UGI and related classes. * Initialize UGI and related classes.
* @param conf the configuration to use * @param conf the configuration to use
*/ */
private static synchronized void initialize(Configuration conf, boolean skipRulesSetting) { private static synchronized void initialize(Configuration conf,
initUGI(conf); boolean overrideNameRules) {
// give the configuration on how to translate Kerberos names
try {
if (!skipRulesSetting) {
HadoopKerberosName.setConfiguration(conf);
}
} catch (IOException ioe) {
throw new RuntimeException("Problem with Kerberos auth_to_local name " +
"configuration", ioe);
}
}
/**
* Set the configuration values for UGI.
* @param conf the configuration to use
*/
private static synchronized void initUGI(Configuration conf) {
authenticationMethod = SecurityUtil.getAuthenticationMethod(conf); authenticationMethod = SecurityUtil.getAuthenticationMethod(conf);
if (overrideNameRules || !HadoopKerberosName.hasRulesBeenSet()) {
try {
HadoopKerberosName.setConfiguration(conf);
} catch (IOException ioe) {
throw new RuntimeException(
"Problem with Kerberos auth_to_local name configuration", ioe);
}
}
// If we haven't set up testing groups, use the configuration to find it // If we haven't set up testing groups, use the configuration to find it
if (!(groups instanceof TestingGroups)) { if (!(groups instanceof TestingGroups)) {
groups = Groups.getUserToGroupsMappingService(conf); groups = Groups.getUserToGroupsMappingService(conf);
} }
isInitialized = true;
UserGroupInformation.conf = conf; UserGroupInformation.conf = conf;
} }
@ -257,7 +244,17 @@ private static synchronized void initUGI(Configuration conf) {
@InterfaceAudience.Public @InterfaceAudience.Public
@InterfaceStability.Evolving @InterfaceStability.Evolving
public static void setConfiguration(Configuration conf) { public static void setConfiguration(Configuration conf) {
initialize(conf, false); initialize(conf, true);
}
@InterfaceAudience.Private
@VisibleForTesting
static void reset() {
authenticationMethod = null;
conf = null;
groups = null;
setLoginUser(null);
HadoopKerberosName.setRules(null);
} }
/** /**

View File

@ -37,10 +37,12 @@
import org.apache.hadoop.io.Text; import org.apache.hadoop.io.Text;
import org.apache.hadoop.metrics2.MetricsRecordBuilder; import org.apache.hadoop.metrics2.MetricsRecordBuilder;
import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod; import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
import org.apache.hadoop.security.authentication.util.KerberosName;
import org.apache.hadoop.security.token.Token; import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.security.token.TokenIdentifier; import org.apache.hadoop.security.token.TokenIdentifier;
import static org.apache.hadoop.test.MetricsAsserts.*; import static org.apache.hadoop.test.MetricsAsserts.*;
import org.apache.hadoop.fs.CommonConfigurationKeysPublic; import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
import static org.apache.hadoop.fs.CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTH_TO_LOCAL;
public class TestUserGroupInformation { public class TestUserGroupInformation {
final private static String USER_NAME = "user1@HADOOP.APACHE.ORG"; final private static String USER_NAME = "user1@HADOOP.APACHE.ORG";
@ -71,17 +73,18 @@ public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
public static void setup() { public static void setup() {
javax.security.auth.login.Configuration.setConfiguration( javax.security.auth.login.Configuration.setConfiguration(
new DummyLoginConfiguration()); new DummyLoginConfiguration());
// doesn't matter what it is, but getGroups needs it set...
System.setProperty("hadoop.home.dir", "/tmp");
// fake the realm is kerberos is enabled
System.setProperty("java.security.krb5.kdc", "");
System.setProperty("java.security.krb5.realm", "DEFAULT.REALM");
} }
@Before @Before
public void setupUgi() { public void setupUgi() {
conf = new Configuration(); conf = new Configuration();
conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTH_TO_LOCAL, UserGroupInformation.reset();
"RULE:[2:$1@$0](.*@HADOOP.APACHE.ORG)s/@.*//" +
"RULE:[1:$1@$0](.*@HADOOP.APACHE.ORG)s/@.*//"
+ "DEFAULT");
UserGroupInformation.setConfiguration(conf); UserGroupInformation.setConfiguration(conf);
UserGroupInformation.setLoginUser(null);
} }
@After @After
@ -209,31 +212,141 @@ public Object run() throws IOException {
/** test constructor */ /** test constructor */
@Test @Test
public void testConstructor() throws Exception { public void testConstructor() throws Exception {
UserGroupInformation ugi = // security off, so default should just return simple name
UserGroupInformation.createUserForTesting("user2/cron@HADOOP.APACHE.ORG", testConstructorSuccess("user1", "user1");
GROUP_NAMES); testConstructorSuccess("user2@DEFAULT.REALM", "user2");
// make sure the short and full user names are correct testConstructorSuccess("user3/cron@DEFAULT.REALM", "user3");
assertEquals("user2/cron@HADOOP.APACHE.ORG", ugi.getUserName()); testConstructorSuccess("user4@OTHER.REALM", "user4");
assertEquals("user2", ugi.getShortUserName()); testConstructorSuccess("user5/cron@OTHER.REALM", "user5");
ugi = UserGroupInformation.createUserForTesting(USER_NAME, GROUP_NAMES); // failure test
assertEquals("user1", ugi.getShortUserName()); testConstructorFailures(null);
testConstructorFailures("");
}
/** test constructor */
@Test (timeout = 30000)
public void testConstructorWithRules() throws Exception {
// security off, but use rules if explicitly set
conf.set(HADOOP_SECURITY_AUTH_TO_LOCAL,
"RULE:[1:$1@$0](.*@OTHER.REALM)s/(.*)@.*/other-$1/");
UserGroupInformation.setConfiguration(conf);
testConstructorSuccess("user1", "user1");
testConstructorSuccess("user4@OTHER.REALM", "other-user4");
// failure test
testConstructorFailures("user2@DEFAULT.REALM");
testConstructorFailures("user3/cron@DEFAULT.REALM");
testConstructorFailures("user5/cron@OTHER.REALM");
testConstructorFailures(null);
testConstructorFailures("");
}
/** test constructor */
@Test (timeout = 30000)
public void testConstructorWithKerberos() throws Exception {
// security on, default is remove default realm
SecurityUtil.setAuthenticationMethod(AuthenticationMethod.KERBEROS, conf);
UserGroupInformation.setConfiguration(conf);
testConstructorSuccess("user1", "user1");
testConstructorSuccess("user2@DEFAULT.REALM", "user2");
testConstructorSuccess("user3/cron@DEFAULT.REALM", "user3");
// failure test
testConstructorFailures("user4@OTHER.REALM");
testConstructorFailures("user5/cron@OTHER.REALM");
testConstructorFailures(null);
testConstructorFailures("");
}
/** test constructor */
@Test (timeout = 30000)
public void testConstructorWithKerberosRules() throws Exception {
// security on, explicit rules
SecurityUtil.setAuthenticationMethod(AuthenticationMethod.KERBEROS, conf);
conf.set(HADOOP_SECURITY_AUTH_TO_LOCAL,
"RULE:[2:$1@$0](.*@OTHER.REALM)s/(.*)@.*/other-$1/" +
"RULE:[1:$1@$0](.*@OTHER.REALM)s/(.*)@.*/other-$1/" +
"DEFAULT");
UserGroupInformation.setConfiguration(conf);
testConstructorSuccess("user1", "user1");
testConstructorSuccess("user2@DEFAULT.REALM", "user2");
testConstructorSuccess("user3/cron@DEFAULT.REALM", "user3");
testConstructorSuccess("user4@OTHER.REALM", "other-user4");
testConstructorSuccess("user5/cron@OTHER.REALM", "other-user5");
// failure test // failure test
testConstructorFailures(null); testConstructorFailures(null);
testConstructorFailures(""); testConstructorFailures("");
} }
private void testConstructorSuccess(String principal, String shortName) {
UserGroupInformation ugi =
UserGroupInformation.createUserForTesting(principal, GROUP_NAMES);
// make sure the short and full user names are correct
assertEquals(principal, ugi.getUserName());
assertEquals(shortName, ugi.getShortUserName());
}
private void testConstructorFailures(String userName) { private void testConstructorFailures(String userName) {
boolean gotException = false;
try { try {
UserGroupInformation.createRemoteUser(userName); UserGroupInformation.createRemoteUser(userName);
} catch (Exception e) { fail("user:"+userName+" wasn't invalid");
gotException = true; } catch (IllegalArgumentException e) {
String expect = (userName == null || userName.isEmpty())
? "Null user" : "Illegal principal name "+userName;
assertEquals(expect, e.getMessage());
} }
assertTrue(gotException);
} }
@Test @Test
public void testSetConfigWithRules() {
String[] rules = { "RULE:[1:TEST1]", "RULE:[1:TEST2]", "RULE:[1:TEST3]" };
// explicitly set a rule
UserGroupInformation.reset();
assertFalse(KerberosName.hasRulesBeenSet());
KerberosName.setRules(rules[0]);
assertTrue(KerberosName.hasRulesBeenSet());
assertEquals(rules[0], KerberosName.getRules());
// implicit init should honor rules already being set
UserGroupInformation.createUserForTesting("someone", new String[0]);
assertEquals(rules[0], KerberosName.getRules());
// set conf, should override
conf.set(HADOOP_SECURITY_AUTH_TO_LOCAL, rules[1]);
UserGroupInformation.setConfiguration(conf);
assertEquals(rules[1], KerberosName.getRules());
// set conf, should again override
conf.set(HADOOP_SECURITY_AUTH_TO_LOCAL, rules[2]);
UserGroupInformation.setConfiguration(conf);
assertEquals(rules[2], KerberosName.getRules());
// implicit init should honor rules already being set
UserGroupInformation.createUserForTesting("someone", new String[0]);
assertEquals(rules[2], KerberosName.getRules());
}
@Test (timeout = 30000)
public void testEnsureInitWithRules() throws IOException {
String rules = "RULE:[1:RULE1]";
// trigger implicit init, rules should init
UserGroupInformation.reset();
assertFalse(KerberosName.hasRulesBeenSet());
UserGroupInformation.createUserForTesting("someone", new String[0]);
assertTrue(KerberosName.hasRulesBeenSet());
// set a rule, trigger implicit init, rule should not change
UserGroupInformation.reset();
KerberosName.setRules(rules);
assertTrue(KerberosName.hasRulesBeenSet());
assertEquals(rules, KerberosName.getRules());
UserGroupInformation.createUserForTesting("someone", new String[0]);
assertEquals(rules, KerberosName.getRules());
}
@Test (timeout = 30000)
public void testEquals() throws Exception { public void testEquals() throws Exception {
UserGroupInformation uugi = UserGroupInformation uugi =
UserGroupInformation.createUserForTesting(USER_NAME, GROUP_NAMES); UserGroupInformation.createUserForTesting(USER_NAME, GROUP_NAMES);