HADOOP-9035. Generalize setup of LoginContext (daryn via bobby)
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1410018 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
96f28d878e
commit
86ce5f6c91
|
@ -369,6 +369,8 @@ Release 2.0.3-alpha - Unreleased
|
||||||
|
|
||||||
HADOO-8998. set Cache-Control no-cache header on all dynamic content. (tucu)
|
HADOO-8998. set Cache-Control no-cache header on all dynamic content. (tucu)
|
||||||
|
|
||||||
|
HADOOP-9035. Generalize setup of LoginContext (daryn via bobby)
|
||||||
|
|
||||||
OPTIMIZATIONS
|
OPTIMIZATIONS
|
||||||
|
|
||||||
HADOOP-8866. SampleQuantiles#query is O(N^2) instead of O(N). (Andrew Wang
|
HADOOP-8866. SampleQuantiles#query is O(N^2) instead of O(N). (Andrew Wang
|
||||||
|
|
|
@ -294,14 +294,15 @@ public class Client {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AuthenticationMethod authentication;
|
||||||
if (token != null) {
|
if (token != null) {
|
||||||
authMethod = AuthenticationMethod.TOKEN.getAuthMethod();
|
authentication = AuthenticationMethod.TOKEN;
|
||||||
} else if (UserGroupInformation.isSecurityEnabled()) {
|
} else if (ticket != null) {
|
||||||
// eventually just use the ticket's authMethod
|
authentication = ticket.getRealAuthenticationMethod();
|
||||||
authMethod = AuthMethod.KERBEROS;
|
} else { // this only happens in lazy tests
|
||||||
} else {
|
authentication = AuthenticationMethod.SIMPLE;
|
||||||
authMethod = AuthMethod.SIMPLE;
|
|
||||||
}
|
}
|
||||||
|
authMethod = authentication.getAuthMethod();
|
||||||
|
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
LOG.debug("Use " + authMethod + " authentication for protocol "
|
LOG.debug("Use " + authMethod + " authentication for protocol "
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
*/
|
*/
|
||||||
package org.apache.hadoop.security;
|
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;
|
||||||
import static org.apache.hadoop.fs.CommonConfigurationKeys.HADOOP_KERBEROS_MIN_SECONDS_BEFORE_RELOGIN_DEFAULT;
|
import static org.apache.hadoop.fs.CommonConfigurationKeys.HADOOP_KERBEROS_MIN_SECONDS_BEFORE_RELOGIN_DEFAULT;
|
||||||
|
|
||||||
|
@ -133,7 +132,7 @@ public class UserGroupInformation {
|
||||||
}
|
}
|
||||||
Principal user = null;
|
Principal user = null;
|
||||||
// if we are using kerberos, try it out
|
// if we are using kerberos, try it out
|
||||||
if (useKerberos) {
|
if (isAuthenticationMethodEnabled(AuthenticationMethod.KERBEROS)) {
|
||||||
user = getCanonicalUser(KerberosPrincipal.class);
|
user = getCanonicalUser(KerberosPrincipal.class);
|
||||||
if (LOG.isDebugEnabled()) {
|
if (LOG.isDebugEnabled()) {
|
||||||
LOG.debug("using kerberos user:"+user);
|
LOG.debug("using kerberos user:"+user);
|
||||||
|
@ -191,8 +190,8 @@ public class UserGroupInformation {
|
||||||
static UgiMetrics metrics = UgiMetrics.create();
|
static UgiMetrics metrics = UgiMetrics.create();
|
||||||
/** Are the static variables that depend on configuration initialized? */
|
/** Are the static variables that depend on configuration initialized? */
|
||||||
private static boolean isInitialized = false;
|
private static boolean isInitialized = false;
|
||||||
/** Should we use Kerberos configuration? */
|
/** The auth method to use */
|
||||||
private static boolean useKerberos;
|
private static AuthenticationMethod authenticationMethod;
|
||||||
/** Server-side groups fetching service */
|
/** Server-side groups fetching service */
|
||||||
private static Groups groups;
|
private static Groups groups;
|
||||||
/** Min time (in seconds) before relogin for Kerberos */
|
/** Min time (in seconds) before relogin for Kerberos */
|
||||||
|
@ -237,20 +236,7 @@ public class UserGroupInformation {
|
||||||
* @param conf the configuration to use
|
* @param conf the configuration to use
|
||||||
*/
|
*/
|
||||||
private static synchronized void initUGI(Configuration conf) {
|
private static synchronized void initUGI(Configuration conf) {
|
||||||
AuthenticationMethod auth = SecurityUtil.getAuthenticationMethod(conf);
|
authenticationMethod = 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);
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
kerberosMinSecondsBeforeRelogin = 1000L * conf.getLong(
|
kerberosMinSecondsBeforeRelogin = 1000L * conf.getLong(
|
||||||
HADOOP_KERBEROS_MIN_SECONDS_BEFORE_RELOGIN,
|
HADOOP_KERBEROS_MIN_SECONDS_BEFORE_RELOGIN,
|
||||||
|
@ -288,8 +274,14 @@ public class UserGroupInformation {
|
||||||
* @return true if UGI is working in a secure environment
|
* @return true if UGI is working in a secure environment
|
||||||
*/
|
*/
|
||||||
public static boolean isSecurityEnabled() {
|
public static boolean isSecurityEnabled() {
|
||||||
|
return !isAuthenticationMethodEnabled(AuthenticationMethod.SIMPLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@InterfaceAudience.Private
|
||||||
|
@InterfaceStability.Evolving
|
||||||
|
private static boolean isAuthenticationMethodEnabled(AuthenticationMethod method) {
|
||||||
ensureInitialized();
|
ensureInitialized();
|
||||||
return useKerberos;
|
return (authenticationMethod == method);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -585,7 +577,7 @@ public class UserGroupInformation {
|
||||||
@InterfaceStability.Evolving
|
@InterfaceStability.Evolving
|
||||||
public static UserGroupInformation getUGIFromTicketCache(
|
public static UserGroupInformation getUGIFromTicketCache(
|
||||||
String ticketCache, String user) throws IOException {
|
String ticketCache, String user) throws IOException {
|
||||||
if (!isSecurityEnabled()) {
|
if (!isAuthenticationMethodEnabled(AuthenticationMethod.KERBEROS)) {
|
||||||
return getBestUGI(null, user);
|
return getBestUGI(null, user);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
|
@ -638,19 +630,12 @@ public class UserGroupInformation {
|
||||||
public synchronized
|
public synchronized
|
||||||
static UserGroupInformation getLoginUser() throws IOException {
|
static UserGroupInformation getLoginUser() throws IOException {
|
||||||
if (loginUser == null) {
|
if (loginUser == null) {
|
||||||
|
ensureInitialized();
|
||||||
try {
|
try {
|
||||||
Subject subject = new Subject();
|
Subject subject = new Subject();
|
||||||
LoginContext login;
|
LoginContext login =
|
||||||
AuthenticationMethod authenticationMethod;
|
newLoginContext(authenticationMethod.getLoginAppName(),
|
||||||
if (isSecurityEnabled()) {
|
|
||||||
authenticationMethod = AuthenticationMethod.KERBEROS;
|
|
||||||
login = newLoginContext(HadoopConfiguration.USER_KERBEROS_CONFIG_NAME,
|
|
||||||
subject, new HadoopConfiguration());
|
subject, new HadoopConfiguration());
|
||||||
} else {
|
|
||||||
authenticationMethod = AuthenticationMethod.SIMPLE;
|
|
||||||
login = newLoginContext(HadoopConfiguration.SIMPLE_CONFIG_NAME,
|
|
||||||
subject, new HadoopConfiguration());
|
|
||||||
}
|
|
||||||
login.login();
|
login.login();
|
||||||
loginUser = new UserGroupInformation(subject);
|
loginUser = new UserGroupInformation(subject);
|
||||||
loginUser.setLogin(login);
|
loginUser.setLogin(login);
|
||||||
|
@ -675,6 +660,14 @@ public class UserGroupInformation {
|
||||||
return loginUser;
|
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?
|
* Is this user logged in from a keytab file?
|
||||||
* @return true if the credentials are 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 {
|
public static enum AuthenticationMethod {
|
||||||
// currently we support only one auth per method, but eventually a
|
// currently we support only one auth per method, but eventually a
|
||||||
// subtype is needed to differentiate, ex. if digest is token or ldap
|
// subtype is needed to differentiate, ex. if digest is token or ldap
|
||||||
SIMPLE(AuthMethod.SIMPLE),
|
SIMPLE(AuthMethod.SIMPLE,
|
||||||
KERBEROS(AuthMethod.KERBEROS),
|
HadoopConfiguration.SIMPLE_CONFIG_NAME),
|
||||||
|
KERBEROS(AuthMethod.KERBEROS,
|
||||||
|
HadoopConfiguration.USER_KERBEROS_CONFIG_NAME),
|
||||||
TOKEN(AuthMethod.DIGEST),
|
TOKEN(AuthMethod.DIGEST),
|
||||||
CERTIFICATE(null),
|
CERTIFICATE(null),
|
||||||
KERBEROS_SSL(null),
|
KERBEROS_SSL(null),
|
||||||
PROXY(null);
|
PROXY(null);
|
||||||
|
|
||||||
private final AuthMethod authMethod;
|
private final AuthMethod authMethod;
|
||||||
|
private final String loginAppName;
|
||||||
|
|
||||||
private AuthenticationMethod(AuthMethod authMethod) {
|
private AuthenticationMethod(AuthMethod authMethod) {
|
||||||
|
this(authMethod, null);
|
||||||
|
}
|
||||||
|
private AuthenticationMethod(AuthMethod authMethod, String loginAppName) {
|
||||||
this.authMethod = authMethod;
|
this.authMethod = authMethod;
|
||||||
|
this.loginAppName = loginAppName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AuthMethod getAuthMethod() {
|
public AuthMethod getAuthMethod() {
|
||||||
return authMethod;
|
return authMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getLoginAppName() {
|
||||||
|
if (loginAppName == null) {
|
||||||
|
throw new UnsupportedOperationException(
|
||||||
|
this + " login authentication is not supported");
|
||||||
|
}
|
||||||
|
return loginAppName;
|
||||||
|
}
|
||||||
|
|
||||||
public static AuthenticationMethod valueOf(AuthMethod authMethod) {
|
public static AuthenticationMethod valueOf(AuthMethod authMethod) {
|
||||||
for (AuthenticationMethod value : values()) {
|
for (AuthenticationMethod value : values()) {
|
||||||
if (value.getAuthMethod() == authMethod) {
|
if (value.getAuthMethod() == authMethod) {
|
||||||
|
@ -1335,6 +1344,20 @@ public class UserGroupInformation {
|
||||||
return user.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
|
* Returns the authentication method of a ugi. If the authentication method is
|
||||||
* PROXY, returns the authentication method of the real user.
|
* PROXY, returns the authentication method of the real user.
|
||||||
|
|
|
@ -70,16 +70,75 @@ public class TestUserGroupInformation {
|
||||||
/** configure ugi */
|
/** configure ugi */
|
||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void setup() {
|
public static void setup() {
|
||||||
|
javax.security.auth.login.Configuration.setConfiguration(
|
||||||
|
new DummyLoginConfiguration());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setupUgi() {
|
||||||
conf = new Configuration();
|
conf = new Configuration();
|
||||||
conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTH_TO_LOCAL,
|
conf.set(CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTH_TO_LOCAL,
|
||||||
"RULE:[2:$1@$0](.*@HADOOP.APACHE.ORG)s/@.*//" +
|
"RULE:[2:$1@$0](.*@HADOOP.APACHE.ORG)s/@.*//" +
|
||||||
"RULE:[1:$1@$0](.*@HADOOP.APACHE.ORG)s/@.*//"
|
"RULE:[1:$1@$0](.*@HADOOP.APACHE.ORG)s/@.*//"
|
||||||
+ "DEFAULT");
|
+ "DEFAULT");
|
||||||
UserGroupInformation.setConfiguration(conf);
|
UserGroupInformation.setConfiguration(conf);
|
||||||
javax.security.auth.login.Configuration.setConfiguration(
|
UserGroupInformation.setLoginUser(null);
|
||||||
new DummyLoginConfiguration());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@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 login method */
|
||||||
@Test
|
@Test
|
||||||
public void testLogin() throws Exception {
|
public void testLogin() throws Exception {
|
||||||
|
|
Loading…
Reference in New Issue