|
21 | 21 | import java.io.IOException;
|
22 | 22 | import java.lang.reflect.Method;
|
23 | 23 | import java.security.Principal;
|
| 24 | +import java.security.PrivilegedExceptionAction; |
24 | 25 | import java.util.ArrayList;
|
25 | 26 | import java.util.Collection;
|
26 | 27 | import java.util.HashMap;
|
|
46 | 47 | import org.apache.commons.lang3.StringUtils;
|
47 | 48 | import org.apache.commons.lang3.tuple.Pair;
|
48 | 49 | import org.apache.hadoop.conf.Configuration;
|
| 50 | +import org.apache.hadoop.io.Text; |
| 51 | +import org.apache.hadoop.security.UserGroupInformation; |
49 | 52 | import org.apache.hadoop.security.authorize.AuthorizationException;
|
| 53 | +import org.apache.hadoop.security.token.Token; |
50 | 54 | import org.apache.hadoop.util.ReflectionUtils;
|
51 | 55 | import org.apache.hadoop.util.Sets;
|
52 | 56 | import org.apache.hadoop.util.Time;
|
53 | 57 | import org.apache.hadoop.util.concurrent.HadoopExecutors;
|
| 58 | +import org.apache.hadoop.yarn.api.protocolrecords.*; |
54 | 59 | import org.apache.hadoop.yarn.api.records.ApplicationId;
|
55 | 60 | import org.apache.hadoop.yarn.api.records.ApplicationSubmissionContext;
|
56 | 61 | import org.apache.hadoop.yarn.api.records.ContainerId;
|
|
59 | 64 | import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
60 | 65 | import org.apache.hadoop.yarn.exceptions.YarnException;
|
61 | 66 | import org.apache.hadoop.yarn.exceptions.YarnRuntimeException;
|
| 67 | +import org.apache.hadoop.yarn.security.client.RMDelegationTokenIdentifier; |
62 | 68 | import org.apache.hadoop.yarn.server.federation.policies.FederationPolicyUtils;
|
63 | 69 | import org.apache.hadoop.yarn.server.federation.policies.RouterPolicyFacade;
|
64 | 70 | import org.apache.hadoop.yarn.server.federation.policies.exceptions.FederationPolicyException;
|
|
104 | 110 | import org.apache.hadoop.yarn.server.router.RouterMetrics;
|
105 | 111 | import org.apache.hadoop.yarn.server.router.RouterServerUtil;
|
106 | 112 | 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; |
107 | 115 | import org.apache.hadoop.yarn.server.router.webapp.cache.RouterAppInfoCacheKey;
|
108 | 116 | import org.apache.hadoop.yarn.server.router.webapp.dao.FederationRMQueueAclInfo;
|
| 117 | +import org.apache.hadoop.yarn.server.utils.BuilderUtils; |
109 | 118 | import org.apache.hadoop.yarn.server.webapp.dao.AppAttemptInfo;
|
110 | 119 | import org.apache.hadoop.yarn.server.webapp.dao.ContainerInfo;
|
111 | 120 | import org.apache.hadoop.yarn.server.webapp.dao.ContainersInfo;
|
|
121 | 130 | import org.apache.hadoop.classification.VisibleForTesting;
|
122 | 131 | import org.apache.hadoop.thirdparty.com.google.common.util.concurrent.ThreadFactoryBuilder;
|
123 | 132 |
|
| 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 | + |
124 | 136 | /**
|
125 | 137 | * Extends the {@code AbstractRESTRequestInterceptor} class and provides an
|
126 | 138 | * implementation for federation of YARN RM and scaling an application across
|
@@ -1556,25 +1568,178 @@ public Response updateAppQueue(AppQueue targetQueue, HttpServletRequest hsr,
|
1556 | 1568 | throw new RuntimeException("updateAppQueue Failed.");
|
1557 | 1569 | }
|
1558 | 1570 |
|
| 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 | + */ |
1559 | 1582 | @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 | + } |
1564 | 1601 | }
|
1565 | 1602 |
|
| 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 | + */ |
1566 | 1653 | @Override
|
1567 | 1654 | 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 | + } |
1571 | 1675 | }
|
1572 | 1676 |
|
| 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 | + */ |
1573 | 1718 | @Override
|
1574 | 1719 | 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 | + } |
1578 | 1743 | }
|
1579 | 1744 |
|
1580 | 1745 | @Override
|
|
0 commit comments