Author: vinodkv
Date: Tue Jul 15 23:00:48 2014
New Revision: 1610877
URL: http://svn.apache.org/r1610877
Log:
YARN-2233. Implemented ResourceManager web-services to create, renew and cancel
delegation tokens. Contributed by Varun Vasudev.
svn merge --ignore-ancestry -c 1610876 ../../trunk/
Added:
hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/DelegationToken.java
- copied unchanged from r1610876,
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/dao/DelegationToken.java
hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesDelegationTokens.java
- copied unchanged from r1610876,
hadoop/common/trunk/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebServicesDelegationTokens.java
Modified:
hadoop/common/branches/branch-2/hadoop-yarn-project/CHANGES.txt
hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/pom.xml
hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/RMDelegationTokenSecretManager.java
hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java
hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/apt/ResourceManagerRest.apt.vm
Modified: hadoop/common/branches/branch-2/hadoop-yarn-project/CHANGES.txt
URL:
http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-yarn-project/CHANGES.txt?rev=1610877&r1=1610876&r2=1610877&view=diff
==============================================================================
--- hadoop/common/branches/branch-2/hadoop-yarn-project/CHANGES.txt (original)
+++ hadoop/common/branches/branch-2/hadoop-yarn-project/CHANGES.txt Tue Jul 15
23:00:48 2014
@@ -77,6 +77,9 @@ Release 2.5.0 - UNRELEASED
YARN-1713. Added get-new-app and submit-app functionality to RM web
services.
(Varun Vasudev via vinodkv)
+ YARN-2233. Implemented ResourceManager web-services to create, renew and
+ cancel delegation tokens. (Varun Vasudev via vinodkv)
+
IMPROVEMENTS
YARN-1479. Invalid NaN values in Hadoop REST API JSON response (Chen He via
Modified:
hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/pom.xml
URL:
http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/pom.xml?rev=1610877&r1=1610876&r2=1610877&view=diff
==============================================================================
---
hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/pom.xml
(original)
+++
hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/pom.xml
Tue Jul 15 23:00:48 2014
@@ -212,6 +212,21 @@
<!-- 'mvn dependency:analyze' fails to detect use of this dependency -->
<dependency>
+ <groupId>org.apache.hadoop</groupId>
+ <artifactId>hadoop-minikdc</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.hadoop</groupId>
+ <artifactId>hadoop-auth</artifactId>
+ <scope>test</scope>
+ <type>test-jar</type>
+ <version>${project.version}</version>
+ </dependency>
+
+ <!-- 'mvn dependency:analyze' fails to detect use of this dependency -->
+ <dependency>
<groupId>com.sun.jersey.jersey-test-framework</groupId>
<artifactId>jersey-test-framework-grizzly2</artifactId>
<scope>test</scope>
Modified:
hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/RMDelegationTokenSecretManager.java
URL:
http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/RMDelegationTokenSecretManager.java?rev=1610877&r1=1610876&r2=1610877&view=diff
==============================================================================
---
hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/RMDelegationTokenSecretManager.java
(original)
+++
hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/security/RMDelegationTokenSecretManager.java
Tue Jul 15 23:00:48 2014
@@ -29,8 +29,10 @@ import org.apache.commons.logging.LogFac
import org.apache.hadoop.classification.InterfaceAudience;
import org.apache.hadoop.classification.InterfaceAudience.Private;
import org.apache.hadoop.classification.InterfaceStability;
+import org.apache.hadoop.security.token.SecretManager.InvalidToken;
import
org.apache.hadoop.security.token.delegation.AbstractDelegationTokenSecretManager;
import org.apache.hadoop.security.token.delegation.DelegationKey;
+import
org.apache.hadoop.security.token.delegation.AbstractDelegationTokenSecretManager.DelegationTokenInformation;
import org.apache.hadoop.util.ExitUtil;
import org.apache.hadoop.yarn.security.client.RMDelegationTokenIdentifier;
import org.apache.hadoop.yarn.server.resourcemanager.RMContext;
@@ -193,4 +195,14 @@ public class RMDelegationTokenSecretMana
addPersistedDelegationToken(entry.getKey(), entry.getValue());
}
}
+
+ public long getRenewDate(RMDelegationTokenIdentifier ident)
+ throws InvalidToken {
+ DelegationTokenInformation info = currentTokens.get(ident);
+ if (info == null) {
+ throw new InvalidToken("token (" + ident.toString()
+ + ") can't be found in cache");
+ }
+ return info.getRenewDate();
+ }
}
Modified:
hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java
URL:
http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java?rev=1610877&r1=1610876&r2=1610877&view=diff
==============================================================================
---
hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java
(original)
+++
hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RMWebServices.java
Tue Jul 15 23:00:48 2014
@@ -22,6 +22,7 @@ import java.io.IOException;
import java.lang.reflect.UndeclaredThrowableException;
import java.security.AccessControlException;
import java.nio.ByteBuffer;
+import java.security.Principal;
import java.security.PrivilegedExceptionAction;
import java.util.Arrays;
import java.util.Collection;
@@ -36,6 +37,7 @@ import java.util.concurrent.ConcurrentMa
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
@@ -57,6 +59,8 @@ import org.apache.hadoop.io.DataOutputBu
import org.apache.hadoop.io.Text;
import org.apache.hadoop.security.Credentials;
import org.apache.hadoop.security.UserGroupInformation;
+import org.apache.hadoop.security.UserGroupInformation.AuthenticationMethod;
+import
org.apache.hadoop.security.authentication.server.KerberosAuthenticationHandler;
import org.apache.hadoop.security.authorize.AuthorizationException;
import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.security.token.TokenIdentifier;
@@ -67,6 +71,13 @@ import org.apache.hadoop.yarn.api.protoc
import org.apache.hadoop.yarn.api.protocolrecords.KillApplicationResponse;
import org.apache.hadoop.yarn.api.protocolrecords.SubmitApplicationRequest;
import org.apache.hadoop.yarn.api.protocolrecords.SubmitApplicationResponse;
+import org.apache.hadoop.security.token.SecretManager.InvalidToken;
+import org.apache.hadoop.yarn.api.protocolrecords.CancelDelegationTokenRequest;
+import
org.apache.hadoop.yarn.api.protocolrecords.CancelDelegationTokenResponse;
+import org.apache.hadoop.yarn.api.protocolrecords.GetDelegationTokenRequest;
+import org.apache.hadoop.yarn.api.protocolrecords.GetDelegationTokenResponse;
+import org.apache.hadoop.yarn.api.protocolrecords.RenewDelegationTokenRequest;
+import org.apache.hadoop.yarn.api.protocolrecords.RenewDelegationTokenResponse;
import org.apache.hadoop.yarn.api.records.ApplicationAccessType;
import org.apache.hadoop.yarn.api.records.ApplicationId;
import org.apache.hadoop.yarn.api.records.ApplicationReport;
@@ -85,6 +96,7 @@ import org.apache.hadoop.yarn.exceptions
import org.apache.hadoop.yarn.exceptions.YarnRuntimeException;
import org.apache.hadoop.yarn.factories.RecordFactory;
import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider;
+import org.apache.hadoop.yarn.security.client.RMDelegationTokenIdentifier;
import org.apache.hadoop.yarn.server.resourcemanager.RMAuditLogger;
import
org.apache.hadoop.yarn.server.resourcemanager.RMAuditLogger.AuditConstants;
import org.apache.hadoop.yarn.server.resourcemanager.RMServerUtils;
@@ -109,6 +121,7 @@ import org.apache.hadoop.yarn.server.res
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ClusterInfo;
import
org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.ClusterMetricsInfo;
import
org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.CredentialsInfo;
+import
org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.DelegationToken;
import
org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.FairSchedulerInfo;
import
org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.FifoSchedulerInfo;
import
org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.LocalResourceInfo;
@@ -118,6 +131,7 @@ import org.apache.hadoop.yarn.server.res
import org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.SchedulerInfo;
import
org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.SchedulerTypeInfo;
import
org.apache.hadoop.yarn.server.resourcemanager.webapp.dao.StatisticsItemInfo;
+import org.apache.hadoop.yarn.server.utils.BuilderUtils;
import org.apache.hadoop.yarn.util.ConverterUtils;
import org.apache.hadoop.yarn.webapp.BadRequestException;
import org.apache.hadoop.yarn.webapp.NotFoundException;
@@ -139,6 +153,9 @@ public class RMWebServices {
private final Configuration conf;
private @Context HttpServletResponse response;
+ public final static String DELEGATION_TOKEN_HEADER =
+ "Hadoop-YARN-RM-Delegation-Token";
+
@Inject
public RMWebServices(final ResourceManager rm, Configuration conf) {
this.rm = rm;
@@ -147,11 +164,7 @@ public class RMWebServices {
protected Boolean hasAccess(RMApp app, HttpServletRequest hsr) {
// Check for the authorization.
- String remoteUser = hsr.getRemoteUser();
- UserGroupInformation callerUGI = null;
- if (remoteUser != null) {
- callerUGI = UserGroupInformation.createRemoteUser(remoteUser);
- }
+ UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true);
if (callerUGI != null
&& !(this.rm.getApplicationACLsManager().checkAccess(callerUGI,
ApplicationAccessType.VIEW_APP, app.getUser(),
@@ -626,7 +639,7 @@ public class RMWebServices {
public AppState getAppState(@Context HttpServletRequest hsr,
@PathParam("appid") String appId) throws AuthorizationException {
init();
- UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr);
+ UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true);
String userName = "";
if (callerUGI != null) {
userName = callerUGI.getUserName();
@@ -661,7 +674,7 @@ public class RMWebServices {
IOException {
init();
- UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr);
+ UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true);
if (callerUGI == null) {
String msg = "Unable to obtain user name, user not authenticated";
throw new AuthorizationException(msg);
@@ -771,9 +784,14 @@ public class RMWebServices {
}
private UserGroupInformation getCallerUserGroupInformation(
- HttpServletRequest hsr) {
+ HttpServletRequest hsr, boolean usePrincipal) {
String remoteUser = hsr.getRemoteUser();
+ if (usePrincipal) {
+ Principal princ = hsr.getUserPrincipal();
+ remoteUser = princ == null ? null : princ.getName();
+ }
+
UserGroupInformation callerUGI = null;
if (remoteUser != null) {
callerUGI = UserGroupInformation.createRemoteUser(remoteUser);
@@ -799,7 +817,7 @@ public class RMWebServices {
public Response createNewApplication(@Context HttpServletRequest hsr)
throws AuthorizationException, IOException, InterruptedException {
init();
- UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr);
+ UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true);
if (callerUGI == null) {
throw new AuthorizationException("Unable to obtain user name, "
+ "user not authenticated");
@@ -835,7 +853,7 @@ public class RMWebServices {
IOException, InterruptedException {
init();
- UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr);
+ UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true);
if (callerUGI == null) {
throw new AuthorizationException("Unable to obtain user name, "
+ "user not authenticated");
@@ -887,8 +905,8 @@ public class RMWebServices {
throw new YarnRuntimeException(msg, e);
}
NewApplication appId =
- new NewApplication(resp.getApplicationId().toString(), new
ResourceInfo(
- resp.getMaximumResourceCapability()));
+ new NewApplication(resp.getApplicationId().toString(),
+ new ResourceInfo(resp.getMaximumResourceCapability()));
return appId;
}
@@ -962,7 +980,8 @@ public class RMWebServices {
* @throws IOException
*/
protected ContainerLaunchContext createContainerLaunchContext(
- ApplicationSubmissionContextInfo newApp) throws BadRequestException,
IOException {
+ ApplicationSubmissionContextInfo newApp) throws BadRequestException,
+ IOException {
// create container launch context
@@ -1033,4 +1052,238 @@ public class RMWebServices {
}
return ret;
}
+
+ private UserGroupInformation createKerberosUserGroupInformation(
+ HttpServletRequest hsr) throws AuthorizationException, YarnException {
+
+ UserGroupInformation callerUGI = getCallerUserGroupInformation(hsr, true);
+ if (callerUGI == null) {
+ String msg = "Unable to obtain user name, user not authenticated";
+ throw new AuthorizationException(msg);
+ }
+
+ String authType = hsr.getAuthType();
+ if (!KerberosAuthenticationHandler.TYPE.equals(authType)) {
+ String msg =
+ "Delegation token operations can only be carried out on a "
+ + "Kerberos authenticated channel";
+ throw new YarnException(msg);
+ }
+
+ callerUGI.setAuthenticationMethod(AuthenticationMethod.KERBEROS);
+ return callerUGI;
+ }
+
+ @POST
+ @Path("/delegation-token")
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ public Response postDelegationToken(DelegationToken tokenData,
+ @Context HttpServletRequest hsr) throws AuthorizationException,
+ IOException, InterruptedException, Exception {
+
+ init();
+ UserGroupInformation callerUGI;
+ try {
+ callerUGI = createKerberosUserGroupInformation(hsr);
+ } catch (YarnException ye) {
+ return Response.status(Status.FORBIDDEN).entity(ye.getMessage()).build();
+ }
+ return createDelegationToken(tokenData, hsr, callerUGI);
+ }
+
+ @POST
+ @Path("/delegation-token/expiration")
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ @Consumes({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ public Response
+ postDelegationTokenExpiration(@Context HttpServletRequest hsr)
+ throws AuthorizationException, IOException, InterruptedException,
+ Exception {
+
+ init();
+ UserGroupInformation callerUGI;
+ try {
+ callerUGI = createKerberosUserGroupInformation(hsr);
+ } catch (YarnException ye) {
+ return Response.status(Status.FORBIDDEN).entity(ye.getMessage()).build();
+ }
+
+ DelegationToken requestToken = new DelegationToken();
+ requestToken.setToken(extractToken(hsr).encodeToUrlString());
+ return renewDelegationToken(requestToken, hsr, callerUGI);
+ }
+
+ private Response createDelegationToken(DelegationToken tokenData,
+ HttpServletRequest hsr, UserGroupInformation callerUGI)
+ throws AuthorizationException, IOException, InterruptedException,
+ Exception {
+
+ final String renewer = tokenData.getRenewer();
+ GetDelegationTokenResponse resp;
+ try {
+ resp =
+ callerUGI
+ .doAs(new PrivilegedExceptionAction<GetDelegationTokenResponse>() {
+ @Override
+ public GetDelegationTokenResponse run() throws IOException,
+ YarnException {
+ GetDelegationTokenRequest createReq =
+ GetDelegationTokenRequest.newInstance(renewer);
+ return rm.getClientRMService().getDelegationToken(createReq);
+ }
+ });
+ } catch (Exception e) {
+ LOG.info("Create delegation token request failed", e);
+ throw e;
+ }
+
+ Token<RMDelegationTokenIdentifier> tk =
+ new Token<RMDelegationTokenIdentifier>(resp.getRMDelegationToken()
+ .getIdentifier().array(), resp.getRMDelegationToken().getPassword()
+ .array(), new Text(resp.getRMDelegationToken().getKind()), new Text(
+ resp.getRMDelegationToken().getService()));
+ RMDelegationTokenIdentifier identifier = tk.decodeIdentifier();
+ long currentExpiration =
+ rm.getRMContext().getRMDelegationTokenSecretManager()
+ .getRenewDate(identifier);
+ DelegationToken respToken =
+ new DelegationToken(tk.encodeToUrlString(), renewer, identifier
+ .getOwner().toString(), tk.getKind().toString(), currentExpiration,
+ identifier.getMaxDate());
+ return Response.status(Status.OK).entity(respToken).build();
+ }
+
+ private Response renewDelegationToken(DelegationToken tokenData,
+ HttpServletRequest hsr, UserGroupInformation callerUGI)
+ throws AuthorizationException, IOException, InterruptedException,
+ Exception {
+
+ Token<RMDelegationTokenIdentifier> token =
+ extractToken(tokenData.getToken());
+
+ org.apache.hadoop.yarn.api.records.Token dToken =
+ BuilderUtils.newDelegationToken(token.getIdentifier(), token.getKind()
+ .toString(), token.getPassword(), token.getService().toString());
+ final RenewDelegationTokenRequest req =
+ RenewDelegationTokenRequest.newInstance(dToken);
+
+ RenewDelegationTokenResponse resp;
+ try {
+ resp =
+ callerUGI
+ .doAs(new
PrivilegedExceptionAction<RenewDelegationTokenResponse>() {
+ @Override
+ public RenewDelegationTokenResponse run() throws IOException,
+ YarnException {
+ return rm.getClientRMService().renewDelegationToken(req);
+ }
+ });
+ } catch (UndeclaredThrowableException ue) {
+ if (ue.getCause() instanceof YarnException) {
+ if (ue.getCause().getCause() instanceof InvalidToken) {
+ throw new BadRequestException(ue.getCause().getCause().getMessage());
+ } else if (ue.getCause().getCause() instanceof
org.apache.hadoop.security.AccessControlException) {
+ return Response.status(Status.FORBIDDEN)
+ .entity(ue.getCause().getCause().getMessage()).build();
+ }
+ LOG.info("Renew delegation token request failed", ue);
+ throw ue;
+ }
+ LOG.info("Renew delegation token request failed", ue);
+ throw ue;
+ } catch (Exception e) {
+ LOG.info("Renew delegation token request failed", e);
+ throw e;
+ }
+ long renewTime = resp.getNextExpirationTime();
+
+ DelegationToken respToken = new DelegationToken();
+ respToken.setNextExpirationTime(renewTime);
+ return Response.status(Status.OK).entity(respToken).build();
+ }
+
+ // For cancelling tokens, the encoded token is passed as a header
+ // There are two reasons for this -
+ // 1. Passing a request body as part of a DELETE request is not
+ // allowed by Jetty
+ // 2. Passing the encoded token as part of the url is not ideal
+ // since urls tend to get logged and anyone with access to
+ // the logs can extract tokens which are meant to be secret
+ @DELETE
+ @Path("/delegation-token")
+ @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
+ public Response cancelDelegationToken(@Context HttpServletRequest hsr)
+ throws AuthorizationException, IOException, InterruptedException,
+ Exception {
+
+ init();
+ UserGroupInformation callerUGI;
+ try {
+ callerUGI = createKerberosUserGroupInformation(hsr);
+ } catch (YarnException ye) {
+ return Response.status(Status.FORBIDDEN).entity(ye.getMessage()).build();
+ }
+
+ Token<RMDelegationTokenIdentifier> token = extractToken(hsr);
+
+ org.apache.hadoop.yarn.api.records.Token dToken =
+ BuilderUtils.newDelegationToken(token.getIdentifier(), token.getKind()
+ .toString(), token.getPassword(), token.getService().toString());
+ final CancelDelegationTokenRequest req =
+ CancelDelegationTokenRequest.newInstance(dToken);
+
+ try {
+ callerUGI
+ .doAs(new PrivilegedExceptionAction<CancelDelegationTokenResponse>() {
+ @Override
+ public CancelDelegationTokenResponse run() throws IOException,
+ YarnException {
+ return rm.getClientRMService().cancelDelegationToken(req);
+ }
+ });
+ } catch (UndeclaredThrowableException ue) {
+ if (ue.getCause() instanceof YarnException) {
+ if (ue.getCause().getCause() instanceof InvalidToken) {
+ throw new BadRequestException(ue.getCause().getCause().getMessage());
+ } else if (ue.getCause().getCause() instanceof
org.apache.hadoop.security.AccessControlException) {
+ return Response.status(Status.FORBIDDEN)
+ .entity(ue.getCause().getCause().getMessage()).build();
+ }
+ LOG.info("Renew delegation token request failed", ue);
+ throw ue;
+ }
+ LOG.info("Renew delegation token request failed", ue);
+ throw ue;
+ } catch (Exception e) {
+ LOG.info("Renew delegation token request failed", e);
+ throw e;
+ }
+
+ return Response.status(Status.OK).build();
+ }
+
+ private Token<RMDelegationTokenIdentifier> extractToken(
+ HttpServletRequest request) {
+ String encodedToken = request.getHeader(DELEGATION_TOKEN_HEADER);
+ if (encodedToken == null) {
+ String msg =
+ "Header '" + DELEGATION_TOKEN_HEADER
+ + "' containing encoded token not found";
+ throw new BadRequestException(msg);
+ }
+ return extractToken(encodedToken);
+ }
+
+ private Token<RMDelegationTokenIdentifier> extractToken(String encodedToken)
{
+ Token<RMDelegationTokenIdentifier> token =
+ new Token<RMDelegationTokenIdentifier>();
+ try {
+ token.decodeFromUrlString(encodedToken);
+ } catch (Exception ie) {
+ String msg = "Could not decode encoded token";
+ throw new BadRequestException(msg);
+ }
+ return token;
+ }
}
Modified:
hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/apt/ResourceManagerRest.apt.vm
URL:
http://svn.apache.org/viewvc/hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/apt/ResourceManagerRest.apt.vm?rev=1610877&r1=1610876&r2=1610877&view=diff
==============================================================================
---
hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/apt/ResourceManagerRest.apt.vm
(original)
+++
hadoop/common/branches/branch-2/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-site/src/site/apt/ResourceManagerRest.apt.vm
Tue Jul 15 23:00:48 2014
@@ -2707,3 +2707,223 @@ Server: Jetty(6.1.26)
+---+
+* Cluster {Delegation Tokens API}
+
+ The Delegation Tokens API can be used to create, renew and cancel YARN
ResourceManager delegation tokens. All delegation token requests must be
carried out on a Kerberos authenticated connection(using SPNEGO). Carrying out
operations on a non-kerberos connection will result in a FORBIDDEN response. In
case of renewing a token, only the renewer specified when creating the token
can renew the token. Other users(including the owner) are forbidden from
renewing tokens. It should be noted that when cancelling or renewing a token,
the token to be cancelled or renewed is specified by setting a header.
+
+ This feature is currently in the alpha stage and may change in the future.
+
+** URI
+
+ Use the following URI to create and cancel delegation tokens.
+
+------
+ * http://<rm http address:port>/ws/v1/cluster/delegation-token
+------
+
+ Use the following URI to renew delegation tokens.
+
+------
+ * http://<rm http address:port>/ws/v1/cluster/delegation-token/expiration
+------
+
+** HTTP Operations Supported
+
+------
+ * POST
+ * DELETE
+------
+
+** Query Parameters Supported
+
+------
+ None
+------
+
+** Elements of the <delegation-token> object
+
+ The response from the delegation tokens API contains one of the fields
listed below.
+
+*---------------+--------------+-------------------------------+
+|| Item || Data Type || Description |
+*---------------+--------------+-------------------------------+
+| token | string | The delegation token |
+*---------------+--------------+-------------------------------+
+| renewer | string | The user who is allowed to renew the
delegation token |
+*---------------+--------------+-------------------------------+
+| owner | string | The owner of the delegation token |
+*---------------+--------------+-------------------------------+
+| kind | string | The kind of delegation token |
+*---------------+--------------+-------------------------------+
+| expiration-time | long | The expiration time of the token |
+*---------------+--------------+-------------------------------+
+| max-validity | long | The maximum validity of the token |
+*---------------+--------------+-------------------------------+
+
+** Response Examples
+
+*** Creating a token
+
+ <<JSON response>>
+
+ HTTP Request:
+
+------
+ POST http://<rm http address:port>/ws/v1/cluster/delegation-token
+ Accept: application/json
+ Content-Type: application/json
+ {
+ "renewer" : "test-renewer"
+ }
+------
+
+ Response Header
+
++---+
+ HTTP/1.1 200 OK
+ WWW-Authenticate: Negotiate ...
+ Date: Sat, 28 Jun 2014 18:08:11 GMT
+ Server: Jetty(6.1.26)
+ Set-Cookie: ...
+ Content-Type: application/json
++---+
+
+ Response body
+
++---+
+ {
+
"token":"MgASY2xpZW50QEVYQU1QTEUuQ09NDHRlc3QtcmVuZXdlcgCKAUckiEZpigFHSJTKaQECFN9EMM9BzfPoDxu572EVUpzqhnSGE1JNX0RFTEVHQVRJT05fVE9LRU4A",
+ "renewer":"test-renewer",
+ "owner":"[email protected]",
+ "kind":"RM_DELEGATION_TOKEN",
+ "expiration-time":"1405153616489",
+ "max-validity":"1405672016489"
+ }
++---+
+
+ <<XML response>>
+
+ HTTP Request
+
+------
+ POST http://<rm http address:port>/ws/v1/cluster/delegation-token
+ Accept: application/xml
+ Content-Type: application/xml
+ <delegation-token>
+ <renewer>test-renewer</renewer>
+ </delegation-token>
+------
+
+ Response Header
+
++---+
+ HTTP/1.1 200 OK
+ WWW-Authenticate: Negotiate ...
+ Date: Sat, 28 Jun 2014 18:08:11 GMT
+ Content-Length: 423
+ Server: Jetty(6.1.26)
+ Set-Cookie: ...
+ Content-Type: application/xml
++---+
+
+ Response Body
+
++---+
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+ <delegation-token>
+
<token>MgASY2xpZW50QEVYQU1QTEUuQ09NDHRlc3QtcmVuZXdlcgCKAUckgZ8yigFHSI4jMgcCFDTG8X6XFFn2udQngzSXQL8vWaKIE1JNX0RFTEVHQVRJT05fVE9LRU4A</token>
+ <renewer>test-renewer</renewer>
+ <owner>[email protected]</owner>
+ <kind>RM_DELEGATION_TOKEN</kind>
+ <expiration-time>1405153180466</expiration-time>
+ <max-validity>1405671580466</max-validity>
+ </delegation-token>
++---+
+
+*** Renewing a token
+
+ <<JSON response>>
+
+ HTTP Request:
+
+------
+ POST http://<rm http address:port>/ws/v1/cluster/delegation-token/expiration
+ Accept: application/json
+ Hadoop-YARN-RM-Delegation-Token:
MgASY2xpZW50QEVYQU1QTEUuQ09NDHRlc3QtcmVuZXdlcgCKAUbjqcHHigFHB7ZFxwQCFKWD3znCkDSy6SQIjRCLDydxbxvgE1JNX0RFTEVHQVRJT05fVE9LRU4A
+ Content-Type: application/json
+------
+
+ Response Header
+
++---+
+ HTTP/1.1 200 OK
+ WWW-Authenticate: Negotiate ...
+ Date: Sat, 28 Jun 2014 18:08:11 GMT
+ Server: Jetty(6.1.26)
+ Set-Cookie: ...
+ Content-Type: application/json
++---+
+
+ Response body
+
++---+
+ {
+ "expiration-time":"1404112520402"
+ }
++---+
+
+ <<XML response>>
+
+ HTTP Request
+
+------
+ POST http://<rm http address:port>/ws/v1/cluster/delegation-token/expiration
+ Accept: application/xml
+ Content-Type: application/xml
+ Hadoop-YARN-RM-Delegation-Token:
MgASY2xpZW50QEVYQU1QTEUuQ09NDHRlc3QtcmVuZXdlcgCKAUbjqcHHigFHB7ZFxwQCFKWD3znCkDSy6SQIjRCLDydxbxvgE1JNX0RFTEVHQVRJT05fVE9LRU4A
+------
+
+ Response Header
+
++---+
+ HTTP/1.1 200 OK
+ WWW-Authenticate: Negotiate ...
+ Date: Sat, 28 Jun 2014 18:08:11 GMT
+ Content-Length: 423
+ Server: Jetty(6.1.26)
+ Set-Cookie: ...
+ Content-Type: application/xml
++---+
+
+ Response Body
+
++---+
+ <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+ <delegation-token>
+ <expiration-time>1404112520402</expiration-time>
+ </delegation-token>
++---+
+
+*** Cancelling a token
+
+ HTTP Request
+
+-----
+DELETE http://<rm http address:port>/ws/v1/cluster/delegation-token
+Hadoop-YARN-RM-Delegation-Token:
MgASY2xpZW50QEVYQU1QTEUuQ09NDHRlc3QtcmVuZXdlcgCKAUbjqcHHigFHB7ZFxwQCFKWD3znCkDSy6SQIjRCLDydxbxvgE1JNX0RFTEVHQVRJT05fVE9LRU4A
+Accept: application/xml
+-----
+
+ Response Header
+
++---+
+ HTTP/1.1 200 OK
+ WWW-Authenticate: Negotiate ...
+ Date: Sun, 29 Jun 2014 07:25:18 GMT
+ Transfer-Encoding: chunked
+ Server: Jetty(6.1.26)
+ Set-Cookie: ...
+ Content-Type: application/xml
++---+
+
+ No response body.