diff --git hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenSecretManager.java hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenSecretManager.java index fde11e7..566a8fe 100644 --- hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenSecretManager.java +++ hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/security/token/delegation/AbstractDelegationTokenSecretManager.java @@ -26,6 +26,7 @@ import java.io.DataInputStream; import java.io.IOException; import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -40,6 +41,7 @@ import org.apache.hadoop.security.HadoopKerberosName; import org.apache.hadoop.security.token.Token; import org.apache.hadoop.security.token.SecretManager; +import org.apache.hadoop.security.token.TokenIdentifier; import org.apache.hadoop.util.Daemon; import org.apache.hadoop.util.Time; @@ -304,7 +306,30 @@ public synchronized long renewToken(Token token, currentTokens.put(id, info); return renewTime; } - + + /** + * Recover tokens after RM restart + * @param allTokns the tokens to recover + * @throws IOException + */ + public void recoverTokens( + Collection> allTokens) + throws IOException { + + LOG.info("Recovering delegation tokens into DelegationTokenSecretManager"); + for(Token token : allTokens) { + long now = Time.now(); + ByteArrayInputStream buf = new ByteArrayInputStream(token.getIdentifier()); + DataInputStream in = new DataInputStream(buf); + TokenIdent id = createIdentifier(); + id.readFields(in); + long renewTime = Math.min(id.getMaxDate(), now + tokenRenewInterval); + DelegationTokenInformation info = + new DelegationTokenInformation(renewTime, token.getPassword()); + currentTokens.put(id, info); + } + } + /** * Cancel a token by removing it from cache. * @return Identifier of the canceled token diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMAppManager.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMAppManager.java index 5cc4de1..7877234 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMAppManager.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMAppManager.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.nio.ByteBuffer; +import java.util.Collection; import java.util.LinkedList; import java.util.Map; @@ -28,6 +29,8 @@ import org.apache.hadoop.io.DataInputByteBuffer; import org.apache.hadoop.security.Credentials; import org.apache.hadoop.security.UserGroupInformation; +import org.apache.hadoop.security.token.Token; +import org.apache.hadoop.security.token.TokenIdentifier; import org.apache.hadoop.util.StringUtils; import org.apache.hadoop.yarn.api.records.ApplicationId; import org.apache.hadoop.yarn.api.records.ApplicationSubmissionContext; @@ -289,10 +292,13 @@ protected void submitApplication( try { // Setup tokens for renewal if (UserGroupInformation.isSecurityEnabled()) { + Credentials ts = parseCredentials(submissionContext); + Collection> allTokens = + ts.getAllTokens(); + this.rmContext.getRMDelegationTokenSecretManager().recoverTokens( + allTokens); this.rmContext.getDelegationTokenRenewer().addApplication( - applicationId,parseCredentials(submissionContext), - submissionContext.getCancelTokensWhenComplete() - ); + applicationId, ts, submissionContext.getCancelTokensWhenComplete()); } } catch (IOException ie) { LOG.warn( diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMContext.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMContext.java index b487670..9a400a8 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMContext.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMContext.java @@ -23,6 +23,7 @@ import org.apache.hadoop.yarn.api.records.ApplicationId; import org.apache.hadoop.yarn.api.records.NodeId; import org.apache.hadoop.yarn.event.Dispatcher; +import org.apache.hadoop.yarn.server.RMDelegationTokenSecretManager; import org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore; import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp; import org.apache.hadoop.yarn.server.resourcemanager.rmapp.attempt.AMLivelinessMonitor; @@ -56,6 +57,8 @@ DelegationTokenRenewer getDelegationTokenRenewer(); + RMDelegationTokenSecretManager getRMDelegationTokenSecretManager(); + ApplicationTokenSecretManager getApplicationTokenSecretManager(); RMContainerTokenSecretManager getContainerTokenSecretManager(); diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMContextImpl.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMContextImpl.java index 840d129..1c45486 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMContextImpl.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMContextImpl.java @@ -25,6 +25,7 @@ import org.apache.hadoop.yarn.api.records.NodeId; import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.event.Dispatcher; +import org.apache.hadoop.yarn.server.RMDelegationTokenSecretManager; import org.apache.hadoop.yarn.server.resourcemanager.recovery.NullRMStateStore; import org.apache.hadoop.yarn.server.resourcemanager.recovery.RMStateStore; import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMApp; @@ -59,6 +60,7 @@ private final ApplicationTokenSecretManager appTokenSecretManager; private final RMContainerTokenSecretManager containerTokenSecretManager; private final ClientToAMTokenSecretManagerInRM clientToAMTokenSecretManager; + private final RMDelegationTokenSecretManager rmDelegationTokenSecretManager; public RMContextImpl(Dispatcher rmDispatcher, RMStateStore store, @@ -68,7 +70,8 @@ public RMContextImpl(Dispatcher rmDispatcher, DelegationTokenRenewer tokenRenewer, ApplicationTokenSecretManager appTokenSecretManager, RMContainerTokenSecretManager containerTokenSecretManager, - ClientToAMTokenSecretManagerInRM clientTokenSecretManager) { + ClientToAMTokenSecretManagerInRM clientTokenSecretManager, + RMDelegationTokenSecretManager rmDTSecretManager) { this.rmDispatcher = rmDispatcher; this.stateStore = store; this.containerAllocationExpirer = containerAllocationExpirer; @@ -78,6 +81,7 @@ public RMContextImpl(Dispatcher rmDispatcher, this.appTokenSecretManager = appTokenSecretManager; this.containerTokenSecretManager = containerTokenSecretManager; this.clientToAMTokenSecretManager = clientTokenSecretManager; + this.rmDelegationTokenSecretManager = rmDTSecretManager; } @VisibleForTesting @@ -92,7 +96,7 @@ public RMContextImpl(Dispatcher rmDispatcher, ClientToAMTokenSecretManagerInRM clientTokenSecretManager) { this(rmDispatcher, null, containerAllocationExpirer, amLivelinessMonitor, amFinishingMonitor, tokenRenewer, appTokenSecretManager, - containerTokenSecretManager, clientTokenSecretManager); + containerTokenSecretManager, clientTokenSecretManager, null); RMStateStore nullStore = new NullRMStateStore(); nullStore.setDispatcher(rmDispatcher); try { @@ -167,4 +171,9 @@ public ClientToAMTokenSecretManagerInRM getClientToAMTokenSecretManager() { public void setStateStore(RMStateStore store) { stateStore = store; } + + @Override + public RMDelegationTokenSecretManager getRMDelegationTokenSecretManager() { + return this.rmDelegationTokenSecretManager; + } } \ No newline at end of file diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceManager.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceManager.java index 4cd1969..f9d858a 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceManager.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/ResourceManager.java @@ -164,6 +164,7 @@ public synchronized void init(Configuration conf) { addService(tokenRenewer); this.containerTokenSecretManager = createContainerTokenSecretManager(conf); + this.rmDTSecretManager = createRMDelegationTokenSecretManager(); boolean isRecoveryEnabled = conf.getBoolean( YarnConfiguration.RECOVERY_ENABLED, @@ -191,7 +192,8 @@ public synchronized void init(Configuration conf) { new RMContextImpl(this.rmDispatcher, rmStore, this.containerAllocationExpirer, amLivelinessMonitor, amFinishingMonitor, tokenRenewer, this.appTokenSecretManager, - this.containerTokenSecretManager, this.clientToAMSecretManager); + this.containerTokenSecretManager, this.clientToAMSecretManager, + this.rmDTSecretManager); // Register event handler for NodesListManager this.nodesListManager = new NodesListManager(this.rmContext); @@ -239,7 +241,6 @@ public synchronized void init(Configuration conf) { // Register event handler for RMAppManagerEvents this.rmDispatcher.register(RMAppManagerEventType.class, this.rmAppManager); - this.rmDTSecretManager = createRMDelegationTokenSecretManager(); clientRM = createClientRMService(); addService(clientRM); diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestRMRestart.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestRMRestart.java index fded9fb..b543b03 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestRMRestart.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestRMRestart.java @@ -478,6 +478,13 @@ public void testTokenRestoredOnRMrestart() throws Exception { Assert.assertEquals(tokenSet, rm1.getRMContext() .getDelegationTokenRenewer().getDelegationTokens()); + try{ + rm2.getRMDTSecretManager().verifyToken(dtId1, token1.getPassword()); + rm2.getRMDTSecretManager().verifyToken(dtId2, token2.getPassword()); + } catch (Exception e) { + Assert.fail(); + } + // stop the RM rm1.stop(); rm2.stop(); diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/TestRMAppTransitions.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/TestRMAppTransitions.java index 60ea8fc..e71c1f1 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/TestRMAppTransitions.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/rmapp/TestRMAppTransitions.java @@ -146,7 +146,7 @@ public void setUp() throws Exception { containerAllocationExpirer, amLivelinessMonitor, amFinishingMonitor, null, new ApplicationTokenSecretManager(conf), new RMContainerTokenSecretManager(conf), - new ClientToAMTokenSecretManagerInRM()); + new ClientToAMTokenSecretManagerInRM(), null); rmDispatcher.register(RMAppAttemptEventType.class, new TestApplicationAttemptEventDispatcher(this.rmContext));