YARN-3725. App submission via REST API is broken in secure mode due to Timeline DT service address is empty. (Zhijie Shen via wangda)

(cherry picked from commit 5cc3fced95)
(cherry picked from commit a3734f67d3)
(cherry picked from commit 9ccc22e2ac89990f3e7997f1d89594523c66e76a)
This commit is contained in:
Wangda Tan 2015-05-31 16:30:34 -07:00 committed by Vinod Kumar Vavilapalli
parent 1c6a287bf5
commit ae0fac3efa
3 changed files with 39 additions and 1 deletions

View File

@ -150,6 +150,9 @@ Release 2.6.1 - UNRELEASED
YARN-2900. Application (Attempt and Container) Not Found in AHS results YARN-2900. Application (Attempt and Container) Not Found in AHS results
in InternalServer Error (500). (Zhijie Shen and Mit Desai via xgong) in InternalServer Error (500). (Zhijie Shen and Mit Desai via xgong)
YARN-3725. App submission via REST API is broken in secure mode due to
Timeline DT service address is empty. (Zhijie Shen via wangda)
Release 2.6.0 - 2014-11-18 Release 2.6.0 - 2014-11-18
INCOMPATIBLE CHANGES INCOMPATIBLE CHANGES

View File

@ -23,6 +23,7 @@ import java.io.IOException;
import java.lang.reflect.UndeclaredThrowableException; import java.lang.reflect.UndeclaredThrowableException;
import java.net.ConnectException; import java.net.ConnectException;
import java.net.HttpURLConnection; import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.URI; import java.net.URI;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
@ -44,6 +45,7 @@ import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.classification.InterfaceAudience.Private; import org.apache.hadoop.classification.InterfaceAudience.Private;
import org.apache.hadoop.classification.InterfaceStability.Unstable; import org.apache.hadoop.classification.InterfaceStability.Unstable;
import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.security.SecurityUtil;
import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.authentication.client.AuthenticationException; import org.apache.hadoop.security.authentication.client.AuthenticationException;
import org.apache.hadoop.security.authentication.client.ConnectionConfigurator; import org.apache.hadoop.security.authentication.client.ConnectionConfigurator;
@ -362,6 +364,12 @@ public class TimelineClientImpl extends TimelineClient {
public long renewDelegationToken( public long renewDelegationToken(
final Token<TimelineDelegationTokenIdentifier> timelineDT) final Token<TimelineDelegationTokenIdentifier> timelineDT)
throws IOException, YarnException { throws IOException, YarnException {
final boolean isTokenServiceAddrEmpty =
timelineDT.getService().toString().isEmpty();
final String scheme = isTokenServiceAddrEmpty ? null
: (YarnConfiguration.useHttps(this.getConfig()) ? "https" : "http");
final InetSocketAddress address = isTokenServiceAddrEmpty ? null
: SecurityUtil.getTokenServiceAddr(timelineDT);
PrivilegedExceptionAction<Long> renewDTAction = PrivilegedExceptionAction<Long> renewDTAction =
new PrivilegedExceptionAction<Long>() { new PrivilegedExceptionAction<Long>() {
@ -377,6 +385,11 @@ public class TimelineClientImpl extends TimelineClient {
DelegationTokenAuthenticatedURL authUrl = DelegationTokenAuthenticatedURL authUrl =
new DelegationTokenAuthenticatedURL(authenticator, new DelegationTokenAuthenticatedURL(authenticator,
connConfigurator); connConfigurator);
// If the token service address is not available, fall back to use
// the configured service address.
final URI serviceURI = isTokenServiceAddrEmpty ? resURI
: new URI(scheme, null, address.getHostName(),
address.getPort(), RESOURCE_URI_STR, null, null);
return authUrl return authUrl
.renewDelegationToken(resURI.toURL(), token, doAsUser); .renewDelegationToken(resURI.toURL(), token, doAsUser);
} }
@ -389,6 +402,12 @@ public class TimelineClientImpl extends TimelineClient {
public void cancelDelegationToken( public void cancelDelegationToken(
final Token<TimelineDelegationTokenIdentifier> timelineDT) final Token<TimelineDelegationTokenIdentifier> timelineDT)
throws IOException, YarnException { throws IOException, YarnException {
final boolean isTokenServiceAddrEmpty =
timelineDT.getService().toString().isEmpty();
final String scheme = isTokenServiceAddrEmpty ? null
: (YarnConfiguration.useHttps(this.getConfig()) ? "https" : "http");
final InetSocketAddress address = isTokenServiceAddrEmpty ? null
: SecurityUtil.getTokenServiceAddr(timelineDT);
PrivilegedExceptionAction<Void> cancelDTAction = PrivilegedExceptionAction<Void> cancelDTAction =
new PrivilegedExceptionAction<Void>() { new PrivilegedExceptionAction<Void>() {
@ -404,7 +423,12 @@ public class TimelineClientImpl extends TimelineClient {
DelegationTokenAuthenticatedURL authUrl = DelegationTokenAuthenticatedURL authUrl =
new DelegationTokenAuthenticatedURL(authenticator, new DelegationTokenAuthenticatedURL(authenticator,
connConfigurator); connConfigurator);
authUrl.cancelDelegationToken(resURI.toURL(), token, doAsUser); // If the token service address is not available, fall back to use
// the configured service address.
final URI serviceURI = isTokenServiceAddrEmpty ? resURI
: new URI(scheme, null, address.getHostName(),
address.getPort(), RESOURCE_URI_STR, null, null);
authUrl.cancelDelegationToken(serviceURI.toURL(), token, doAsUser);
return null; return null;
} }
}; };

View File

@ -240,12 +240,21 @@ public class TestTimelineAuthenticationFilter {
Assert.assertEquals(new Text(HTTP_USER), tDT.getOwner()); Assert.assertEquals(new Text(HTTP_USER), tDT.getOwner());
// Renew token // Renew token
Assert.assertFalse(token.getService().toString().isEmpty());
// Renew the token from the token service address
long renewTime1 = httpUserClient.renewDelegationToken(token); long renewTime1 = httpUserClient.renewDelegationToken(token);
Thread.sleep(100); Thread.sleep(100);
token.setService(new Text());
Assert.assertTrue(token.getService().toString().isEmpty());
// If the token service address is not avaiable, it still can be renewed
// from the configured address
long renewTime2 = httpUserClient.renewDelegationToken(token); long renewTime2 = httpUserClient.renewDelegationToken(token);
Assert.assertTrue(renewTime1 < renewTime2); Assert.assertTrue(renewTime1 < renewTime2);
// Cancel token // Cancel token
Assert.assertTrue(token.getService().toString().isEmpty());
// If the token service address is not avaiable, it still can be canceled
// from the configured address
httpUserClient.cancelDelegationToken(token); httpUserClient.cancelDelegationToken(token);
// Renew should not be successful because the token is canceled // Renew should not be successful because the token is canceled
try { try {
@ -280,6 +289,8 @@ public class TestTimelineAuthenticationFilter {
Assert.assertTrue(renewTime1 < renewTime2); Assert.assertTrue(renewTime1 < renewTime2);
// Cancel token // Cancel token
Assert.assertFalse(tokenToRenew.getService().toString().isEmpty());
// Cancel the token from the token service address
fooUserClient.cancelDelegationToken(tokenToRenew); fooUserClient.cancelDelegationToken(tokenToRenew);
// Renew should not be successful because the token is canceled // Renew should not be successful because the token is canceled