DFSConfigKeys.DFS_BLOCK_ACCESS_TOKEN_PROTOBUF_ENABLE, DFSConfigKeys.DFS_BLOCK_ACCESS_TOKEN_PROTOBUF_ENABLE_DEFAULT); this.blockTokenSecretManager = new BlockTokenSecretManager( updateInterval, tokenLifetime, blockpoolID, encryptionAlgorithm, enableProtobuf); this.blockTokenSecretManager.addKeys(keys);
/** * Check if access should be allowed. userID is not checked if null. This * method doesn't check if token password is correct. It should be used only * when token password has already been verified (e.g., in the RPC layer). * * Some places need to check the access using StorageTypes and for other * places the StorageTypes is not relevant. */ public void checkAccess(BlockTokenIdentifier id, String userId, ExtendedBlock block, BlockTokenIdentifier.AccessMode mode, StorageType[] storageTypes, String[] storageIds) throws InvalidToken { checkAccess(id, userId, block, mode); if (ArrayUtils.isNotEmpty(storageTypes)) { checkAccess(id.getStorageTypes(), storageTypes, "StorageTypes"); } if (ArrayUtils.isNotEmpty(storageIds)) { checkAccess(id.getStorageIds(), storageIds, "StorageIDs"); } }
/** Generate an block token for current user */ public Token<BlockTokenIdentifier> generateToken(ExtendedBlock block, EnumSet<BlockTokenIdentifier.AccessMode> modes, StorageType[] storageTypes, String[] storageIds) throws IOException { UserGroupInformation ugi = UserGroupInformation.getCurrentUser(); String userID = (ugi == null ? null : ugi.getShortUserName()); return generateToken(userID, block, modes, storageTypes, storageIds); }
/** * Constructor for masters. * * @param keyUpdateInterval how often a new key will be generated * @param tokenLifetime how long an individual token is valid * @param nnIndex namenode index of the namenode for which we are creating the manager * @param blockPoolId block pool ID * @param encryptionAlgorithm encryption algorithm to use * @param numNNs number of namenodes possible * @param useProto should we use new protobuf style tokens */ public BlockTokenSecretManager(long keyUpdateInterval, long tokenLifetime, int nnIndex, int numNNs, String blockPoolId, String encryptionAlgorithm, boolean useProto) { this(true, keyUpdateInterval, tokenLifetime, blockPoolId, encryptionAlgorithm, nnIndex, numNNs, useProto); Preconditions.checkArgument(nnIndex >= 0); Preconditions.checkArgument(numNNs > 0); setSerialNo(new SecureRandom().nextInt()); generateKeys(); }
/** Initialize block keys */ private synchronized void generateKeys() { if (!isMaster) { return; } /* * Need to set estimated expiry dates for currentKey and nextKey so that if * NN crashes, DN can still expire those keys. NN will stop using the newly * generated currentKey after the first keyUpdateInterval, however it may * still be used by DN and Balancer to generate new tokens before they get a * chance to sync their keys with NN. Since we require keyUpdInterval to be * long enough so that all live DN's and Balancer will sync their keys with * NN at least once during the period, the estimated expiry date for * currentKey is set to now() + 2 * keyUpdateInterval + tokenLifetime. * Similarly, the estimated expiry date for nextKey is one keyUpdateInterval * more. */ setSerialNo(serialNo + 1); currentKey = new BlockKey(serialNo, timer.now() + 2 * keyUpdateInterval + tokenLifetime, generateSecret()); setSerialNo(serialNo + 1); nextKey = new BlockKey(serialNo, timer.now() + 3 * keyUpdateInterval + tokenLifetime, generateSecret()); allKeys.put(currentKey.getKeyId(), currentKey); allKeys.put(nextKey.getKeyId(), nextKey); }
/** Check if access should be allowed. userID is not checked if null */ public void checkAccess(Token<BlockTokenIdentifier> token, String userId, ExtendedBlock block, BlockTokenIdentifier.AccessMode mode, StorageType[] storageTypes, String[] storageIds) throws InvalidToken { BlockTokenIdentifier id = new BlockTokenIdentifier(); try { id.readFields(new DataInputStream(new ByteArrayInputStream(token .getIdentifier()))); } catch (IOException e) { throw new InvalidToken( "Unable to de-serialize block token identifier for user=" + userId + ", block=" + block + ", access mode=" + mode); } checkAccess(id, userId, block, mode, storageTypes, storageIds); if (!Arrays.equals(retrievePassword(id), token.getPassword())) { throw new InvalidToken("Block token with " + id + " doesn't have the correct token password"); } }
/** test block key and token handling */ @Test public void testBlockTokenSecretManager() throws Exception { BlockTokenSecretManager masterHandler = new BlockTokenSecretManager(true, blockKeyUpdateInterval, blockTokenLifetime); BlockTokenSecretManager slaveHandler = new BlockTokenSecretManager(false, blockKeyUpdateInterval, blockTokenLifetime); ExportedBlockKeys keys = masterHandler.exportKeys(); slaveHandler.setKeys(keys); tokenGenerationAndVerification(masterHandler, slaveHandler); // key updating masterHandler.updateKeys(); tokenGenerationAndVerification(masterHandler, slaveHandler); keys = masterHandler.exportKeys(); slaveHandler.setKeys(keys); tokenGenerationAndVerification(masterHandler, slaveHandler); }
/** test block key and token handling */ @Test public void testBlockTokenSecretManager() throws Exception { BlockTokenSecretManager masterHandler = new BlockTokenSecretManager( blockKeyUpdateInterval, blockTokenLifetime, 0, "fake-pool", null); BlockTokenSecretManager slaveHandler = new BlockTokenSecretManager( blockKeyUpdateInterval, blockTokenLifetime, "fake-pool", null); ExportedBlockKeys keys = masterHandler.exportKeys(); slaveHandler.addKeys(keys); tokenGenerationAndVerification(masterHandler, slaveHandler); // key updating masterHandler.updateKeys(); tokenGenerationAndVerification(masterHandler, slaveHandler); keys = masterHandler.exportKeys(); slaveHandler.addKeys(keys); tokenGenerationAndVerification(masterHandler, slaveHandler); }
/** * Test {@link BlockPoolTokenSecretManager} */ @Test public void testBlockPoolTokenSecretManager() throws Exception { BlockPoolTokenSecretManager bpMgr = new BlockPoolTokenSecretManager(); // Test BlockPoolSecretManager with upto 10 block pools for (int i = 0; i < 10; i++) { String bpid = Integer.toString(i); BlockTokenSecretManager masterHandler = new BlockTokenSecretManager( blockKeyUpdateInterval, blockTokenLifetime, 0, "fake-pool", null); BlockTokenSecretManager slaveHandler = new BlockTokenSecretManager( blockKeyUpdateInterval, blockTokenLifetime, "fake-pool", null); bpMgr.addBlockPool(bpid, slaveHandler); ExportedBlockKeys keys = masterHandler.exportKeys(); bpMgr.addKeys(bpid, keys); tokenGenerationAndVerification(masterHandler, bpMgr.get(bpid)); // Test key updating masterHandler.updateKeys(); tokenGenerationAndVerification(masterHandler, bpMgr.get(bpid)); keys = masterHandler.exportKeys(); bpMgr.addKeys(bpid, keys); tokenGenerationAndVerification(masterHandler, bpMgr.get(bpid)); } }
/** * Update block keys, only to be used in master mode */ synchronized boolean updateKeys() throws IOException { if (!isMaster) { return false; } LOG.info("Updating block keys"); removeExpiredKeys(); // set final expiry date of retiring currentKey allKeys.put(currentKey.getKeyId(), new BlockKey(currentKey.getKeyId(), timer.now() + keyUpdateInterval + tokenLifetime, currentKey.getKey())); // update the estimated expiry date of new currentKey currentKey = new BlockKey(nextKey.getKeyId(), timer.now() + 2 * keyUpdateInterval + tokenLifetime, nextKey.getKey()); allKeys.put(currentKey.getKeyId(), currentKey); // generate a new nextKey setSerialNo(serialNo + 1); nextKey = new BlockKey(serialNo, timer.now() + 3 * keyUpdateInterval + tokenLifetime, generateSecret()); allKeys.put(nextKey.getKeyId(), nextKey); return true; }
@Test public void testBlockTokenRpc() throws Exception { BlockTokenSecretManager sm = new BlockTokenSecretManager(true, blockKeyUpdateInterval, blockTokenLifetime); Token<BlockTokenIdentifier> token = sm.generateToken(block3, EnumSet.allOf(BlockTokenSecretManager.AccessMode.class)); final Server server = createMockDatanode(sm, token); server.start(); final InetSocketAddress addr = NetUtils.getConnectAddress(server); final UserGroupInformation ticket = UserGroupInformation .createRemoteUser(block3.toString()); ticket.addToken(token); ClientDatanodeProtocol proxy = null; try { proxy = (ClientDatanodeProtocol)RPC.getProxy( ClientDatanodeProtocol.class, ClientDatanodeProtocol.versionID, addr, ticket, conf, NetUtils.getDefaultSocketFactory(conf)); assertEquals(block3.getBlockId(), proxy.getReplicaVisibleLength(block3)); } finally { server.stop(); if (proxy != null) { RPC.stopProxy(proxy); } } }
return new BlockTokenSecretManager(updateMin * 60 * 1000L, lifetimeMin * 60 * 1000L, nnIndex, nnIds.size(), null, encryptionAlgorithm, shouldWriteProtobufToken); } else { return new BlockTokenSecretManager(updateMin*60*1000L, lifetimeMin*60*1000L, 0, 1, null, encryptionAlgorithm, shouldWriteProtobufToken);
private static void lowerKeyUpdateIntervalAndClearKeys(FSNamesystem namesystem) { BlockTokenSecretManager btsm = namesystem.getBlockManager() .getBlockTokenSecretManager(); btsm.setKeyUpdateIntervalForTesting(2 * 1000); btsm.setTokenLifetime(2 * 1000); btsm.clearAllKeysForTesting(); }
/** @return current access keys. */ public ExportedBlockKeys getBlockKeys() { return isBlockTokenEnabled()? blockTokenSecretManager.exportKeys() : ExportedBlockKeys.DUMMY_KEYS; }
/** * Update block keys if update time > update interval. * @return true if the keys are updated. */ public synchronized boolean updateKeys(final long updateTime) throws IOException { if (updateTime > keyUpdateInterval) { return updateKeys(); } return false; }
final String blockPoolId = "bp-foo"; FakeTimer fakeTimer = new FakeTimer(); BlockTokenSecretManager btsm = new BlockTokenSecretManager( keyUpdateInterval, tokenLifeTime, 0, blockPoolId, null); Whitebox.setInternalState(btsm, "timer", fakeTimer); when(namenode.getBlockKeys()).thenReturn(btsm.exportKeys());
private BlockTokenIdentifier generateTokenId(BlockTokenSecretManager sm, Block block, EnumSet<BlockTokenSecretManager.AccessMode> accessModes) throws IOException { Token<BlockTokenIdentifier> token = sm.generateToken(block, accessModes); BlockTokenIdentifier id = sm.createIdentifier(); id.readFields(new DataInputStream(new ByteArrayInputStream(token .getIdentifier()))); return id; }
@Override public byte[] createPassword(BlockTokenIdentifier identifier) { return get(identifier.getBlockPoolId()).createPassword(identifier); }
/** * See {@link BlockTokenSecretManager#addKeys(ExportedBlockKeys)} */ public void addKeys(String bpid, ExportedBlockKeys exportedKeys) throws IOException { get(bpid).addKeys(exportedKeys); }
public DataEncryptionKey generateDataEncryptionKey() { if (isBlockTokenEnabled() && encryptDataTransfer) { return blockTokenSecretManager.generateDataEncryptionKey(); } else { return null; } }