Skip to content

Commit 2b67668

Browse files
author
slfan1989
committed
YARN-11225. [Federation] Add postDelegationToken postDelegationTokenExpiration cancelDelegationToken REST APIs for Router.
1 parent 8a9bdb1 commit 2b67668

File tree

9 files changed

+548
-12
lines changed

9 files changed

+548
-12
lines changed

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-router/src/main/java/org/apache/hadoop/yarn/server/router/clientrm/RouterClientRMService.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -611,4 +611,16 @@ protected RouterDelegationTokenSecretManager createRouterRMDelegationTokenSecret
611611
public RouterDelegationTokenSecretManager getRouterDTSecretManager() {
612612
return routerDTSecretManager;
613613
}
614+
615+
@VisibleForTesting
616+
public void setRouterDTSecretManager(RouterDelegationTokenSecretManager routerDTSecretManager) {
617+
this.routerDTSecretManager = routerDTSecretManager;
618+
}
619+
620+
@VisibleForTesting
621+
public void initUserPipelineMap(Configuration conf) {
622+
int maxCacheSize = conf.getInt(YarnConfiguration.ROUTER_PIPELINE_CACHE_MAX_SIZE,
623+
YarnConfiguration.DEFAULT_ROUTER_PIPELINE_CACHE_MAX_SIZE);
624+
this.userPipelineMap = Collections.synchronizedMap(new LRUCacheHashMap<>(maxCacheSize, true));
625+
}
614626
}

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-router/src/main/java/org/apache/hadoop/yarn/server/router/security/RouterDelegationTokenSecretManager.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,4 +251,14 @@ public synchronized Map<RMDelegationTokenIdentifier, Long> getAllTokens() {
251251
}
252252
return allTokens;
253253
}
254+
255+
public long getRenewDate(RMDelegationTokenIdentifier ident)
256+
throws InvalidToken {
257+
DelegationTokenInformation info = currentTokens.get(ident);
258+
if (info == null) {
259+
throw new InvalidToken("token (" + ident.toString()
260+
+ ") can't be found in cache");
261+
}
262+
return info.getRenewDate();
263+
}
254264
}

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-router/src/main/java/org/apache/hadoop/yarn/server/router/webapp/AbstractRESTRequestInterceptor.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.apache.hadoop.conf.Configuration;
2222
import org.apache.hadoop.security.UserGroupInformation;
2323
import org.apache.hadoop.yarn.exceptions.YarnRuntimeException;
24+
import org.apache.hadoop.yarn.server.router.clientrm.RouterClientRMService;
2425

2526
import java.io.IOException;
2627

@@ -34,6 +35,7 @@ public abstract class AbstractRESTRequestInterceptor
3435
private Configuration conf;
3536
private RESTRequestInterceptor nextInterceptor;
3637
private UserGroupInformation user = null;
38+
private RouterClientRMService routerClientRMService = null;
3739

