Browse Source

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

Wangda Tan 10 years ago
parent
commit
5cc3fced95

+ 3 - 0
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
     YARN-2900. Application (Attempt and Container) Not Found in AHS results
     in Internal Server Error (500). (Zhijie Shen and Mit Desai via xgong)
     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
 Release 2.7.0 - 2015-04-20
 
 
   INCOMPATIBLE CHANGES
   INCOMPATIBLE CHANGES

+ 20 - 8
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(
   public long renewDelegationToken(
       final Token<TimelineDelegationTokenIdentifier> timelineDT)
       final Token<TimelineDelegationTokenIdentifier> timelineDT)
           throws IOException, YarnException {
           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<Long> renewDTAction =
     PrivilegedExceptionAction<Long> renewDTAction =
         new PrivilegedExceptionAction<Long>() {
         new PrivilegedExceptionAction<Long>() {
 
 
@@ -385,7 +388,10 @@ public class TimelineClientImpl extends TimelineClient {
             DelegationTokenAuthenticatedURL authUrl =
             DelegationTokenAuthenticatedURL authUrl =
                 new DelegationTokenAuthenticatedURL(authenticator,
                 new DelegationTokenAuthenticatedURL(authenticator,
                     connConfigurator);
                     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);
                 address.getPort(), RESOURCE_URI_STR, null, null);
             return authUrl
             return authUrl
                 .renewDelegationToken(serviceURI.toURL(), token, doAsUser);
                 .renewDelegationToken(serviceURI.toURL(), token, doAsUser);
@@ -399,9 +405,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 {
-    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<Void> cancelDTAction =
     PrivilegedExceptionAction<Void> cancelDTAction =
         new PrivilegedExceptionAction<Void>() {
         new PrivilegedExceptionAction<Void>() {
 
 
@@ -416,7 +425,10 @@ public class TimelineClientImpl extends TimelineClient {
             DelegationTokenAuthenticatedURL authUrl =
             DelegationTokenAuthenticatedURL authUrl =
                 new DelegationTokenAuthenticatedURL(authenticator,
                 new DelegationTokenAuthenticatedURL(authenticator,
                     connConfigurator);
                     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);
                 address.getPort(), RESOURCE_URI_STR, null, null);
             authUrl.cancelDelegationToken(serviceURI.toURL(), token, doAsUser);
             authUrl.cancelDelegationToken(serviceURI.toURL(), token, doAsUser);
             return null;
             return null;

+ 11 - 0
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());
     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