From ae0fac3efa9a86b6582cc9721c857d8ff36a8d10 Mon Sep 17 00:00:00 2001 From: Wangda Tan Date: Sun, 31 May 2015 16:30:34 -0700 Subject: [PATCH] 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 5cc3fced957a8471733e0e9490878bd68429fe24) (cherry picked from commit a3734f67d35e714690ecdf21d80bce8a355381e3) (cherry picked from commit 9ccc22e2ac89990f3e7997f1d89594523c66e76a) --- hadoop-yarn-project/CHANGES.txt | 3 +++ .../client/api/impl/TimelineClientImpl.java | 26 ++++++++++++++++++- .../TestTimelineAuthenticationFilter.java | 11 ++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/hadoop-yarn-project/CHANGES.txt b/hadoop-yarn-project/CHANGES.txt index b8d1f530cc7..4ce9f9fafc4 100644 --- a/hadoop-yarn-project/CHANGES.txt +++ b/hadoop-yarn-project/CHANGES.txt @@ -150,6 +150,9 @@ Release 2.6.1 - UNRELEASED YARN-2900. Application (Attempt and Container) Not Found in AHS results 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 INCOMPATIBLE CHANGES diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/client/api/impl/TimelineClientImpl.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/client/api/impl/TimelineClientImpl.java index f5c85c15932..6bf858a37c3 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/client/api/impl/TimelineClientImpl.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/client/api/impl/TimelineClientImpl.java @@ -23,6 +23,7 @@ import java.lang.reflect.UndeclaredThrowableException; import java.net.ConnectException; import java.net.HttpURLConnection; +import java.net.InetSocketAddress; import java.net.URI; import java.net.URL; import java.net.URLConnection; @@ -44,6 +45,7 @@ import org.apache.hadoop.classification.InterfaceAudience.Private; import org.apache.hadoop.classification.InterfaceStability.Unstable; import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.security.SecurityUtil; import org.apache.hadoop.security.UserGroupInformation; import org.apache.hadoop.security.authentication.client.AuthenticationException; import org.apache.hadoop.security.authentication.client.ConnectionConfigurator; @@ -362,6 +364,12 @@ public Token run() public long renewDelegationToken( final Token timelineDT) 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 renewDTAction = new PrivilegedExceptionAction() { @@ -377,6 +385,11 @@ public Long run() DelegationTokenAuthenticatedURL authUrl = new DelegationTokenAuthenticatedURL(authenticator, 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 .renewDelegationToken(resURI.toURL(), token, doAsUser); } @@ -389,6 +402,12 @@ public Long run() public void cancelDelegationToken( final Token timelineDT) 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 cancelDTAction = new PrivilegedExceptionAction() { @@ -404,7 +423,12 @@ public Void run() DelegationTokenAuthenticatedURL authUrl = new DelegationTokenAuthenticatedURL(authenticator, 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; } }; diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/timeline/security/TestTimelineAuthenticationFilter.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/timeline/security/TestTimelineAuthenticationFilter.java index c93e8f2bc9f..063f5121e50 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/timeline/security/TestTimelineAuthenticationFilter.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-applicationhistoryservice/src/test/java/org/apache/hadoop/yarn/server/timeline/security/TestTimelineAuthenticationFilter.java @@ -240,12 +240,21 @@ public UserGroupInformation call() throws Exception { Assert.assertEquals(new Text(HTTP_USER), tDT.getOwner()); // Renew token + Assert.assertFalse(token.getService().toString().isEmpty()); + // Renew the token from the token service address long renewTime1 = httpUserClient.renewDelegationToken(token); 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); Assert.assertTrue(renewTime1 < renewTime2); // 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); // Renew should not be successful because the token is canceled try { @@ -280,6 +289,8 @@ public TimelineClient run() throws Exception { Assert.assertTrue(renewTime1 < renewTime2); // Cancel token + Assert.assertFalse(tokenToRenew.getService().toString().isEmpty()); + // Cancel the token from the token service address fooUserClient.cancelDelegationToken(tokenToRenew); // Renew should not be successful because the token is canceled