3840
/**
3941
* Sets the {@link RESTRequestInterceptor} in the chain.
@@ -123,4 +125,14 @@ private void setupUser(final String userName) {
123125
public UserGroupInformation getUser() {
124126
return user;
125127
}
128+
129+
@Override
130+
public RouterClientRMService getRouterClientRMService() {
131+
return routerClientRMService;
132+
}
133+
134+
@Override
135+
public void setRouterClientRMService(RouterClientRMService routerClientRMService) {
136+
this.routerClientRMService = routerClientRMService;
137+
}
126138
}

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-router/src/main/java/org/apache/hadoop/yarn/server/router/webapp/FederationInterceptorREST.java

Lines changed: 175 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.io.IOException;
2222
import java.lang.reflect.Method;
2323
import java.security.Principal;
24+
import java.security.PrivilegedExceptionAction;
2425
import java.util.ArrayList;
2526
import java.util.Collection;
2627
import java.util.HashMap;
@@ -46,11 +47,15 @@
4647
import org.apache.commons.lang3.StringUtils;
4748
import org.apache.commons.lang3.tuple.Pair;
4849
import org.apache.hadoop.conf.Configuration;
50+
import org.apache.hadoop.io.Text;
51+
import org.apache.hadoop.security.UserGroupInformation;
4952
import org.apache.hadoop.security.authorize.AuthorizationException;
53+
import org.apache.hadoop.security.token.Token;
5054
import org.apache.hadoop.util.ReflectionUtils;
5155
import org.apache.hadoop.util.Sets;
5256
import org.apache.hadoop.util.Time;
5357
import org.apache.hadoop.util.concurrent.HadoopExecutors;
58+
import org.apache.hadoop.yarn.api.protocolrecords.*;
5459
import org.apache.hadoop.yarn.api.records.ApplicationId;
5560
import org.apache.hadoop.yarn.api.records.ApplicationSubmissionContext;
5661
import org.apache.hadoop.yarn.api.records.ContainerId;
@@ -59,6 +64,7 @@
5964
import org.apache.hadoop.yarn.conf.YarnConfiguration;
6065
import org.apache.hadoop.yarn.exceptions.YarnException;
6166
import org.apache.hadoop.yarn.exceptions.YarnRuntimeException;
67+
import org.apache.hadoop.yarn.security.client.RMDelegationTokenIdentifier;
6268
import org.apache.hadoop.yarn.server.federation.policies.FederationPolicyUtils;
6369
import org.apache.hadoop.yarn.server.federation.policies.RouterPolicyFacade;
6470
import org.apache.hadoop.yarn.server.federation.policies.exceptions.FederationPolicyException;
@@ -104,8 +110,11 @@
104110
import org.apache.hadoop.yarn.server.router.RouterMetrics;
105111
import org.apache.hadoop.yarn.server.router.RouterServerUtil;
106112
import org.apache.hadoop.yarn.server.router.clientrm.ClientMethod;
113+
import org.apache.hadoop.yarn.server.router.clientrm.RouterClientRMService;
114+
import org.apache.hadoop.yarn.server.router.security.RouterDelegationTokenSecretManager;
107115
import org.apache.hadoop.yarn.server.router.webapp.cache.RouterAppInfoCacheKey;
108116
import org.apache.hadoop.yarn.server.router.webapp.dao.FederationRMQueueAclInfo;
117+
import org.apache.hadoop.yarn.server.utils.BuilderUtils;
109118
import org.apache.hadoop.yarn.server.webapp.dao.AppAttemptInfo;
110119
import org.apache.hadoop.yarn.server.webapp.dao.ContainerInfo;
111120
import org.apache.hadoop.yarn.server.webapp.dao.ContainersInfo;
@@ -121,6 +130,9 @@
121130
import org.apache.hadoop.classification.VisibleForTesting;
122131
import org.apache.hadoop.thirdparty.com.google.common.util.concurrent.ThreadFactoryBuilder;
123132

133+
import static org.apache.hadoop.yarn.server.router.webapp.RouterWebServiceUtil.extractToken;
134+
import static org.apache.hadoop.yarn.server.router.webapp.RouterWebServiceUtil.getKerberosUserGroupInformation;
135+
124136
/**
125137
* Extends the {@code AbstractRESTRequestInterceptor} class and provides an
126138
* implementation for federation of YARN RM and scaling an application across
@@ -1556,25 +1568,178 @@ public Response updateAppQueue(AppQueue targetQueue, HttpServletRequest hsr,
15561568
throw new RuntimeException("updateAppQueue Failed.");
15571569
}
15581570

1571+
/**
1572+
* This method posts a delegation token from the client.
1573+
*
1574+
* @param tokenData the token to delegate. It is a content param.
1575+
* @param hsr the servlet request.
1576+
* @return Response containing the status code.
1577+
* @throws AuthorizationException if Kerberos auth failed.
1578+
* @throws IOException if the delegation failed.
1579+
* @throws InterruptedException if interrupted.
1580+
* @throws Exception in case of bad request.
1581+
*/
15591582
@Override
1560-
public Response postDelegationToken(DelegationToken tokenData,
1561-
HttpServletRequest hsr) throws AuthorizationException, IOException,
1562-
InterruptedException, Exception {
1563-
throw new NotImplementedException("Code is not implemented");
1583+
public Response postDelegationToken(DelegationToken tokenData, HttpServletRequest hsr)
1584+
throws AuthorizationException, IOException, InterruptedException, Exception {
1585+
1586+
if (tokenData == null || hsr == null) {
1587+
throw new IllegalArgumentException("Parameter error, the tokenData or hsr is null.");
1588+
}
1589+
1590+
try {
1591+
// get Caller UserGroupInformation
1592+
Configuration conf = federationFacade.getConf();
1593+
UserGroupInformation callerUGI = getKerberosUserGroupInformation(conf, hsr);
1594+
1595+
// create a delegation token
1596+
return createDelegationToken(tokenData, callerUGI);
1597+
} catch (YarnException e) {
1598+
LOG.error("Create delegation token request failed.", e);
1599+
return Response.status(Status.FORBIDDEN).entity(e.getMessage()).build();
1600+
}
15641601
}
15651602

1603+
/**
1604+
* Create DelegationToken.
1605+
*
1606+
* @param dtoken DelegationToken Data.
1607+
* @param callerUGI UserGroupInformation.
1608+
* @return Response.
1609+
* @throws Exception An exception occurred when creating a delegationToken.
1610+
*/
1611+
private Response createDelegationToken(DelegationToken dtoken, UserGroupInformation callerUGI)
1612+
throws IOException, InterruptedException {
1613+
1614+
String renewer = dtoken.getRenewer();
1615+
1616+
GetDelegationTokenResponse resp = callerUGI.doAs(
1617+
(PrivilegedExceptionAction<GetDelegationTokenResponse>) () -> {
1618+
GetDelegationTokenRequest createReq = GetDelegationTokenRequest.newInstance(renewer);
1619+
return this.getRouterClientRMService().getDelegationToken(createReq);
1620+
});
1621+
1622+
org.apache.hadoop.yarn.api.records.Token token = resp.getRMDelegationToken();
1623+
byte[] identifier = token.getIdentifier().array();
1624+
byte[] password = token.getPassword().array();
1625+
Text kind = new Text(token.getKind());
1626+
Text service = new Text(token.getService());
1627+
Token<RMDelegationTokenIdentifier> tk = new Token<>(identifier, password, kind, service);
1628+
1629+
RMDelegationTokenIdentifier tokenIdentifier = tk.decodeIdentifier();
1630+
RouterClientRMService clientRMService = this.getRouterClientRMService();
1631+
RouterDelegationTokenSecretManager tokenSecretManager =
1632+
clientRMService.getRouterDTSecretManager();
1633+
long currentExpiration = tokenSecretManager.getRenewDate(tokenIdentifier);
1634+
1635+
String owner = tokenIdentifier.getOwner().toString();
1636+
String tokenKind = tk.getKind().toString();
1637+
long maxDate = tokenIdentifier.getMaxDate();
1638+
DelegationToken respToken = new DelegationToken(tk.encodeToUrlString(),
1639+
renewer, owner, tokenKind, currentExpiration, maxDate);
1640+
return Response.status(Status.OK).entity(respToken).build();
1641+
}
1642+
1643+
/**
1644+
* This method updates the expiration for a delegation token from the client.
1645+
*
1646+
* @param hsr the servlet request
1647+
* @return Response containing the status code.
1648+
* @throws AuthorizationException if Kerberos auth failed.
1649+
* @throws IOException if the delegation failed.
1650+
* @throws InterruptedException if interrupted.
1651+
* @throws Exception in case of bad request.
1652+
*/
15661653
@Override
15671654
public Response postDelegationTokenExpiration(HttpServletRequest hsr)
1568-
throws AuthorizationException, IOException, InterruptedException,
1569-
Exception {
1570-
throw new NotImplementedException("Code is not implemented");
1655+
throws AuthorizationException, IOException, InterruptedException, Exception {
1656+
1657+
if (hsr == null) {
1658+
throw new IllegalArgumentException("Parameter error, the hsr is null.");
1659+
}
1660+
1661+
try {
1662+
// get Caller UserGroupInformation
1663+
Configuration conf = federationFacade.getConf();
1664+
UserGroupInformation callerUGI = getKerberosUserGroupInformation(conf, hsr);
1665+
1666+
// renew Delegation Token
1667+
DelegationToken requestToken = new DelegationToken();
1668+
String token = extractToken(hsr).encodeToUrlString();
1669+
requestToken.setToken(token);
1670+
return renewDelegationToken(requestToken, callerUGI);
1671+
} catch (YarnException e) {
1672+
LOG.error("Renew delegation token request failed.", e);
1673+
return Response.status(Status.FORBIDDEN).entity(e.getMessage()).build();
1674+
}
15711675
}
15721676

1677+
/**
1678+
* Renew DelegationToken.
1679+
*
1680+
* @param tokenData DelegationToken.
1681+
* @param callerUGI UserGroupInformation.
1682+
* @return Response
1683+
* @throws IOException if there are I/O errors.
1684+
* @throws InterruptedException if any thread has interrupted.
1685+
*/
1686+
private Response renewDelegationToken(DelegationToken tokenData, UserGroupInformation callerUGI)
1687+
throws IOException, InterruptedException {
1688+
// Parse token data
1689+
Token<RMDelegationTokenIdentifier> token = extractToken(tokenData.getToken());
1690+
org.apache.hadoop.yarn.api.records.Token dToken =
1691+
BuilderUtils.newDelegationToken(token.getIdentifier(), token.getKind().toString(),
1692+
token.getPassword(), token.getService().toString());
1693+
1694+
// Renew token
1695+
RenewDelegationTokenResponse resp = callerUGI.doAs(
1696+
(PrivilegedExceptionAction<RenewDelegationTokenResponse>) () -> {
1697+
RenewDelegationTokenRequest req = RenewDelegationTokenRequest.newInstance(dToken);
1698+
return this.getRouterClientRMService().renewDelegationToken(req);
1699+
});
1700+
1701+
// return DelegationToken
1702+
long renewTime = resp.getNextExpirationTime();
1703+
DelegationToken respToken = new DelegationToken();
1704+
respToken.setNextExpirationTime(renewTime);
1705+
return Response.status(Status.OK).entity(respToken).build();
1706+
}
1707+
1708+
/**
1709+
* Cancel DelegationToken.
1710+
*
1711+
* @param hsr the servlet request
1712+
* @return Response containing the status code.
1713+
* @throws AuthorizationException if Kerberos auth failed.
1714+
* @throws IOException if the delegation failed.
1715+
* @throws InterruptedException if interrupted.
1716+
* @throws Exception in case of bad request.
1717+
*/
15731718
@Override
15741719
public Response cancelDelegationToken(HttpServletRequest hsr)
1575-
throws AuthorizationException, IOException, InterruptedException,
1576-
Exception {
1577-
throw new NotImplementedException("Code is not implemented");
1720+
throws AuthorizationException, IOException, InterruptedException, Exception {
1721+
try {
1722+
// get Caller UserGroupInformation
1723+
Configuration conf = federationFacade.getConf();
1724+
UserGroupInformation callerUGI = getKerberosUserGroupInformation(conf, hsr);
1725+
1726+
// parse Token Data
1727+
Token<RMDelegationTokenIdentifier> token = extractToken(hsr);
1728+
org.apache.hadoop.yarn.api.records.Token dToken = BuilderUtils
1729+
.newDelegationToken(token.getIdentifier(), token.getKind().toString(),
1730+
token.getPassword(), token.getService().toString());
1731+
1732+
// cancelDelegationToken
1733+
callerUGI.doAs((PrivilegedExceptionAction<CancelDelegationTokenResponse>) () -> {
1734+
CancelDelegationTokenRequest req = CancelDelegationTokenRequest.newInstance(dToken);
1735+
return this.getRouterClientRMService().cancelDelegationToken(req);
1736+
});
1737+
1738+
return Response.status(Status.OK).build();
1739+
} catch (YarnException e) {
1740+
LOG.error("Cancel delegation token request failed.", e);
1741+
return Response.status(Status.FORBIDDEN).entity(e.getMessage()).build();
1742+
}
15781743
}
15791744

15801745
@Override

hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-router/src/main/java/org/apache/hadoop/yarn/server/router/webapp/RESTRequestInterceptor.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
import org.apache.hadoop.conf.Configurable;
2525
import org.apache.hadoop.yarn.server.resourcemanager.webapp.RMWebServiceProtocol;
26+
import org.apache.hadoop.yarn.server.router.clientrm.RouterClientRMService;
2627
import org.apache.hadoop.yarn.server.webapp.WebServices;
2728
import org.apache.hadoop.yarn.server.webapp.dao.AppAttemptInfo;
2829
import org.apache.hadoop.yarn.server.webapp.dao.ContainerInfo;
@@ -122,4 +123,18 @@ ContainersInfo getContainers(HttpServletRequest req, HttpServletResponse res,
122123
*/
123124
ContainerInfo getContainer(HttpServletRequest req, HttpServletResponse res,
124125
String appId, String appAttemptId, String containerId);
126+
127+
/**
128+
* Set RouterClientRMService.
129+
*
130+
* @param routerClientRMService routerClientRMService.
131+
*/
132+
void setRouterClientRMService(RouterClientRMService routerClientRMService);
133+
134+
/**
135+
* Get RouterClientRMService.
136+
*
137+
* @return RouterClientRMService
138+
*/
139+
RouterClientRMService getRouterClientRMService();
125140
}

0 commit comments

Comments
 (0)