Author: bobby
Date: Thu Nov 15 21:14:37 2012
New Revision: 1410018
URL: http://svn.apache.org/viewvc?rev=1410018&view=rev
Log:
HADOOP-9035. Generalize setup of LoginContext (daryn via bobby)
Modified:
hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Client.java
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java
hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestUserGroupInformation.java
Modified: hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt?rev=1410018&r1=1410017&r2=1410018&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt (original)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/CHANGES.txt Thu Nov 15 21:14:37
2012
@@ -369,6 +369,8 @@ Release 2.0.3-alpha - Unreleased
HADOO-8998. set Cache-Control no-cache header on all dynamic content. (tucu)
+ HADOOP-9035. Generalize setup of LoginContext (daryn via bobby)
+
OPTIMIZATIONS
HADOOP-8866. SampleQuantiles#query is O(N^2) instead of O(N). (Andrew Wang
Modified: hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Client.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Client.java?rev=1410018&r1=1410017&r2=1410018&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Client.java
(original)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/ipc/Client.java
Thu Nov 15 21:14:37 2012
@@ -294,14 +294,15 @@ public class Client {
}
}
+ AuthenticationMethod authentication;
if (token != null) {
- authMethod = AuthenticationMethod.TOKEN.getAuthMethod();
- } else if (UserGroupInformation.isSecurityEnabled()) {
- // eventually just use the ticket's authMethod
- authMethod = AuthMethod.KERBEROS;
- } else {
- authMethod = AuthMethod.SIMPLE;
+ authentication = AuthenticationMethod.TOKEN;
+ } else if (ticket != null) {
+ authentication = ticket.getRealAuthenticationMethod();
+ } else { // this only happens in lazy tests
+ authentication = AuthenticationMethod.SIMPLE;
}
+ authMethod = authentication.getAuthMethod();
if (LOG.isDebugEnabled())
LOG.debug("Use " + authMethod + " authentication for protocol "
Modified: hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java?rev=1410018&r1=1410017&r2=1410018&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java
(original)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/UserGroupInformation.java
Thu Nov 15 21:14:37 2012
@@ -17,7 +17,6 @@
*/
package org.apache.hadoop.security;
-import static org.apache.hadoop.fs.CommonConfigurationKeys.HADOOP_SECURITY_AUTHENTICATION;
import static org.apache.hadoop.fs.CommonConfigurationKeys.HADOOP_KERBEROS_MIN_SECONDS_BEFORE_RELOGIN;
import static org.apache.hadoop.fs.CommonConfigurationKeys.HADOOP_KERBEROS_MIN_SECONDS_BEFORE_RELOGIN_DEFAULT;
@@ -133,7 +132,7 @@ public class UserGroupInformation {
}
Principal user = null;
// if we are using kerberos, try it out
- if (useKerberos) {
+ if (isAuthenticationMethodEnabled(AuthenticationMethod.KERBEROS)) {
user = getCanonicalUser(KerberosPrincipal.class);
if (LOG.isDebugEnabled()) {
LOG.debug("using kerberos user:"+user);
@@ -191,8 +190,8 @@ public class UserGroupInformation {
static UgiMetrics metrics = UgiMetrics.create();
/** Are the static variables that depend on configuration initialized? */
private static boolean isInitialized = false;
- /** Should we use Kerberos configuration? */
- private static boolean useKerberos;
+ /** The auth method to use */
+ private static AuthenticationMethod authenticationMethod;
/** Server-side groups fetching service */
private static Groups groups;
/** Min time (in seconds) before relogin for Kerberos */
@@ -237,20 +236,7 @@ public class UserGroupInformation {
* @param conf the configuration to use
*/
private static synchronized void initUGI(Configuration conf) {
- AuthenticationMethod auth = SecurityUtil.getAuthenticationMethod(conf);
- switch (auth) {
- case SIMPLE:
- case TOKEN:
- useKerberos = false;
- break;
- case KERBEROS:
- useKerberos = true;
- break;
- default:
- throw new IllegalArgumentException("Invalid attribute value for " +
- HADOOP_SECURITY_AUTHENTICATION +
- " of " + auth);
- }
+ authenticationMethod = SecurityUtil.getAuthenticationMethod(conf);
try {
kerberosMinSecondsBeforeRelogin = 1000L * conf.getLong(
HADOOP_KERBEROS_MIN_SECONDS_BEFORE_RELOGIN,
@@ -288,8 +274,14 @@ public class UserGroupInformation {
* @return true if UGI is working in a secure environment
*/
public static boolean isSecurityEnabled() {
+ return !isAuthenticationMethodEnabled(AuthenticationMethod.SIMPLE);
+ }
+
+ @InterfaceAudience.Private
+ @InterfaceStability.Evolving
+ private static boolean isAuthenticationMethodEnabled(AuthenticationMethod method) {
ensureInitialized();
- return useKerberos;
+ return (authenticationMethod == method);
}
/**
@@ -585,7 +577,7 @@ public class UserGroupInformation {
@InterfaceStability.Evolving
public static UserGroupInformation getUGIFromTicketCache(
String ticketCache, String user) throws IOException {
- if (!isSecurityEnabled()) {
+ if (!isAuthenticationMethodEnabled(AuthenticationMethod.KERBEROS)) {
return getBestUGI(null, user);
}
try {
@@ -638,19 +630,12 @@ public class UserGroupInformation {
public synchronized
static UserGroupInformation getLoginUser() throws IOException {
if (loginUser == null) {
+ ensureInitialized();
try {
Subject subject = new Subject();
- LoginContext login;
- AuthenticationMethod authenticationMethod;
- if (isSecurityEnabled()) {
- authenticationMethod = AuthenticationMethod.KERBEROS;
- login = newLoginContext(HadoopConfiguration.USER_KERBEROS_CONFIG_NAME,
- subject, new HadoopConfiguration());
- } else {
- authenticationMethod = AuthenticationMethod.SIMPLE;
- login = newLoginContext(HadoopConfiguration.SIMPLE_CONFIG_NAME,
- subject, new HadoopConfiguration());
- }
+ LoginContext login =
+ newLoginContext(authenticationMethod.getLoginAppName(),
+ subject, new HadoopConfiguration());
login.login();
loginUser = new UserGroupInformation(subject);
loginUser.setLogin(login);
@@ -675,6 +660,14 @@ public class UserGroupInformation {
return loginUser;
}
+ @InterfaceAudience.Private
+ @InterfaceStability.Unstable
+ synchronized static void setLoginUser(UserGroupInformation ugi) {
+ // if this is to become stable, should probably logout the currently
+ // logged in ugi if it's different
+ loginUser = ugi;
+ }
+
/**
* Is this user logged in from a keytab file?
* @return true if the credentials are from a keytab file.
@@ -1027,22 +1020,38 @@ public class UserGroupInformation {
public static enum AuthenticationMethod {
// currently we support only one auth per method, but eventually a
// subtype is needed to differentiate, ex. if digest is token or ldap
- SIMPLE(AuthMethod.SIMPLE),
- KERBEROS(AuthMethod.KERBEROS),
+ SIMPLE(AuthMethod.SIMPLE,
+ HadoopConfiguration.SIMPLE_CONFIG_NAME),
+ KERBEROS(AuthMethod.KERBEROS,
+ HadoopConfiguration.USER_KERBEROS_CONFIG_NAME),
TOKEN(AuthMethod.DIGEST),
CERTIFICATE(null),
KERBEROS_SSL(null),
PROXY(null);
private final AuthMethod authMethod;
+ private final String loginAppName;
+
private AuthenticationMethod(AuthMethod authMethod) {
+ this(authMethod, null);
+ }
+ private AuthenticationMethod(AuthMethod authMethod, String loginAppName) {
this.authMethod = authMethod;
+ this.loginAppName = loginAppName;
}
public AuthMethod getAuthMethod() {
return authMethod;
}
+ String getLoginAppName() {
+ if (loginAppName == null) {
+ throw new UnsupportedOperationException(
+ this + " login authentication is not supported");
+ }
+ return loginAppName;
+ }
+
public static AuthenticationMethod valueOf(AuthMethod authMethod) {
for (AuthenticationMethod value : values()) {
if (value.getAuthMethod() == authMethod) {
@@ -1334,7 +1343,21 @@ public class UserGroupInformation {
public synchronized AuthenticationMethod getAuthenticationMethod() {
return user.getAuthenticationMethod();
}
-
+
+ /**
+ * Get the authentication method from the real user's subject. If there
+ * is no real user, return the given user's authentication method.
+ *
+ * @return AuthenticationMethod in the subject, null if not present.
+ */
+ public synchronized AuthenticationMethod getRealAuthenticationMethod() {
+ UserGroupInformation ugi = getRealUser();
+ if (ugi == null) {
+ ugi = this;
+ }
+ return ugi.getAuthenticationMethod();
+ }
+
/**
* Returns the authentication method of a ugi. If the authentication method is
* PROXY, returns the authentication method of the real user.
Modified: hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestUserGroupInformation.java
URL: http://svn.apache.org/viewvc/hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestUserGroupInformation.java?rev=1410018&r1=1410017&r2=1410018&view=diff
==============================================================================
--- hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestUserGroupInformation.java
(original)
+++ hadoop/common/trunk/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/security/TestUserGroupInformation.java
Thu Nov 15 21:14:37 2012
@@ -70,16 +70,75 @@ public class TestUserGroupInformation {
/** configure ugi */
@BeforeClass
public static void setup() {
+ javax.security.auth.login.Configuration.setConfiguration(
+ new DummyLoginConfiguration());
+ }
+
+ @Before
+ public void setupUgi() {
conf = new Configuration();
conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTH_TO_LOCAL,
"RULE:[2:$1@$0](.*@HADOOP.APACHE.ORG)s/@.*//" +
"RULE:[1:$1@$0](.*@HADOOP.APACHE.ORG)s/@.*//"
+ "DEFAULT");
UserGroupInformation.setConfiguration(conf);
- javax.security.auth.login.Configuration.setConfiguration(
- new DummyLoginConfiguration());
+ UserGroupInformation.setLoginUser(null);
+ }
+
+ @After
+ public void resetUgi() {
+ UserGroupInformation.setLoginUser(null);
+ }
+
+ @Test
+ public void testSimpleLogin() throws IOException {
+ tryLoginAuthenticationMethod(AuthenticationMethod.SIMPLE, true);
+ }
+
+ @Test
+ public void testTokenLogin() throws IOException {
+ tryLoginAuthenticationMethod(AuthenticationMethod.TOKEN, false);
+ }
+
+ @Test
+ public void testProxyLogin() throws IOException {
+ tryLoginAuthenticationMethod(AuthenticationMethod.PROXY, false);
}
+ private void tryLoginAuthenticationMethod(AuthenticationMethod method,
+ boolean expectSuccess)
+ throws IOException {
+ SecurityUtil.setAuthenticationMethod(method, conf);
+ UserGroupInformation.setConfiguration(conf); // pick up changed auth
+
+ UserGroupInformation ugi = null;
+ Exception ex = null;
+ try {
+ ugi = UserGroupInformation.getLoginUser();
+ } catch (Exception e) {
+ ex = e;
+ }
+ if (expectSuccess) {
+ assertNotNull(ugi);
+ assertEquals(method, ugi.getAuthenticationMethod());
+ } else {
+ assertNotNull(ex);
+ assertEquals(UnsupportedOperationException.class, ex.getClass());
+ assertEquals(method + " login authentication is not supported",
+ ex.getMessage());
+ }
+ }
+
+ @Test
+ public void testGetRealAuthenticationMethod() {
+ UserGroupInformation ugi = UserGroupInformation.createRemoteUser("user1");
+ ugi.setAuthenticationMethod(AuthenticationMethod.SIMPLE);
+ assertEquals(AuthenticationMethod.SIMPLE, ugi.getAuthenticationMethod());
+ assertEquals(AuthenticationMethod.SIMPLE, ugi.getRealAuthenticationMethod());
+ ugi = UserGroupInformation.createProxyUser("user2", ugi);
+ assertEquals(AuthenticationMethod.PROXY, ugi.getAuthenticationMethod());
+ assertEquals(AuthenticationMethod.SIMPLE, ugi.getRealAuthenticationMethod());
+ }
/** Test login method */
@Test
public void testLogin() throws Exception {
|