YARN-320. RM should always be able to renew its own tokens. Contributed by Daryn Sharp
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1431020 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
0ba7078ef4
commit
ba5b19fb5d
@ -287,6 +287,9 @@ Release 0.23.6 - UNRELEASED
|
|||||||
YARN-50. Implement renewal / cancellation of Delegation Tokens
|
YARN-50. Implement renewal / cancellation of Delegation Tokens
|
||||||
(Siddharth Seth via tgraves)
|
(Siddharth Seth via tgraves)
|
||||||
|
|
||||||
|
YARN-320. RM should always be able to renew its own tokens.
|
||||||
|
(Daryn Sharp via sseth)
|
||||||
|
|
||||||
Release 0.23.5 - UNRELEASED
|
Release 0.23.5 - UNRELEASED
|
||||||
|
|
||||||
INCOMPATIBLE CHANGES
|
INCOMPATIBLE CHANGES
|
||||||
|
@ -519,7 +519,7 @@ public RenewDelegationTokenResponse renewDelegationToken(
|
|||||||
protoToken.getIdentifier().array(), protoToken.getPassword().array(),
|
protoToken.getIdentifier().array(), protoToken.getPassword().array(),
|
||||||
new Text(protoToken.getKind()), new Text(protoToken.getService()));
|
new Text(protoToken.getKind()), new Text(protoToken.getService()));
|
||||||
|
|
||||||
String user = UserGroupInformation.getCurrentUser().getShortUserName();
|
String user = getRenewerForToken(token);
|
||||||
long nextExpTime = rmDTSecretManager.renewToken(token, user);
|
long nextExpTime = rmDTSecretManager.renewToken(token, user);
|
||||||
RenewDelegationTokenResponse renewResponse = Records
|
RenewDelegationTokenResponse renewResponse = Records
|
||||||
.newRecord(RenewDelegationTokenResponse.class);
|
.newRecord(RenewDelegationTokenResponse.class);
|
||||||
@ -543,7 +543,7 @@ public CancelDelegationTokenResponse cancelDelegationToken(
|
|||||||
protoToken.getIdentifier().array(), protoToken.getPassword().array(),
|
protoToken.getIdentifier().array(), protoToken.getPassword().array(),
|
||||||
new Text(protoToken.getKind()), new Text(protoToken.getService()));
|
new Text(protoToken.getKind()), new Text(protoToken.getService()));
|
||||||
|
|
||||||
String user = UserGroupInformation.getCurrentUser().getShortUserName();
|
String user = getRenewerForToken(token);
|
||||||
rmDTSecretManager.cancelToken(token, user);
|
rmDTSecretManager.cancelToken(token, user);
|
||||||
return Records.newRecord(CancelDelegationTokenResponse.class);
|
return Records.newRecord(CancelDelegationTokenResponse.class);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -551,6 +551,16 @@ public CancelDelegationTokenResponse cancelDelegationToken(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getRenewerForToken(Token<RMDelegationTokenIdentifier> token)
|
||||||
|
throws IOException {
|
||||||
|
UserGroupInformation user = UserGroupInformation.getCurrentUser();
|
||||||
|
UserGroupInformation loginUser = UserGroupInformation.getLoginUser();
|
||||||
|
// we can always renew our own tokens
|
||||||
|
return loginUser.getUserName().equals(user.getUserName())
|
||||||
|
? token.decodeIdentifier().getRenewer().toString()
|
||||||
|
: user.getShortUserName();
|
||||||
|
}
|
||||||
|
|
||||||
void refreshServiceAcls(Configuration configuration,
|
void refreshServiceAcls(Configuration configuration,
|
||||||
PolicyProvider policyProvider) {
|
PolicyProvider policyProvider) {
|
||||||
this.server.refreshServiceAcl(configuration, policyProvider);
|
this.server.refreshServiceAcl(configuration, policyProvider);
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import java.security.PrivilegedExceptionAction;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
@ -33,14 +34,19 @@
|
|||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.apache.hadoop.conf.Configuration;
|
import org.apache.hadoop.conf.Configuration;
|
||||||
|
import org.apache.hadoop.io.Text;
|
||||||
|
import org.apache.hadoop.security.UserGroupInformation;
|
||||||
|
import org.apache.hadoop.security.token.Token;
|
||||||
import org.apache.hadoop.yarn.api.ClientRMProtocol;
|
import org.apache.hadoop.yarn.api.ClientRMProtocol;
|
||||||
import org.apache.hadoop.yarn.api.protocolrecords.GetApplicationReportRequest;
|
import org.apache.hadoop.yarn.api.protocolrecords.GetApplicationReportRequest;
|
||||||
import org.apache.hadoop.yarn.api.protocolrecords.GetApplicationReportResponse;
|
import org.apache.hadoop.yarn.api.protocolrecords.GetApplicationReportResponse;
|
||||||
import org.apache.hadoop.yarn.api.protocolrecords.GetClusterNodesRequest;
|
import org.apache.hadoop.yarn.api.protocolrecords.GetClusterNodesRequest;
|
||||||
import org.apache.hadoop.yarn.api.protocolrecords.GetQueueInfoRequest;
|
import org.apache.hadoop.yarn.api.protocolrecords.GetQueueInfoRequest;
|
||||||
import org.apache.hadoop.yarn.api.protocolrecords.GetQueueInfoResponse;
|
import org.apache.hadoop.yarn.api.protocolrecords.GetQueueInfoResponse;
|
||||||
|
import org.apache.hadoop.yarn.api.protocolrecords.RenewDelegationTokenRequest;
|
||||||
import org.apache.hadoop.yarn.api.records.ApplicationId;
|
import org.apache.hadoop.yarn.api.records.ApplicationId;
|
||||||
import org.apache.hadoop.yarn.api.records.ApplicationReport;
|
import org.apache.hadoop.yarn.api.records.ApplicationReport;
|
||||||
|
import org.apache.hadoop.yarn.api.records.DelegationToken;
|
||||||
import org.apache.hadoop.yarn.api.records.NodeReport;
|
import org.apache.hadoop.yarn.api.records.NodeReport;
|
||||||
import org.apache.hadoop.yarn.api.records.QueueInfo;
|
import org.apache.hadoop.yarn.api.records.QueueInfo;
|
||||||
import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
import org.apache.hadoop.yarn.conf.YarnConfiguration;
|
||||||
@ -49,11 +55,16 @@
|
|||||||
import org.apache.hadoop.yarn.factories.RecordFactory;
|
import org.apache.hadoop.yarn.factories.RecordFactory;
|
||||||
import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider;
|
import org.apache.hadoop.yarn.factory.providers.RecordFactoryProvider;
|
||||||
import org.apache.hadoop.yarn.ipc.YarnRPC;
|
import org.apache.hadoop.yarn.ipc.YarnRPC;
|
||||||
|
import org.apache.hadoop.yarn.security.client.RMDelegationTokenIdentifier;
|
||||||
|
import org.apache.hadoop.yarn.server.RMDelegationTokenSecretManager;
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp;
|
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp;
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppImpl;
|
import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppImpl;
|
||||||
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.YarnScheduler;
|
import org.apache.hadoop.yarn.server.resourcemanager.scheduler.YarnScheduler;
|
||||||
|
import org.apache.hadoop.yarn.util.BuilderUtils;
|
||||||
import org.apache.hadoop.yarn.util.Records;
|
import org.apache.hadoop.yarn.util.Records;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
|
||||||
|
|
||||||
public class TestClientRMService {
|
public class TestClientRMService {
|
||||||
@ -63,6 +74,21 @@ public class TestClientRMService {
|
|||||||
private RecordFactory recordFactory = RecordFactoryProvider
|
private RecordFactory recordFactory = RecordFactoryProvider
|
||||||
.getRecordFactory(null);
|
.getRecordFactory(null);
|
||||||
|
|
||||||
|
private static RMDelegationTokenSecretManager dtsm;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void setupSecretManager() throws IOException {
|
||||||
|
dtsm = new RMDelegationTokenSecretManager(60000, 60000, 60000, 60000);
|
||||||
|
dtsm.startThreads();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterClass
|
||||||
|
public static void teardownSecretManager() {
|
||||||
|
if (dtsm != null) {
|
||||||
|
dtsm.stopThreads();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetClusterNodes() throws Exception {
|
public void testGetClusterNodes() throws Exception {
|
||||||
MockRM rm = new MockRM() {
|
MockRM rm = new MockRM() {
|
||||||
@ -141,6 +167,74 @@ public void testGetQueueInfo() throws Exception {
|
|||||||
Assert.assertEquals(2, applications.size());
|
Assert.assertEquals(2, applications.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final UserGroupInformation owner =
|
||||||
|
UserGroupInformation.createRemoteUser("owner");
|
||||||
|
private static final UserGroupInformation other =
|
||||||
|
UserGroupInformation.createRemoteUser("other");
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTokenRenewalByOwner() throws Exception {
|
||||||
|
owner.doAs(new PrivilegedExceptionAction<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void run() throws Exception {
|
||||||
|
checkTokenRenewal(owner, owner);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTokenRenewalWrongUser() throws Exception {
|
||||||
|
try {
|
||||||
|
owner.doAs(new PrivilegedExceptionAction<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void run() throws Exception {
|
||||||
|
checkTokenRenewal(owner, other);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (YarnRemoteException e) {
|
||||||
|
Assert.assertEquals(e.getMessage(),
|
||||||
|
"Client " + owner.getUserName() +
|
||||||
|
" tries to renew a token with renewer specified as " +
|
||||||
|
other.getUserName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Assert.fail("renew should have failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTokenRenewalByLoginUser() throws Exception {
|
||||||
|
UserGroupInformation.getLoginUser().doAs(new PrivilegedExceptionAction<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void run() throws Exception {
|
||||||
|
checkTokenRenewal(owner, owner);
|
||||||
|
checkTokenRenewal(owner, other);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkTokenRenewal(UserGroupInformation owner,
|
||||||
|
UserGroupInformation renewer) throws IOException {
|
||||||
|
RMDelegationTokenIdentifier tokenIdentifier =
|
||||||
|
new RMDelegationTokenIdentifier(
|
||||||
|
new Text(owner.getUserName()), new Text(renewer.getUserName()), null);
|
||||||
|
Token<?> token =
|
||||||
|
new Token<RMDelegationTokenIdentifier>(tokenIdentifier, dtsm);
|
||||||
|
DelegationToken dToken = BuilderUtils.newDelegationToken(
|
||||||
|
token.getIdentifier(), token.getKind().toString(),
|
||||||
|
token.getPassword(), token.getService().toString());
|
||||||
|
RenewDelegationTokenRequest request =
|
||||||
|
Records.newRecord(RenewDelegationTokenRequest.class);
|
||||||
|
request.setDelegationToken(dToken);
|
||||||
|
|
||||||
|
RMContext rmContext = mock(RMContext.class);
|
||||||
|
ClientRMService rmService = new ClientRMService(
|
||||||
|
rmContext, null, null, null, dtsm);
|
||||||
|
rmService.renewDelegationToken(request);
|
||||||
|
}
|
||||||
|
|
||||||
private void mockRMContext(YarnScheduler yarnScheduler, RMContext rmContext)
|
private void mockRMContext(YarnScheduler yarnScheduler, RMContext rmContext)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
Dispatcher dispatcher = mock(Dispatcher.class);
|
Dispatcher dispatcher = mock(Dispatcher.class);
|
||||||
|
Loading…
Reference in New Issue
Block a user