HADOOP-13346. DelegationTokenAuthenticationHandler writes via closed writer. Contributed by Gregory Chanan and Hrishikesh Gadre.

This commit is contained in:
Xiao Chen 2016-11-09 09:32:15 -08:00
parent c619e9b43f
commit 822ae88f7d
2 changed files with 81 additions and 1 deletions

View File

@ -48,6 +48,8 @@
import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenSecretManager;
import org.apache.hadoop.util.HttpExceptionUtils;
import org.apache.hadoop.util.StringUtils;
import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.map.ObjectMapper;
import com.google.common.annotations.VisibleForTesting;
@ -89,6 +91,8 @@ public abstract class DelegationTokenAuthenticationHandler
public static final String DELEGATION_TOKEN_UGI_ATTRIBUTE =
"hadoop.security.delegation-token.ugi";
public static final String JSON_MAPPER_PREFIX = PREFIX + "json-mapper.";
static {
DELEGATION_TOKEN_OPS.add(KerberosDelegationTokenAuthenticator.
DelegationTokenOperation.GETDELEGATIONTOKEN.toString());
@ -101,6 +105,7 @@ public abstract class DelegationTokenAuthenticationHandler
private AuthenticationHandler authHandler;
private DelegationTokenManager tokenManager;
private String authType;
private JsonFactory jsonFactory;
public DelegationTokenAuthenticationHandler(AuthenticationHandler handler) {
authHandler = handler;
@ -120,6 +125,7 @@ AuthenticationHandler getAuthHandler() {
public void init(Properties config) throws ServletException {
authHandler.init(config);
initTokenManager(config);
initJsonFactory(config);
}
/**
@ -153,6 +159,30 @@ public void initTokenManager(Properties config) {
tokenManager.init();
}
@VisibleForTesting
public void initJsonFactory(Properties config) {
boolean hasFeature = false;
JsonFactory tmpJsonFactory = new JsonFactory();
for (Map.Entry entry : config.entrySet()) {
String key = (String)entry.getKey();
if (key.startsWith(JSON_MAPPER_PREFIX)) {
JsonGenerator.Feature feature =
JsonGenerator.Feature.valueOf(key.substring(JSON_MAPPER_PREFIX
.length()));
if (feature != null) {
hasFeature = true;
boolean enabled = Boolean.parseBoolean((String)entry.getValue());
tmpJsonFactory.configure(feature, enabled);
}
}
}
if (hasFeature) {
jsonFactory = tmpJsonFactory;
}
}
@Override
public void destroy() {
tokenManager.destroy();
@ -298,7 +328,7 @@ public boolean managementOperation(AuthenticationToken token,
if (map != null) {
response.setContentType(MediaType.APPLICATION_JSON);
Writer writer = response.getWriter();
ObjectMapper jsonMapper = new ObjectMapper();
ObjectMapper jsonMapper = new ObjectMapper(jsonFactory);
jsonMapper.writeValue(writer, map);
writer.write(ENTER);
writer.flush();

View File

@ -17,6 +17,9 @@
*/
package org.apache.hadoop.security.token.delegation.web;
import static org.apache.hadoop.security.token.delegation.web.DelegationTokenAuthenticator.DelegationTokenOperation.*;
import org.apache.commons.lang.mutable.MutableBoolean;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.authentication.client.AuthenticationException;
@ -458,4 +461,51 @@ public void testCannotRenewTokenUsingToken() throws Exception {
Assert.assertFalse(handler.managementOperation(null, request, response));
Mockito.verify(response).setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
@Test
public void testWriterNotClosed() throws Exception {
Properties conf = new Properties();
conf.put(KerberosDelegationTokenAuthenticationHandler.TOKEN_KIND, "foo");
conf.put(DelegationTokenAuthenticationHandler.JSON_MAPPER_PREFIX
+ "AUTO_CLOSE_TARGET", "false");
DelegationTokenAuthenticationHandler noAuthCloseHandler =
new MockDelegationTokenAuthenticationHandler();
try {
noAuthCloseHandler.initTokenManager(conf);
noAuthCloseHandler.initJsonFactory(conf);
DelegationTokenAuthenticator.DelegationTokenOperation op =
GETDELEGATIONTOKEN;
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
Mockito.when(request.getQueryString()).thenReturn(
DelegationTokenAuthenticator.OP_PARAM + "=" + op.toString());
Mockito.when(request.getMethod()).thenReturn(op.getHttpMethod());
AuthenticationToken token = Mockito.mock(AuthenticationToken.class);
Mockito.when(token.getUserName()).thenReturn("user");
final MutableBoolean closed = new MutableBoolean();
PrintWriter printWriterCloseCount = new PrintWriter(new StringWriter()) {
@Override
public void close() {
closed.setValue(true);
super.close();
}
@Override
public void write(String str) {
if (closed.booleanValue()) {
throw new RuntimeException("already closed!");
}
super.write(str);
}
};
Mockito.when(response.getWriter()).thenReturn(printWriterCloseCount);
Assert.assertFalse(noAuthCloseHandler.managementOperation(token, request,
response));
} finally {
noAuthCloseHandler.destroy();
}
}
}