diff --git a/hadoop-yarn-project/CHANGES.txt b/hadoop-yarn-project/CHANGES.txt index d7ea5a9ed36..7f06cf1c861 100644 --- a/hadoop-yarn-project/CHANGES.txt +++ b/hadoop-yarn-project/CHANGES.txt @@ -609,6 +609,9 @@ Release 2.7.1 - UNRELEASED YARN-2900. Application (Attempt and Container) Not Found in AHS results in Internal Server 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.7.0 - 2015-04-20 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 76db4e24ed5..04c84ca5f73 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 @@ -368,9 +368,12 @@ public class TimelineClientImpl extends TimelineClient { public long renewDelegationToken( final Token timelineDT) throws IOException, YarnException { - boolean useHttps = YarnConfiguration.useHttps(this.getConfig()); - final String scheme = useHttps ? "https" : "http"; - final InetSocketAddress address = SecurityUtil.getTokenServiceAddr(timelineDT); + 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() { @@ -385,7 +388,10 @@ public class TimelineClientImpl extends TimelineClient { DelegationTokenAuthenticatedURL authUrl = new DelegationTokenAuthenticatedURL(authenticator, connConfigurator); - final URI serviceURI = new URI(scheme, null, address.getHostName(), + // 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(serviceURI.toURL(), token, doAsUser); @@ -399,9 +405,12 @@ public class TimelineClientImpl extends TimelineClient { public void cancelDelegationToken( final Token timelineDT) throws IOException, YarnException { - boolean useHttps = YarnConfiguration.useHttps(this.getConfig()); - final String scheme = useHttps ? "https" : "http"; - final InetSocketAddress address = SecurityUtil.getTokenServiceAddr(timelineDT); + 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() { @@ -416,7 +425,10 @@ public class TimelineClientImpl extends TimelineClient { DelegationTokenAuthenticatedURL authUrl = new DelegationTokenAuthenticatedURL(authenticator, connConfigurator); - final URI serviceURI = new URI(scheme, null, address.getHostName(), + // 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 class TestTimelineAuthenticationFilter { 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 class TestTimelineAuthenticationFilter { 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