Add test cases specific to handling secret manager in a distributed setup

This commit is contained in:
krgoyal krgoyal 2023-03-03 18:08:31 +05:30
parent eb8856d843
commit 0e8f950c91
7 changed files with 192 additions and 171 deletions

View File

@ -237,7 +237,7 @@ extends AbstractDelegationTokenIdentifier>
// RM // RM
protected void removeStoredToken(TokenIdent ident) throws IOException { protected void removeStoredToken(TokenIdent ident) throws IOException {
return;
} }
// RM // RM
protected void updateStoredToken(TokenIdent ident, long renewDate) throws IOException { protected void updateStoredToken(TokenIdent ident, long renewDate) throws IOException {
@ -386,6 +386,15 @@ extends AbstractDelegationTokenIdentifier>
updateStoredToken(ident, tokenInfo.getRenewDate()); updateStoredToken(ident, tokenInfo.getRenewDate());
} }
protected void removeToken(TokenIdent ident) throws IOException {
DelegationTokenInformation info = currentTokens.remove(ident);
if (info == null) {
throw new InvalidToken("Token not found " + formatTokenId(ident));
}
removeTokenForOwnerStats(ident);
removeStoredToken(ident);
}
/** /**
* This method is intended to be used for recovering persisted delegation * This method is intended to be used for recovering persisted delegation
* tokens. Tokens that have an unknown <code>DelegationKey</code> are * tokens. Tokens that have an unknown <code>DelegationKey</code> are
@ -691,13 +700,8 @@ extends AbstractDelegationTokenIdentifier>
throw new AccessControlException(canceller throw new AccessControlException(canceller
+ " is not authorized to cancel the token " + formatTokenId(id)); + " is not authorized to cancel the token " + formatTokenId(id));
} }
DelegationTokenInformation info = currentTokens.remove(id);
if (info == null) {
throw new InvalidToken("Token not found " + formatTokenId(id));
}
METRICS.trackRemoveToken(() -> { METRICS.trackRemoveToken(() -> {
removeTokenForOwnerStats(id); removeToken(id);
removeStoredToken(id);
}); });
return id; return id;
} }

View File

@ -161,7 +161,7 @@ public abstract class SQLDelegationTokenSecretManager<TokenIdent
* null if it doesn't exist in the database. * null if it doesn't exist in the database.
*/ */
@Override @Override
protected DelegationTokenInformation getTokenInfo(TokenIdent ident) { protected DelegationTokenInformation getTokenInfo(TokenIdent ident) throws IOException {
// Look for token in local cache // Look for token in local cache
DelegationTokenInformation tokenInfo = super.getTokenInfo(ident); DelegationTokenInformation tokenInfo = super.getTokenInfo(ident);
@ -302,7 +302,7 @@ public abstract class SQLDelegationTokenSecretManager<TokenIdent
* if it doesn't exist in the database. * if it doesn't exist in the database.
*/ */
@Override @Override
protected DelegationKey getDelegationKey(int keyId) { protected DelegationKey getDelegationKey(int keyId) throws IOException {
// Look for delegation key in local cache // Look for delegation key in local cache
DelegationKey delegationKey = super.getDelegationKey(keyId); DelegationKey delegationKey = super.getDelegationKey(keyId);

View File

@ -138,10 +138,7 @@ public class MemoryFederationStateStore implements FederationStateStore {
@Override @Override
public void close() { public void close() {
membership = null; init(new Configuration());
applications = null;
reservations = null;
policies = null;
} }
@Override @Override
@ -464,13 +461,13 @@ public class MemoryFederationStateStore implements FederationStateStore {
RouterMasterKey masterKey = request.getRouterMasterKey(); RouterMasterKey masterKey = request.getRouterMasterKey();
DelegationKey delegationKey = getDelegationKeyByMasterKey(masterKey); DelegationKey delegationKey = getDelegationKeyByMasterKey(masterKey);
Set<DelegationKey> rmDTMasterKeyState = routerRMSecretManagerState.getMasterKeyState(); Map<Integer, DelegationKey> rmDTMasterKeyState = routerRMSecretManagerState.getMasterKeyState();
if (rmDTMasterKeyState.contains(delegationKey)) { if (rmDTMasterKeyState.containsKey(delegationKey.getKeyId())) {
FederationStateStoreUtils.logAndThrowStoreException(LOG, FederationStateStoreUtils.logAndThrowStoreException(LOG,
"Error storing info for RMDTMasterKey with keyID: %s.", delegationKey.getKeyId()); "Error storing info for RMDTMasterKey with keyID: %s.", delegationKey.getKeyId());
} }
routerRMSecretManagerState.getMasterKeyState().add(delegationKey); routerRMSecretManagerState.getMasterKeyState().put(delegationKey.getKeyId(), delegationKey);
LOG.info("Store Router-RMDT master key with key id: {}. Currently rmDTMasterKeyState size: {}", LOG.info("Store Router-RMDT master key with key id: {}. Currently rmDTMasterKeyState size: {}",
delegationKey.getKeyId(), rmDTMasterKeyState.size()); delegationKey.getKeyId(), rmDTMasterKeyState.size());
@ -485,8 +482,8 @@ public class MemoryFederationStateStore implements FederationStateStore {
DelegationKey delegationKey = getDelegationKeyByMasterKey(masterKey); DelegationKey delegationKey = getDelegationKeyByMasterKey(masterKey);
LOG.info("Remove Router-RMDT master key with key id: {}.", delegationKey.getKeyId()); LOG.info("Remove Router-RMDT master key with key id: {}.", delegationKey.getKeyId());
Set<DelegationKey> rmDTMasterKeyState = routerRMSecretManagerState.getMasterKeyState(); Map<Integer, DelegationKey> rmDTMasterKeyState = routerRMSecretManagerState.getMasterKeyState();
rmDTMasterKeyState.remove(delegationKey); rmDTMasterKeyState.remove(delegationKey.getKeyId());
return RouterMasterKeyResponse.newInstance(masterKey); return RouterMasterKeyResponse.newInstance(masterKey);
} }
@ -494,12 +491,10 @@ public class MemoryFederationStateStore implements FederationStateStore {
@Override @Override
public RouterMasterKeyResponse getMasterKeyByDelegationKey(RouterMasterKeyRequest request) public RouterMasterKeyResponse getMasterKeyByDelegationKey(RouterMasterKeyRequest request)
throws YarnException, IOException { throws YarnException, IOException {
// Restore the DelegationKey from the request
RouterMasterKey masterKey = request.getRouterMasterKey(); RouterMasterKey masterKey = request.getRouterMasterKey();
DelegationKey delegationKey = getDelegationKeyByMasterKey(masterKey); Map<Integer, DelegationKey> rmDTMasterKeyState = routerRMSecretManagerState.getMasterKeyState();
DelegationKey delegationKey = rmDTMasterKeyState.get(masterKey.getKeyId());
Set<DelegationKey> rmDTMasterKeyState = routerRMSecretManagerState.getMasterKeyState(); if (delegationKey == null) {
if (!rmDTMasterKeyState.contains(delegationKey)) {
throw new IOException("GetMasterKey with keyID: " + masterKey.getKeyId() + throw new IOException("GetMasterKey with keyID: " + masterKey.getKeyId() +
" does not exist."); " does not exist.");
} }

View File

@ -30,7 +30,7 @@ public class RouterRMDTSecretManagerState {
// DTIdentifier -> renewDate // DTIdentifier -> renewDate
private Map<Integer, RouterStoreToken> delegationTokenState = new HashMap<>(); private Map<Integer, RouterStoreToken> delegationTokenState = new HashMap<>();
private Set<DelegationKey> masterKeyState = new HashSet<>(); private Map<Integer, DelegationKey> masterKeyState = new HashMap<>();
private int dtSequenceNumber = 0; private int dtSequenceNumber = 0;
@ -38,7 +38,7 @@ public class RouterRMDTSecretManagerState {
return delegationTokenState; return delegationTokenState;
} }
public Set<DelegationKey> getMasterKeyState() { public Map<Integer, DelegationKey> getMasterKeyState() {
return masterKeyState; return masterKeyState;
} }

View File

@ -59,10 +59,10 @@ public class TestMemoryFederationStateStore extends FederationStateStoreBaseTest
memoryStateStore.getRouterRMSecretManagerState(); memoryStateStore.getRouterRMSecretManagerState();
assertNotNull(secretManagerState); assertNotNull(secretManagerState);
Set<DelegationKey> delegationKeys = secretManagerState.getMasterKeyState(); Map<Integer, DelegationKey> delegationKeys = secretManagerState.getMasterKeyState();
assertNotNull(delegationKeys); assertNotNull(delegationKeys);
assertTrue(delegationKeys.contains(delegationKey)); assertTrue(delegationKeys.containsKey(delegationKey.getKeyId()));
RouterMasterKey resultRouterMasterKey = RouterMasterKey.newInstance(delegationKey.getKeyId(), RouterMasterKey resultRouterMasterKey = RouterMasterKey.newInstance(delegationKey.getKeyId(),
ByteBuffer.wrap(delegationKey.getEncodedKey()), delegationKey.getExpiryDate()); ByteBuffer.wrap(delegationKey.getEncodedKey()), delegationKey.getExpiryDate());

View File

@ -145,7 +145,7 @@ public class RouterDelegationTokenSecretManager
} }
/** /**
* no-op as expiry of stored tokens is upto the state store in a stateless secret manager * no-op as removal of tokens is handled in removeToken()
*/ */
@Override @Override
public void removeStoredToken(RMDelegationTokenIdentifier identifier) { public void removeStoredToken(RMDelegationTokenIdentifier identifier) {
@ -188,7 +188,6 @@ public class RouterDelegationTokenSecretManager
@Override @Override
protected void storeToken(RMDelegationTokenIdentifier rmDelegationTokenIdentifier, protected void storeToken(RMDelegationTokenIdentifier rmDelegationTokenIdentifier,
DelegationTokenInformation tokenInfo) throws IOException { DelegationTokenInformation tokenInfo) throws IOException {
this.addTokenForOwnerStats(rmDelegationTokenIdentifier);
try { try {
storeNewToken(rmDelegationTokenIdentifier, tokenInfo); storeNewToken(rmDelegationTokenIdentifier, tokenInfo);
} catch (YarnException e) { } catch (YarnException e) {
@ -208,6 +207,16 @@ public class RouterDelegationTokenSecretManager
} }
} }
@Override
protected void removeToken(RMDelegationTokenIdentifier identifier) throws IOException {
try {
federationFacade.removeStoredToken(identifier);
} catch (YarnException e) {
e.printStackTrace();
throw new IOException(e); // Wrap YarnException as an IOException to adhere to removeToken contract
}
}
@Override @Override
protected DelegationTokenInformation getTokenInfo(RMDelegationTokenIdentifier ident) throws IOException { protected DelegationTokenInformation getTokenInfo(RMDelegationTokenIdentifier ident) throws IOException {
try { try {

View File

@ -18,52 +18,55 @@
package org.apache.hadoop.yarn.server.router.security; package org.apache.hadoop.yarn.server.router.security;
import org.apache.hadoop.io.Text; import org.apache.hadoop.io.Text;
import org.apache.hadoop.security.token.SecretManager;
import org.apache.hadoop.security.token.Token; import org.apache.hadoop.security.token.Token;
import org.apache.hadoop.security.token.delegation.AbstractDelegationTokenSecretManager;
import org.apache.hadoop.security.token.delegation.DelegationKey;
import org.apache.hadoop.test.LambdaTestUtils;
import org.apache.hadoop.util.Time;
import org.apache.hadoop.yarn.security.client.RMDelegationTokenIdentifier; import org.apache.hadoop.yarn.security.client.RMDelegationTokenIdentifier;
import org.apache.hadoop.yarn.server.router.clientrm.RouterClientRMService; import org.apache.hadoop.yarn.server.federation.utils.FederationStateStoreFacade;
import org.junit.After;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.slf4j.Logger; import org.mockito.Mockito;
import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertArrayEquals;
public class TestRouterDelegationTokenSecretManager extends AbstractSecureRouterTest { public class TestRouterDelegationTokenSecretManager extends AbstractSecureRouterTest {
private static final Logger LOG = private volatile RouterDelegationTokenSecretManager secretManager_1;
LoggerFactory.getLogger(TestRouterDelegationTokenSecretManager.class); private volatile RouterDelegationTokenSecretManager secretManager_2;
private final Text owner = new Text("owner");
private RouterDelegationTokenSecretManager secretManager_1; private final Text renewer = new Text("renewer");
private RouterDelegationTokenSecretManager secretManager_2; private final Text realUser = new Text("realUser");
private final Text owner = new Text("hadoop"); private final int keyUpdateInterval = 1000;
private final Text renewer = new Text("yarn"); private final int tokenRenewInterval = 2000;
private final Text realUser = new Text("router"); private final int tokenMaxLifeTime = 10000;
@Before @Before
public void setup() { public void setup() {
// Setup multiple secret managers to validate stateless secret managers. // Setup multiple secret managers to validate stateless secret managers.
// They are using same instance of FederationStateStoreFacade thus the in memory state store is shared // They are using same instance of FederationStateStoreFacade thus the in memory state store is shared
secretManager_1 = new RouterDelegationTokenSecretManager( secretManager_1 = Mockito.spy(new RouterDelegationTokenSecretManager(
1000, 10000, 1000, 100 keyUpdateInterval, tokenMaxLifeTime, tokenRenewInterval, 100)
); );
secretManager_2 = new RouterDelegationTokenSecretManager( secretManager_2 = Mockito.spy(new RouterDelegationTokenSecretManager(
1000, 10000, 1000, 100 keyUpdateInterval, tokenMaxLifeTime, tokenRenewInterval, 100)
); );
} }
@After
public void cleanup() throws Exception {
secretManager_1.stopThreads();
secretManager_2.stopThreads();
secretManager_1 = null;
secretManager_2 = null;
FederationStateStoreFacade.getInstance().getStateStore().close();
}
@Test @Test
public void testNewTokenVerification() throws IOException { public void testNewTokenIsVerifiedAcrossManagers() throws IOException {
secretManager_1.startThreads(); secretManager_1.startThreads();
RMDelegationTokenIdentifier tokenIdentifier = new RMDelegationTokenIdentifier(owner, renewer, realUser); RMDelegationTokenIdentifier tokenIdentifier = new RMDelegationTokenIdentifier(owner, renewer, realUser);
@ -77,162 +80,172 @@ public class TestRouterDelegationTokenSecretManager extends AbstractSecureRouter
secretManager_2.startThreads(); secretManager_2.startThreads();
RMDelegationTokenIdentifier tokenIdentifier_3 = secretManager_2.decodeTokenIdentifier(token2); RMDelegationTokenIdentifier tokenIdentifier_3 = secretManager_2.decodeTokenIdentifier(token2);
Assertions.assertDoesNotThrow(() -> secretManager_2.verifyToken(tokenIdentifier_3, token.getPassword())); Assertions.assertDoesNotThrow(() -> secretManager_2.verifyToken(tokenIdentifier_3, token2.getPassword()));
} }
@Test @Test
public void testRouterStoreNewMasterKey() throws Exception { public void testMasterKeyIsRolled() throws IOException, InterruptedException {
LOG.info("Test RouterDelegationTokenSecretManager: StoreNewMasterKey.");
// Start the Router in Secure Mode secretManager_1.startThreads();
startSecureRouter(); RMDelegationTokenIdentifier tokenIdentifier1 = new RMDelegationTokenIdentifier(owner, renewer, realUser);
new Token<>(tokenIdentifier1, secretManager_1);
// Store NewMasterKey RMDelegationTokenIdentifier tokenIdentifier2 = new RMDelegationTokenIdentifier(owner, renewer, realUser);
RouterClientRMService routerClientRMService = this.getRouter().getClientRMProxyService(); new Token<>(tokenIdentifier2, secretManager_1);
RouterDelegationTokenSecretManager secretManager =
routerClientRMService.getRouterDTSecretManager();
DelegationKey storeKey = new DelegationKey(1234, 4321, "keyBytes".getBytes());
secretManager.storeNewMasterKey(storeKey);
// Get DelegationKey // Check multiple tokens have same master key
DelegationKey responseKey = secretManager.getDelegationKey(1234); Assert.assertEquals(tokenIdentifier1.getMasterKeyId(), tokenIdentifier2.getMasterKeyId());
// Sleep until master key is updated
Thread.sleep(keyUpdateInterval + 100);
assertNotNull(responseKey); RMDelegationTokenIdentifier tokenIdentifier3 = new RMDelegationTokenIdentifier(owner, renewer, realUser);
assertEquals(storeKey.getExpiryDate(), responseKey.getExpiryDate()); new Token<>(tokenIdentifier3, secretManager_1);
assertEquals(storeKey.getKeyId(), responseKey.getKeyId()); // Check master key is updated
assertArrayEquals(storeKey.getEncodedKey(), responseKey.getEncodedKey()); Assert.assertNotEquals(tokenIdentifier1.getMasterKeyId(), tokenIdentifier3.getMasterKeyId());
assertEquals(storeKey, responseKey);
stopSecureRouter();
} }
@Test @Test
public void testRouterRemoveStoredMasterKey() throws Exception { public void testNewTokenIsCancelledAcrossManagers() throws IOException {
LOG.info("Test RouterDelegationTokenSecretManager: RemoveStoredMasterKey.");
// Start the Router in Secure Mode secretManager_1.startThreads();
startSecureRouter(); RMDelegationTokenIdentifier tokenIdentifier = new RMDelegationTokenIdentifier(owner, renewer, realUser);
Token<RMDelegationTokenIdentifier> token = new Token<>(tokenIdentifier, secretManager_1);
// Store NewMasterKey Token<RMDelegationTokenIdentifier> token2 = new Token<>();
RouterClientRMService routerClientRMService = this.getRouter().getClientRMProxyService(); token2.decodeFromUrlString(token.encodeToUrlString());
RouterDelegationTokenSecretManager secretManager =
routerClientRMService.getRouterDTSecretManager();
DelegationKey storeKey = new DelegationKey(1234, 4321, "keyBytes".getBytes());
secretManager.storeNewMasterKey(storeKey);
// Remove DelegationKey secretManager_2.startThreads();
secretManager.removeStoredMasterKey(storeKey); secretManager_2.cancelToken(token2, owner.toString());
// Get DelegationKey RMDelegationTokenIdentifier tokenIdentifier_2 = secretManager_1.decodeTokenIdentifier(token2);
LambdaTestUtils.intercept(IOException.class, Assertions.assertThrows(SecretManager.InvalidToken.class,
"GetMasterKey with keyID: " + storeKey.getKeyId() + " does not exist.", () -> secretManager_1.verifyToken(tokenIdentifier_2, token2.getPassword())
() -> secretManager.getDelegationKey(1234)); );
stopSecureRouter();
} }
@Test @Test
public void testRouterStoreNewToken() throws Exception { public void testNewTokenIsRenewedAcrossManagers() throws IOException, InterruptedException {
LOG.info("Test RouterDelegationTokenSecretManager: StoreNewToken.");
// Start the Router in Secure Mode secretManager_1.startThreads();
startSecureRouter(); RMDelegationTokenIdentifier tokenIdentifier = new RMDelegationTokenIdentifier(owner, renewer, realUser);
Token<RMDelegationTokenIdentifier> token = new Token<>(tokenIdentifier, secretManager_1);
// Store new rm-token Token<RMDelegationTokenIdentifier> token2 = new Token<>();
RouterClientRMService routerClientRMService = this.getRouter().getClientRMProxyService(); token2.decodeFromUrlString(token.encodeToUrlString());
RouterDelegationTokenSecretManager secretManager =
routerClientRMService.getRouterDTSecretManager();
RMDelegationTokenIdentifier dtId1 = new RMDelegationTokenIdentifier(
new Text("owner1"), new Text("renewer1"), new Text("realuser1"));
int sequenceNumber = 1;
dtId1.setSequenceNumber(sequenceNumber);
long renewDate1 = Time.now();
secretManager.storeNewToken(dtId1, renewDate1);
// query rm-token Thread.sleep(tokenRenewInterval / 2 + 100);
RMDelegationTokenIdentifier dtId2 = new RMDelegationTokenIdentifier( secretManager_2.startThreads();
new Text("owner1"), new Text("renewer1"), new Text("realuser1")); secretManager_2.renewToken(token2, renewer.toString());
dtId2.setSequenceNumber(sequenceNumber);
AbstractDelegationTokenSecretManager.DelegationTokenInformation dtId3 = secretManager.getTokenInfo(dtId2);
Assert.assertEquals(renewDate1, dtId3.getRenewDate());
// query rm-token2 not exists Thread.sleep(tokenRenewInterval / 2 + 100);
sequenceNumber++; RMDelegationTokenIdentifier tokenIdentifier_2 = secretManager_1.decodeTokenIdentifier(token2);
dtId2.setSequenceNumber(sequenceNumber); Assertions.assertDoesNotThrow(() -> secretManager_1.verifyToken(tokenIdentifier_2, token2.getPassword()));
LambdaTestUtils.intercept(IOException.class,
"RMDelegationToken: " + dtId2 + " does not exist.",
() -> secretManager.getTokenInfo(dtId2));
stopSecureRouter();
} }
@Test @Test
public void testRouterUpdateNewToken() throws Exception { public void testTokenOperationsOnMasterKeyRollover() throws IOException, InterruptedException {
LOG.info("Test RouterDelegationTokenSecretManager: UpdateNewToken.");
// Start the Router in Secure Mode secretManager_1.startThreads();
startSecureRouter(); RMDelegationTokenIdentifier tokenIdentifier1 = new RMDelegationTokenIdentifier(owner, renewer, realUser);
Token<RMDelegationTokenIdentifier> token1 = new Token<>(tokenIdentifier1, secretManager_1);
// Store new rm-token // Sleep until master key is updated
RouterClientRMService routerClientRMService = this.getRouter().getClientRMProxyService(); Thread.sleep(keyUpdateInterval + 100);
RouterDelegationTokenSecretManager secretManager =
routerClientRMService.getRouterDTSecretManager();
RMDelegationTokenIdentifier dtId1 = new RMDelegationTokenIdentifier(
new Text("owner1"), new Text("renewer1"), new Text("realuser1"));
int sequenceNumber = 1;
dtId1.setSequenceNumber(sequenceNumber);
Long renewDate1 = Time.now();
secretManager.storeNewToken(dtId1, renewDate1);
sequenceNumber++; RMDelegationTokenIdentifier tokenIdentifier2 = new RMDelegationTokenIdentifier(owner, renewer, realUser);
dtId1.setSequenceNumber(sequenceNumber); new Token<>(tokenIdentifier2, secretManager_1);
secretManager.updateStoredToken(dtId1, renewDate1); // Check master key is updated
Assert.assertNotEquals(tokenIdentifier1.getMasterKeyId(), tokenIdentifier2.getMasterKeyId());
// query rm-token // Verify token with old master key is still considered valid
RMDelegationTokenIdentifier dtId2 = new RMDelegationTokenIdentifier( Assertions.assertDoesNotThrow(() -> secretManager_1.verifyToken(tokenIdentifier1, token1.getPassword()));
new Text("owner1"), new Text("renewer1"), new Text("realuser1")); // Verify token with old master key can be renewed
dtId2.setSequenceNumber(sequenceNumber); Assertions.assertDoesNotThrow(() -> secretManager_1.renewToken(token1, renewer.toString()));
// RMDelegationTokenIdentifier dtId3 = secretManager.getTokenInfo(dtId2); // Verify token with old master key can be cancelled
// assertNotNull(dtId3); Assertions.assertDoesNotThrow(() -> secretManager_1.cancelToken(token1, owner.toString()));
// assertEquals(dtId1.getKind(), dtId3.getKind()); // Verify token with old master key is now cancelled
// assertEquals(dtId1.getOwner(), dtId3.getOwner()); Assert.assertThrows(SecretManager.InvalidToken.class,
// assertEquals(dtId1.getRealUser(), dtId3.getRealUser()); () -> secretManager_1.verifyToken(tokenIdentifier1, token1.getPassword()));
// assertEquals(dtId1.getRenewer(), dtId3.getRenewer());
// assertEquals(dtId1.getIssueDate(), dtId3.getIssueDate());
// assertEquals(dtId1.getMasterKeyId(), dtId3.getMasterKeyId());
// assertEquals(dtId1.getSequenceNumber(), dtId3.getSequenceNumber());
// assertEquals(sequenceNumber, dtId3.getSequenceNumber());
// assertEquals(dtId1, dtId3);
stopSecureRouter();
} }
@Test @Test
public void testRouterRemoveToken() throws Exception { public void testMasterKeyIsNotRolledOver() throws IOException, InterruptedException {
LOG.info("Test RouterDelegationTokenSecretManager: RouterRemoveToken.");
// Start the Router in Secure Mode secretManager_1.startThreads();
startSecureRouter(); RMDelegationTokenIdentifier tokenIdentifier1 = new RMDelegationTokenIdentifier(owner, renewer, realUser);
new Token<>(tokenIdentifier1, secretManager_1);
// Store new rm-token Mockito.doThrow(new IOException("failure")).when(secretManager_1).storeNewMasterKey(Mockito.any());
RouterClientRMService routerClientRMService = this.getRouter().getClientRMProxyService();
RouterDelegationTokenSecretManager secretManager =
routerClientRMService.getRouterDTSecretManager();
RMDelegationTokenIdentifier dtId1 = new RMDelegationTokenIdentifier(
new Text("owner1"), new Text("renewer1"), new Text("realuser1"));
int sequenceNumber = 1;
dtId1.setSequenceNumber(sequenceNumber);
Long renewDate1 = Time.now();
secretManager.storeNewToken(dtId1, renewDate1);
// Remove rm-token // Sleep until master key is updated
secretManager.removeStoredToken(dtId1); Thread.sleep(keyUpdateInterval + 100);
// query rm-token RMDelegationTokenIdentifier tokenIdentifier2 = new RMDelegationTokenIdentifier(owner, renewer, realUser);
LambdaTestUtils.intercept(IOException.class, new Token<>(tokenIdentifier2, secretManager_1);
"RMDelegationToken: " + dtId1 + " does not exist.", // Verify master key is not updated
() -> secretManager.getTokenInfo(dtId1)); Assert.assertEquals(tokenIdentifier1.getMasterKeyId(), tokenIdentifier2.getMasterKeyId());
stopSecureRouter();
} }
@Test
public void testNewTokenFailsOnDBFailure() throws IOException {
secretManager_1.startThreads();
RMDelegationTokenIdentifier tokenIdentifier1 = new RMDelegationTokenIdentifier(owner, renewer, realUser);
Mockito.doThrow(new IOException("failure")).when(secretManager_1).storeToken(Mockito.any(), Mockito.any());
Assert.assertThrows(RuntimeException.class, () -> new Token<>(tokenIdentifier1, secretManager_1));
}
@Test
public void testTokenIsNotRenewedOnDBFailure() throws IOException, InterruptedException {
secretManager_1.startThreads();
RMDelegationTokenIdentifier tokenIdentifier1 = new RMDelegationTokenIdentifier(owner, renewer, realUser);
Token<RMDelegationTokenIdentifier> token = new Token<>(tokenIdentifier1, secretManager_1);
Mockito.doThrow(new IOException("failure")).when(secretManager_1).updateToken(Mockito.any(), Mockito.any());
Thread.sleep(tokenRenewInterval / 2 + 100);
Assert.assertThrows(IOException.class, () -> secretManager_1.renewToken(token, renewer.toString()));
// validate that token is currently valid
Assertions.assertDoesNotThrow(() -> secretManager_1.verifyToken(tokenIdentifier1, token.getPassword()));
Thread.sleep(tokenRenewInterval / 2 + 100);
// token is no longer valid because token renewal had failed
Assertions.assertThrows(SecretManager.InvalidToken.class,
() -> secretManager_1.verifyToken(tokenIdentifier1, token.getPassword())
);
}
@Ignore
public void testNewTokenFailureIfMasterKeyNotRolledOverAtAll() throws IOException, InterruptedException {
secretManager_1.startThreads();
// Token generation succeeds initially because master key generated on initialisation was saved
RMDelegationTokenIdentifier tokenIdentifier1 = new RMDelegationTokenIdentifier(owner, renewer, realUser);
new Token<>(tokenIdentifier1, secretManager_1);
Mockito.doThrow(new IOException("failure")).when(secretManager_1).storeNewMasterKey(Mockito.any());
// Sleep until current master key expires. New master key isn't generated because rollovers are failing
Thread.sleep(tokenMaxLifeTime + keyUpdateInterval + 100);
RMDelegationTokenIdentifier tokenIdentifier2 = new RMDelegationTokenIdentifier(owner, renewer, realUser);
// New token generation fails because current master key is expired
Assert.assertThrows(RuntimeException.class, () -> new Token<>(tokenIdentifier2, secretManager_1));
}
@Test
public void testMasterKeyCreationFailureOnStartup() throws IOException {
Mockito.doThrow(new IOException("failure")).when(secretManager_1).storeNewMasterKey(Mockito.any());
Assert.assertThrows(IOException.class, () -> secretManager_1.startThreads());
RMDelegationTokenIdentifier tokenIdentifier = new RMDelegationTokenIdentifier(owner, renewer, realUser);
// New token generation fails because master key is not yet set
Assert.assertThrows(NullPointerException.class, () -> new Token<>(tokenIdentifier, secretManager_1));
}
} }