HADOOP-10835. Implement HTTP proxyuser support in HTTP authentication client/server libraries. (tucu)
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1617384 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
b760f20af1
commit
6d7a6766bd
|
@ -127,6 +127,7 @@ public class AuthenticationFilter implements Filter {
|
|||
public static final String SIGNATURE_PROVIDER_ATTRIBUTE =
|
||||
"org.apache.hadoop.security.authentication.util.SignerSecretProvider";
|
||||
|
||||
private Properties config;
|
||||
private Signer signer;
|
||||
private SignerSecretProvider secretProvider;
|
||||
private AuthenticationHandler authHandler;
|
||||
|
@ -150,7 +151,7 @@ public class AuthenticationFilter implements Filter {
|
|||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
String configPrefix = filterConfig.getInitParameter(CONFIG_PREFIX);
|
||||
configPrefix = (configPrefix != null) ? configPrefix + "." : "";
|
||||
Properties config = getConfiguration(configPrefix, filterConfig);
|
||||
config = getConfiguration(configPrefix, filterConfig);
|
||||
String authHandlerName = config.getProperty(AUTH_TYPE, null);
|
||||
String authHandlerClassName;
|
||||
if (authHandlerName == null) {
|
||||
|
@ -224,6 +225,17 @@ public class AuthenticationFilter implements Filter {
|
|||
cookiePath = config.getProperty(COOKIE_PATH, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configuration properties of the {@link AuthenticationFilter}
|
||||
* without the prefix. The returned properties are the same that the
|
||||
* {@link #getConfiguration(String, FilterConfig)} method returned.
|
||||
*
|
||||
* @return the configuration properties.
|
||||
*/
|
||||
protected Properties getConfiguration() {
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the authentication handler being used.
|
||||
*
|
||||
|
@ -457,7 +469,7 @@ public class AuthenticationFilter implements Filter {
|
|||
createAuthCookie(httpResponse, signedToken, getCookieDomain(),
|
||||
getCookiePath(), token.getExpires(), isHttps);
|
||||
}
|
||||
filterChain.doFilter(httpRequest, httpResponse);
|
||||
doFilter(filterChain, httpRequest, httpResponse);
|
||||
}
|
||||
} else {
|
||||
unauthorizedResponse = false;
|
||||
|
@ -481,6 +493,15 @@ public class AuthenticationFilter implements Filter {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates call to the servlet filter chain. Sub-classes my override this
|
||||
* method to perform pre and post tasks.
|
||||
*/
|
||||
protected void doFilter(FilterChain filterChain, HttpServletRequest request,
|
||||
HttpServletResponse response) throws IOException, ServletException {
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the Hadoop authentication HTTP cookie.
|
||||
*
|
||||
|
|
|
@ -496,7 +496,11 @@ Release 2.6.0 - UNRELEASED
|
|||
HADOOP-10791. AuthenticationFilter should support externalizing the
|
||||
secret for signing and provide rotation support. (rkanter via tucu)
|
||||
|
||||
HADOOP-10771. Refactor HTTP delegation support out of httpfs to common, PART 1. (tucu)
|
||||
HADOOP-10771. Refactor HTTP delegation support out of httpfs to common.
|
||||
(tucu)
|
||||
|
||||
HADOOP-10835. Implement HTTP proxyuser support in HTTP authentication
|
||||
client/server libraries. (tucu)
|
||||
|
||||
OPTIMIZATIONS
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@ import java.io.IOException;
|
|||
import java.net.HttpURLConnection;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -60,6 +61,13 @@ import java.util.Map;
|
|||
@InterfaceStability.Unstable
|
||||
public class DelegationTokenAuthenticatedURL extends AuthenticatedURL {
|
||||
|
||||
/**
|
||||
* Constant used in URL's query string to perform a proxy user request, the
|
||||
* value of the <code>DO_AS</code> parameter is the user the request will be
|
||||
* done on behalf of.
|
||||
*/
|
||||
static final String DO_AS = "doAs";
|
||||
|
||||
/**
|
||||
* Client side authentication token that handles Delegation Tokens.
|
||||
*/
|
||||
|
@ -247,6 +255,11 @@ public class DelegationTokenAuthenticatedURL extends AuthenticatedURL {
|
|||
}
|
||||
}
|
||||
|
||||
// proxyuser
|
||||
if (doAs != null) {
|
||||
extraParams.put(DO_AS, URLEncoder.encode(doAs, "UTF-8"));
|
||||
}
|
||||
|
||||
url = augmentURL(url, extraParams);
|
||||
return super.openConnection(url, token);
|
||||
}
|
||||
|
|
|
@ -17,17 +17,39 @@
|
|||
*/
|
||||
package org.apache.hadoop.security.token.delegation.web;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import org.apache.hadoop.classification.InterfaceAudience;
|
||||
import org.apache.hadoop.classification.InterfaceStability;
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.security.SaslRpcServer;
|
||||
import org.apache.hadoop.security.UserGroupInformation;
|
||||
import org.apache.hadoop.security.authentication.server.AuthenticationFilter;
|
||||
import org.apache.hadoop.security.authentication.server.AuthenticationHandler;
|
||||
import org.apache.hadoop.security.authentication.server.AuthenticationToken;
|
||||
import org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler;
|
||||
import org.apache.hadoop.security.authentication.server.PseudoAuthenticationHandler;
|
||||
import org.apache.hadoop.security.authorize.AuthorizationException;
|
||||
import org.apache.hadoop.security.authorize.ProxyUsers;
|
||||
import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenSecretManager;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.utils.URLEncodedUtils;
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.Principal;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
|
@ -49,6 +71,10 @@ import java.util.Properties;
|
|||
public class DelegationTokenAuthenticationFilter
|
||||
extends AuthenticationFilter {
|
||||
|
||||
private static final String APPLICATION_JSON_MIME = "application/json";
|
||||
private static final String ERROR_EXCEPTION_JSON = "exception";
|
||||
private static final String ERROR_MESSAGE_JSON = "message";
|
||||
|
||||
/**
|
||||
* Sets an external <code>DelegationTokenSecretManager</code> instance to
|
||||
* manage creation and verification of Delegation Tokens.
|
||||
|
@ -60,6 +86,14 @@ public class DelegationTokenAuthenticationFilter
|
|||
public static final String DELEGATION_TOKEN_SECRET_MANAGER_ATTR =
|
||||
"hadoop.http.delegation-token-secret-manager";
|
||||
|
||||
private static final Charset UTF8_CHARSET = Charset.forName("UTF-8");
|
||||
|
||||
private static final ThreadLocal<UserGroupInformation> UGI_TL =
|
||||
new ThreadLocal<UserGroupInformation>();
|
||||
public static final String PROXYUSER_PREFIX = "proxyuser";
|
||||
|
||||
private SaslRpcServer.AuthMethod handlerAuthMethod;
|
||||
|
||||
/**
|
||||
* It delegates to
|
||||
* {@link AuthenticationFilter#getConfiguration(String, FilterConfig)} and
|
||||
|
@ -86,17 +120,155 @@ public class DelegationTokenAuthenticationFilter
|
|||
return props;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the proxyuser configuration. All returned properties must start
|
||||
* with <code>proxyuser.</code>'
|
||||
* <p/>
|
||||
* Subclasses may override this method if the proxyuser configuration is
|
||||
* read from other place than the filter init parameters.
|
||||
*
|
||||
* @param filterConfig filter configuration object
|
||||
* @return the proxyuser configuration properties.
|
||||
* @throws ServletException thrown if the configuration could not be created.
|
||||
*/
|
||||
protected Configuration getProxyuserConfiguration(FilterConfig filterConfig)
|
||||
throws ServletException {
|
||||
// this filter class gets the configuration from the filter configs, we are
|
||||
// creating an empty configuration and injecting the proxyuser settings in
|
||||
// it. In the initialization of the filter, the returned configuration is
|
||||
// passed to the ProxyUsers which only looks for 'proxyusers.' properties.
|
||||
Configuration conf = new Configuration(false);
|
||||
Enumeration<?> names = filterConfig.getInitParameterNames();
|
||||
while (names.hasMoreElements()) {
|
||||
String name = (String) names.nextElement();
|
||||
if (name.startsWith(PROXYUSER_PREFIX + ".")) {
|
||||
String value = filterConfig.getInitParameter(name);
|
||||
conf.set(name, value);
|
||||
}
|
||||
}
|
||||
return conf;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
super.init(filterConfig);
|
||||
AuthenticationHandler handler = getAuthenticationHandler();
|
||||
AbstractDelegationTokenSecretManager dtSecretManager =
|
||||
(AbstractDelegationTokenSecretManager) filterConfig.getServletContext().
|
||||
getAttribute(DELEGATION_TOKEN_SECRET_MANAGER_ATTR);
|
||||
if (dtSecretManager != null && getAuthenticationHandler()
|
||||
if (dtSecretManager != null && handler
|
||||
instanceof DelegationTokenAuthenticationHandler) {
|
||||
DelegationTokenAuthenticationHandler handler =
|
||||
DelegationTokenAuthenticationHandler dtHandler =
|
||||
(DelegationTokenAuthenticationHandler) getAuthenticationHandler();
|
||||
handler.setExternalDelegationTokenSecretManager(dtSecretManager);
|
||||
dtHandler.setExternalDelegationTokenSecretManager(dtSecretManager);
|
||||
}
|
||||
if (handler instanceof PseudoAuthenticationHandler ||
|
||||
handler instanceof PseudoDelegationTokenAuthenticationHandler) {
|
||||
setHandlerAuthMethod(SaslRpcServer.AuthMethod.SIMPLE);
|
||||
}
|
||||
if (handler instanceof KerberosAuthenticationHandler ||
|
||||
handler instanceof KerberosDelegationTokenAuthenticationHandler) {
|
||||
setHandlerAuthMethod(SaslRpcServer.AuthMethod.KERBEROS);
|
||||
}
|
||||
|
||||
// proxyuser configuration
|
||||
Configuration conf = getProxyuserConfiguration(filterConfig);
|
||||
ProxyUsers.refreshSuperUserGroupsConfiguration(conf, PROXYUSER_PREFIX);
|
||||
}
|
||||
|
||||
protected void setHandlerAuthMethod(SaslRpcServer.AuthMethod authMethod) {
|
||||
this.handlerAuthMethod = authMethod;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static String getDoAs(HttpServletRequest request) {
|
||||
List<NameValuePair> list = URLEncodedUtils.parse(request.getQueryString(),
|
||||
UTF8_CHARSET);
|
||||
if (list != null) {
|
||||
for (NameValuePair nv : list) {
|
||||
if (DelegationTokenAuthenticatedURL.DO_AS.equals(nv.getName())) {
|
||||
return nv.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static UserGroupInformation getHttpUserGroupInformationInContext() {
|
||||
return UGI_TL.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doFilter(FilterChain filterChain, HttpServletRequest request,
|
||||
HttpServletResponse response) throws IOException, ServletException {
|
||||
boolean requestCompleted = false;
|
||||
UserGroupInformation ugi = null;
|
||||
AuthenticationToken authToken = (AuthenticationToken)
|
||||
request.getUserPrincipal();
|
||||
if (authToken != null && authToken != AuthenticationToken.ANONYMOUS) {
|
||||
// if the request was authenticated because of a delegation token,
|
||||
// then we ignore proxyuser (this is the same as the RPC behavior).
|
||||
ugi = (UserGroupInformation) request.getAttribute(
|
||||
DelegationTokenAuthenticationHandler.DELEGATION_TOKEN_UGI_ATTRIBUTE);
|
||||
if (ugi == null) {
|
||||
String realUser = request.getUserPrincipal().getName();
|
||||
ugi = UserGroupInformation.createRemoteUser(realUser,
|
||||
handlerAuthMethod);
|
||||
String doAsUser = getDoAs(request);
|
||||
if (doAsUser != null) {
|
||||
ugi = UserGroupInformation.createProxyUser(doAsUser, ugi);
|
||||
try {
|
||||
ProxyUsers.authorize(ugi, request.getRemoteHost());
|
||||
} catch (AuthorizationException ex) {
|
||||
String msg = String.format(
|
||||
"User '%s' from host '%s' not allowed to impersonate user '%s'",
|
||||
realUser, request.getRemoteHost(), doAsUser);
|
||||
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
|
||||
response.setContentType(APPLICATION_JSON_MIME);
|
||||
Map<String, String> json = new HashMap<String, String>();
|
||||
json.put(ERROR_EXCEPTION_JSON,
|
||||
AuthorizationException.class.getName());
|
||||
json.put(ERROR_MESSAGE_JSON, msg);
|
||||
Writer writer = response.getWriter();
|
||||
ObjectMapper jsonMapper = new ObjectMapper();
|
||||
jsonMapper.writeValue(writer, json);
|
||||
requestCompleted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
UGI_TL.set(ugi);
|
||||
}
|
||||
if (!requestCompleted) {
|
||||
final UserGroupInformation ugiF = ugi;
|
||||
try {
|
||||
request = new HttpServletRequestWrapper(request) {
|
||||
|
||||
@Override
|
||||
public String getAuthType() {
|
||||
return (ugiF != null) ? handlerAuthMethod.toString() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRemoteUser() {
|
||||
return (ugiF != null) ? ugiF.getShortUserName() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Principal getUserPrincipal() {
|
||||
return (ugiF != null) ? new Principal() {
|
||||
@Override
|
||||
public String getName() {
|
||||
return ugiF.getUserName();
|
||||
}
|
||||
} : null;
|
||||
}
|
||||
};
|
||||
super.doFilter(filterChain, request, response);
|
||||
} finally {
|
||||
UGI_TL.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -92,6 +92,9 @@ public abstract class DelegationTokenAuthenticationHandler
|
|||
|
||||
private static final Set<String> DELEGATION_TOKEN_OPS = new HashSet<String>();
|
||||
|
||||
static final String DELEGATION_TOKEN_UGI_ATTRIBUTE =
|
||||
"hadoop.security.delegation-token.ugi";
|
||||
|
||||
static {
|
||||
DELEGATION_TOKEN_OPS.add(KerberosDelegationTokenAuthenticator.
|
||||
DelegationTokenOperation.GETDELEGATIONTOKEN.toString());
|
||||
|
@ -342,6 +345,7 @@ public abstract class DelegationTokenAuthenticationHandler
|
|||
token = new AuthenticationToken(shortName, ugi.getUserName(),
|
||||
getType());
|
||||
token.setExpires(0);
|
||||
request.setAttribute(DELEGATION_TOKEN_UGI_ATTRIBUTE, ugi);
|
||||
} catch (Throwable ex) {
|
||||
throw new AuthenticationException("Could not verify DelegationToken, " +
|
||||
ex.toString(), ex);
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* 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.security.token.delegation.web;
|
||||
|
||||
import org.apache.hadoop.classification.InterfaceAudience;
|
||||
import org.apache.hadoop.security.UserGroupInformation;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* Util class that returns the remote {@link UserGroupInformation} in scope
|
||||
* for the HTTP request.
|
||||
*/
|
||||
@InterfaceAudience.Private
|
||||
public class HttpUserGroupInformation {
|
||||
|
||||
/**
|
||||
* Returns the remote {@link UserGroupInformation} in context for the current
|
||||
* HTTP request, taking into account proxy user requests.
|
||||
*
|
||||
* @return the remote {@link UserGroupInformation}, <code>NULL</code> if none.
|
||||
*/
|
||||
public static UserGroupInformation get() {
|
||||
return DelegationTokenAuthenticationFilter.
|
||||
getHttpUserGroupInformationInContext();
|
||||
}
|
||||
|
||||
}
|
|
@ -72,6 +72,10 @@ import java.util.UUID;
|
|||
import java.util.concurrent.Callable;
|
||||
|
||||
public class TestWebDelegationToken {
|
||||
private static final String OK_USER = "ok-user";
|
||||
private static final String FAIL_USER = "fail-user";
|
||||
private static final String FOO_USER = "foo";
|
||||
|
||||
private Server jetty;
|
||||
|
||||
public static class DummyAuthenticationHandler
|
||||
|
@ -330,13 +334,13 @@ public class TestWebDelegationToken {
|
|||
new DelegationTokenAuthenticatedURL();
|
||||
|
||||
try {
|
||||
aUrl.getDelegationToken(nonAuthURL, token, "foo");
|
||||
aUrl.getDelegationToken(nonAuthURL, token, FOO_USER);
|
||||
Assert.fail();
|
||||
} catch (Exception ex) {
|
||||
Assert.assertTrue(ex.getMessage().contains("401"));
|
||||
}
|
||||
|
||||
aUrl.getDelegationToken(authURL, token, "foo");
|
||||
aUrl.getDelegationToken(authURL, token, FOO_USER);
|
||||
Assert.assertNotNull(token.getDelegationToken());
|
||||
Assert.assertEquals(new Text("token-kind"),
|
||||
token.getDelegationToken().getKind());
|
||||
|
@ -350,7 +354,7 @@ public class TestWebDelegationToken {
|
|||
Assert.assertTrue(ex.getMessage().contains("401"));
|
||||
}
|
||||
|
||||
aUrl.getDelegationToken(authURL, token, "foo");
|
||||
aUrl.getDelegationToken(authURL, token, FOO_USER);
|
||||
|
||||
try {
|
||||
aUrl.renewDelegationToken(authURL2, token);
|
||||
|
@ -359,15 +363,15 @@ public class TestWebDelegationToken {
|
|||
Assert.assertTrue(ex.getMessage().contains("403"));
|
||||
}
|
||||
|
||||
aUrl.getDelegationToken(authURL, token, "foo");
|
||||
aUrl.getDelegationToken(authURL, token, FOO_USER);
|
||||
|
||||
aUrl.cancelDelegationToken(authURL, token);
|
||||
|
||||
aUrl.getDelegationToken(authURL, token, "foo");
|
||||
aUrl.getDelegationToken(authURL, token, FOO_USER);
|
||||
|
||||
aUrl.cancelDelegationToken(nonAuthURL, token);
|
||||
|
||||
aUrl.getDelegationToken(authURL, token, "foo");
|
||||
aUrl.getDelegationToken(authURL, token, FOO_USER);
|
||||
|
||||
try {
|
||||
aUrl.renewDelegationToken(nonAuthURL, token);
|
||||
|
@ -416,7 +420,7 @@ public class TestWebDelegationToken {
|
|||
DelegationTokenAuthenticatedURL aUrl =
|
||||
new DelegationTokenAuthenticatedURL();
|
||||
|
||||
aUrl.getDelegationToken(authURL, token, "foo");
|
||||
aUrl.getDelegationToken(authURL, token, FOO_USER);
|
||||
Assert.assertNotNull(token.getDelegationToken());
|
||||
Assert.assertEquals(new Text("fooKind"),
|
||||
token.getDelegationToken().getKind());
|
||||
|
@ -488,7 +492,7 @@ public class TestWebDelegationToken {
|
|||
jetty.start();
|
||||
final URL url = new URL(getJettyURL() + "/foo/bar");
|
||||
|
||||
UserGroupInformation ugi = UserGroupInformation.createRemoteUser("foo");
|
||||
UserGroupInformation ugi = UserGroupInformation.createRemoteUser(FOO_USER);
|
||||
ugi.doAs(new PrivilegedExceptionAction<Void>() {
|
||||
@Override
|
||||
public Void run() throws Exception {
|
||||
|
@ -501,10 +505,10 @@ public class TestWebDelegationToken {
|
|||
conn.getResponseCode());
|
||||
List<String> ret = IOUtils.readLines(conn.getInputStream());
|
||||
Assert.assertEquals(1, ret.size());
|
||||
Assert.assertEquals("foo", ret.get(0));
|
||||
Assert.assertEquals(FOO_USER, ret.get(0));
|
||||
|
||||
try {
|
||||
aUrl.getDelegationToken(url, token, "foo");
|
||||
aUrl.getDelegationToken(url, token, FOO_USER);
|
||||
Assert.fail();
|
||||
} catch (AuthenticationException ex) {
|
||||
Assert.assertTrue(ex.getMessage().contains(
|
||||
|
@ -531,6 +535,16 @@ public class TestWebDelegationToken {
|
|||
"token-kind");
|
||||
return conf;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected org.apache.hadoop.conf.Configuration getProxyuserConfiguration(
|
||||
FilterConfig filterConfig) throws ServletException {
|
||||
org.apache.hadoop.conf.Configuration conf =
|
||||
new org.apache.hadoop.conf.Configuration(false);
|
||||
conf.set("proxyuser.foo.users", OK_USER);
|
||||
conf.set("proxyuser.foo.hosts", "localhost");
|
||||
return conf;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -547,7 +561,7 @@ public class TestWebDelegationToken {
|
|||
jetty.start();
|
||||
final URL url = new URL(getJettyURL() + "/foo/bar");
|
||||
|
||||
UserGroupInformation ugi = UserGroupInformation.createRemoteUser("foo");
|
||||
UserGroupInformation ugi = UserGroupInformation.createRemoteUser(FOO_USER);
|
||||
ugi.doAs(new PrivilegedExceptionAction<Void>() {
|
||||
@Override
|
||||
public Void run() throws Exception {
|
||||
|
@ -560,9 +574,9 @@ public class TestWebDelegationToken {
|
|||
conn.getResponseCode());
|
||||
List<String> ret = IOUtils.readLines(conn.getInputStream());
|
||||
Assert.assertEquals(1, ret.size());
|
||||
Assert.assertEquals("foo", ret.get(0));
|
||||
Assert.assertEquals(FOO_USER, ret.get(0));
|
||||
|
||||
aUrl.getDelegationToken(url, token, "foo");
|
||||
aUrl.getDelegationToken(url, token, FOO_USER);
|
||||
Assert.assertNotNull(token.getDelegationToken());
|
||||
Assert.assertEquals(new Text("token-kind"),
|
||||
token.getDelegationToken().getKind());
|
||||
|
@ -684,7 +698,7 @@ public class TestWebDelegationToken {
|
|||
final URL url = new URL(getJettyURL() + "/foo/bar");
|
||||
|
||||
try {
|
||||
aUrl.getDelegationToken(url, token, "foo");
|
||||
aUrl.getDelegationToken(url, token, FOO_USER);
|
||||
Assert.fail();
|
||||
} catch (AuthenticationException ex) {
|
||||
Assert.assertTrue(ex.getMessage().contains("GSSException"));
|
||||
|
@ -700,7 +714,7 @@ public class TestWebDelegationToken {
|
|||
aUrl.renewDelegationToken(url, token);
|
||||
Assert.assertNotNull(token.getDelegationToken());
|
||||
|
||||
aUrl.getDelegationToken(url, token, "foo");
|
||||
aUrl.getDelegationToken(url, token, FOO_USER);
|
||||
Assert.assertNotNull(token.getDelegationToken());
|
||||
|
||||
try {
|
||||
|
@ -710,7 +724,7 @@ public class TestWebDelegationToken {
|
|||
Assert.assertTrue(ex.getMessage().contains("403"));
|
||||
}
|
||||
|
||||
aUrl.getDelegationToken(url, token, "foo");
|
||||
aUrl.getDelegationToken(url, token, FOO_USER);
|
||||
|
||||
aUrl.cancelDelegationToken(url, token);
|
||||
Assert.assertNull(token.getDelegationToken());
|
||||
|
@ -724,4 +738,132 @@ public class TestWebDelegationToken {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProxyUser() throws Exception {
|
||||
final Server jetty = createJettyServer();
|
||||
Context context = new Context();
|
||||
context.setContextPath("/foo");
|
||||
jetty.setHandler(context);
|
||||
context.addFilter(new FilterHolder(PseudoDTAFilter.class), "/*", 0);
|
||||
context.addServlet(new ServletHolder(UserServlet.class), "/bar");
|
||||
|
||||
try {
|
||||
jetty.start();
|
||||
final URL url = new URL(getJettyURL() + "/foo/bar");
|
||||
|
||||
UserGroupInformation ugi = UserGroupInformation.createRemoteUser(FOO_USER);
|
||||
ugi.doAs(new PrivilegedExceptionAction<Void>() {
|
||||
@Override
|
||||
public Void run() throws Exception {
|
||||
DelegationTokenAuthenticatedURL.Token token =
|
||||
new DelegationTokenAuthenticatedURL.Token();
|
||||
DelegationTokenAuthenticatedURL aUrl =
|
||||
new DelegationTokenAuthenticatedURL();
|
||||
|
||||
// proxyuser using authentication handler authentication
|
||||
HttpURLConnection conn = aUrl.openConnection(url, token, OK_USER);
|
||||
Assert.assertEquals(HttpURLConnection.HTTP_OK,
|
||||
conn.getResponseCode());
|
||||
List<String> ret = IOUtils.readLines(conn.getInputStream());
|
||||
Assert.assertEquals(1, ret.size());
|
||||
Assert.assertEquals(OK_USER, ret.get(0));
|
||||
|
||||
// unauthorized proxy user using authentication handler authentication
|
||||
conn = aUrl.openConnection(url, token, FAIL_USER);
|
||||
Assert.assertEquals(HttpURLConnection.HTTP_FORBIDDEN,
|
||||
conn.getResponseCode());
|
||||
|
||||
// proxy using delegation token authentication
|
||||
aUrl.getDelegationToken(url, token, FOO_USER);
|
||||
|
||||
UserGroupInformation ugi = UserGroupInformation.getCurrentUser();
|
||||
ugi.addToken(token.getDelegationToken());
|
||||
token = new DelegationTokenAuthenticatedURL.Token();
|
||||
|
||||
// requests using delegation token as auth do not honor doAs
|
||||
conn = aUrl.openConnection(url, token, OK_USER);
|
||||
Assert.assertEquals(HttpURLConnection.HTTP_OK,
|
||||
conn.getResponseCode());
|
||||
ret = IOUtils.readLines(conn.getInputStream());
|
||||
Assert.assertEquals(1, ret.size());
|
||||
Assert.assertEquals(FOO_USER, ret.get(0));
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
jetty.stop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class UGIServlet extends HttpServlet {
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
|
||||
throws ServletException, IOException {
|
||||
UserGroupInformation ugi = HttpUserGroupInformation.get();
|
||||
if (ugi != null) {
|
||||
String ret = "remoteuser=" + req.getRemoteUser() + ":ugi=" +
|
||||
ugi.getShortUserName();
|
||||
if (ugi.getAuthenticationMethod() ==
|
||||
UserGroupInformation.AuthenticationMethod.PROXY) {
|
||||
ret = "realugi=" + ugi.getRealUser().getShortUserName() + ":" + ret;
|
||||
}
|
||||
resp.setStatus(HttpServletResponse.SC_OK);
|
||||
resp.getWriter().write(ret);
|
||||
} else {
|
||||
resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHttpUGI() throws Exception {
|
||||
final Server jetty = createJettyServer();
|
||||
Context context = new Context();
|
||||
context.setContextPath("/foo");
|
||||
jetty.setHandler(context);
|
||||
context.addFilter(new FilterHolder(PseudoDTAFilter.class), "/*", 0);
|
||||
context.addServlet(new ServletHolder(UGIServlet.class), "/bar");
|
||||
|
||||
try {
|
||||
jetty.start();
|
||||
final URL url = new URL(getJettyURL() + "/foo/bar");
|
||||
|
||||
UserGroupInformation ugi = UserGroupInformation.createRemoteUser(FOO_USER);
|
||||
ugi.doAs(new PrivilegedExceptionAction<Void>() {
|
||||
@Override
|
||||
public Void run() throws Exception {
|
||||
DelegationTokenAuthenticatedURL.Token token =
|
||||
new DelegationTokenAuthenticatedURL.Token();
|
||||
DelegationTokenAuthenticatedURL aUrl =
|
||||
new DelegationTokenAuthenticatedURL();
|
||||
|
||||
// user foo
|
||||
HttpURLConnection conn = aUrl.openConnection(url, token);
|
||||
Assert.assertEquals(HttpURLConnection.HTTP_OK,
|
||||
conn.getResponseCode());
|
||||
List<String> ret = IOUtils.readLines(conn.getInputStream());
|
||||
Assert.assertEquals(1, ret.size());
|
||||
Assert.assertEquals("remoteuser=" + FOO_USER+ ":ugi=" + FOO_USER,
|
||||
ret.get(0));
|
||||
|
||||
// user ok-user via proxyuser foo
|
||||
conn = aUrl.openConnection(url, token, OK_USER);
|
||||
Assert.assertEquals(HttpURLConnection.HTTP_OK,
|
||||
conn.getResponseCode());
|
||||
ret = IOUtils.readLines(conn.getInputStream());
|
||||
Assert.assertEquals(1, ret.size());
|
||||
Assert.assertEquals("realugi=" + FOO_USER +":remoteuser=" + OK_USER +
|
||||
":ugi=" + OK_USER, ret.get(0));
|
||||
|
||||
return null;
|
||||
}
|
||||
});
|
||||
} finally {
|
||||
jetty.stop();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue