/** * Synchronize master key updates / sequence generation for multiple nodes. * NOTE: {@link AbstractDelegationTokenSecretManager} keeps currentKey private, so we need * to utilize this "hook" to manipulate the key through the object reference. * This .20S workaround should cease to exist when Hadoop supports token store. */ @Override protected void logUpdateMasterKey(DelegationKey key) throws IOException { int keySeq = this.tokenStore.addMasterKey(encodeWritable(key)); // update key with assigned identifier DelegationKey keyWithSeq = new DelegationKey(keySeq, key.getExpiryDate(), key.getKey()); String keyStr = encodeWritable(keyWithSeq); this.tokenStore.updateMasterKey(keySeq, keyStr); decodeWritable(key, keyStr); LOGGER.info("New master key with key id={}", key.getKeyId()); super.logUpdateMasterKey(key); }
private DelegationKey getKeyFromZK(int keyId) throws IOException { String nodePath = getNodePath(ZK_DTSM_MASTER_KEY_ROOT, DELEGATION_KEY_PREFIX + keyId); try { byte[] data = zkClient.getData().forPath(nodePath); if ((data == null) || (data.length == 0)) { return null; } ByteArrayInputStream bin = new ByteArrayInputStream(data); DataInputStream din = new DataInputStream(bin); DelegationKey key = new DelegationKey(); key.readFields(din); return key; } catch (KeeperException.NoNodeException e) { LOG.error("No node in path [" + nodePath + "]"); } catch (Exception ex) { throw new IOException(ex); } return null; }
String nodeCreatePath = getNodePath(ZK_DTSM_MASTER_KEY_ROOT, DELEGATION_KEY_PREFIX + key.getKeyId()); ByteArrayOutputStream os = new ByteArrayOutputStream(); DataOutputStream fsOut = new DataOutputStream(os); if (LOG.isDebugEnabled()) { LOG.debug("Storing ZKDTSMDelegationKey_" + key.getKeyId()); key.write(fsOut); try { if (zkClient.checkExists().forPath(nodeCreatePath) != null) {
private void processKeyAddOrUpdate(byte[] data) throws IOException { ByteArrayInputStream bin = new ByteArrayInputStream(data); DataInputStream din = new DataInputStream(bin); DelegationKey key = new DelegationKey(); key.readFields(din); synchronized (this) { allKeys.put(key.getKeyId(), key); } }
private synchronized void removeExpiredKeys() { long now = Time.now(); for (Iterator<Map.Entry<Integer, DelegationKey>> it = allKeys.entrySet() .iterator(); it.hasNext();) { Map.Entry<Integer, DelegationKey> e = it.next(); if (e.getValue().getExpiryDate() < now) { it.remove(); // ensure the tokens generated by this current key can be recovered // with this current key after this current key is rolled if(!e.getValue().equals(currentKey)) removeStoredMasterKey(e.getValue()); } } }
private void loadRMDelegationKeyState(RMState rmState) throws Exception { List<String> childNodes = getChildren(dtMasterKeysRootPath); for (String childNodeName : childNodes) { String childNodePath = getNodePath(dtMasterKeysRootPath, childNodeName); byte[] childData = getData(childNodePath); if (childData == null) { LOG.warn("Content of " + childNodePath + " is broken."); continue; } ByteArrayInputStream is = new ByteArrayInputStream(childData); try (DataInputStream fsIn = new DataInputStream(is)) { if (childNodeName.startsWith(DELEGATION_KEY_PREFIX)) { DelegationKey key = new DelegationKey(); key.readFields(fsIn); rmState.rmSecretManagerState.masterKeyState.add(key); if (LOG.isDebugEnabled()) { LOG.debug("Loaded delegation key: keyId=" + key.getKeyId() + ", expirationDate=" + key.getExpiryDate()); } } } } }
public static void delegationKeyToXml(ContentHandler contentHandler, DelegationKey key) throws SAXException { contentHandler.startElement( "", "", "DELEGATION_KEY", new AttributesImpl()); XMLUtils.addSaxString(contentHandler, "KEY_ID", Integer.toString(key.getKeyId())); XMLUtils.addSaxString(contentHandler, "EXPIRY_DATE", Long.toString(key.getExpiryDate())); if (key.getEncodedKey() != null) { XMLUtils.addSaxString(contentHandler, "KEY", Hex.encodeHexString(key.getEncodedKey())); } contentHandler.endElement("", "", "DELEGATION_KEY"); }
@Override protected synchronized byte[] createPassword(TokenIdent identifier) { int sequenceNum; long now = Time.now(); sequenceNum = incrementDelegationTokenSeqNum(); identifier.setIssueDate(now); identifier.setMaxDate(now + tokenMaxLifetime); identifier.setMasterKeyId(currentKey.getKeyId()); identifier.setSequenceNumber(sequenceNum); LOG.info("Creating password for identifier: " + formatTokenId(identifier) + ", currentKey: " + currentKey.getKeyId()); byte[] password = createPassword(identifier.getBytes(), currentKey.getKey()); DelegationTokenInformation tokenInfo = new DelegationTokenInformation(now + tokenRenewInterval, password, getTrackingIdIfEnabled(identifier)); try { storeToken(identifier, tokenInfo); } catch (IOException ioe) { LOG.error("Could not store token " + formatTokenId(identifier) + "!!", ioe); } return password; }
/** * For subclasses externalizing the storage, for example Zookeeper * based implementations */ protected void updateDelegationKey(DelegationKey key) throws IOException { allKeys.put(key.getKeyId(), key); }
protected Map<Integer, DelegationKey> reloadKeys() { // read keys from token store String[] allKeys = tokenStore.getMasterKeys(); Map<Integer, DelegationKey> keys = new HashMap<>(allKeys.length); for (String keyStr : allKeys) { DelegationKey key = new DelegationKey(); try { decodeWritable(key, keyStr); keys.put(key.getKeyId(), key); } catch (IOException ex) { LOGGER.error("Failed to load master key.", ex); } } synchronized (this) { super.allKeys.clear(); super.allKeys.putAll(keys); } return keys; }
private int loadRMDTSecretManagerKeys(RMState state) throws IOException { int numKeys = 0; LeveldbIterator iter = null; try { iter = new LeveldbIterator(db); iter.seek(bytes(RM_DT_MASTER_KEY_KEY_PREFIX)); while (iter.hasNext()) { Entry<byte[],byte[]> entry = iter.next(); String key = asString(entry.getKey()); if (!key.startsWith(RM_DT_MASTER_KEY_KEY_PREFIX)) { break; } DelegationKey masterKey = loadDelegationKey(entry.getValue()); state.rmSecretManagerState.masterKeyState.add(masterKey); ++numKeys; if (LOG.isDebugEnabled()) { LOG.debug("Loaded RM delegation key from " + key + ": keyId=" + masterKey.getKeyId() + ", expirationDate=" + masterKey.getExpiryDate()); } } } catch (DBException e) { throw new IOException(e); } finally { if (iter != null) { iter.close(); } } return numKeys; }
@Override public byte[] signWithKey(byte[] message, DelegationKey key) { return createPassword(message, key.getKey()); }
@Override public void writeFields(DataOutputStream out) throws IOException { key.write(out); }
@Test public void testDelegationKeyEqualAndHash() { DelegationKey key1 = new DelegationKey(1111, 2222, "keyBytes".getBytes()); DelegationKey key2 = new DelegationKey(1111, 2222, "keyBytes".getBytes()); DelegationKey key3 = new DelegationKey(3333, 2222, "keyBytes".getBytes()); Assert.assertEquals(key1, key2); Assert.assertFalse(key2.equals(key3)); } }
/** * Update the current master key * This is called once by startThreads before tokenRemoverThread is created, * and only by tokenRemoverThread afterwards. */ private void updateCurrentKey() throws IOException { LOG.info("Updating the current master key for generating delegation tokens"); /* Create a new currentKey with an estimated expiry date. */ int newCurrentId; synchronized (this) { newCurrentId = incrementCurrentKeyId(); } DelegationKey newKey = new DelegationKey(newCurrentId, System .currentTimeMillis() + keyUpdateInterval + tokenMaxLifetime, generateSecret()); //Log must be invoked outside the lock on 'this' logUpdateMasterKey(newKey); synchronized (this) { currentKey = newKey; storeDelegationKey(currentKey); } }
@Override protected void removeStoredMasterKey(DelegationKey key) { isRemoveStoredMasterKeyCalled = true; Assert.assertFalse(key.equals(allKeys.get(currentId))); }
private void processKeyAddOrUpdate(byte[] data) throws IOException { ByteArrayInputStream bin = new ByteArrayInputStream(data); DataInputStream din = new DataInputStream(bin); DelegationKey key = new DelegationKey(); key.readFields(din); synchronized (this) { allKeys.put(key.getKeyId(), key); } }
private void loadRMDelegationKeyState(RMState rmState) throws Exception { List<String> childNodes = getChildrenWithRetries(dtMasterKeysRootPath, false); for (String childNodeName : childNodes) { String childNodePath = getNodePath(dtMasterKeysRootPath, childNodeName); byte[] childData = getDataWithRetries(childNodePath, false); if (childData == null) { LOG.warn("Content of " + childNodePath + " is broken."); continue; } ByteArrayInputStream is = new ByteArrayInputStream(childData); DataInputStream fsIn = new DataInputStream(is); try { if (childNodeName.startsWith(DELEGATION_KEY_PREFIX)) { DelegationKey key = new DelegationKey(); key.readFields(fsIn); rmState.rmSecretManagerState.masterKeyState.add(key); if (LOG.isDebugEnabled()) { LOG.debug("Loaded delegation key: keyId=" + key.getKeyId() + ", expirationDate=" + key.getExpiryDate()); } } } finally { is.close(); } } }
.newBuilder().setId(v.getKeyId()).setExpiryDate(v.getExpiryDate()); if (v.getEncodedKey() != null) { b.setKey(ByteString.copyFrom(v.getEncodedKey()));
@Override protected synchronized byte[] createPassword(TokenIdent identifier) { int sequenceNum; long now = Time.now(); sequenceNum = incrementDelegationTokenSeqNum(); identifier.setIssueDate(now); identifier.setMaxDate(now + tokenMaxLifetime); identifier.setMasterKeyId(currentKey.getKeyId()); identifier.setSequenceNumber(sequenceNum); LOG.info("Creating password for identifier: " + identifier + ", currentKey: " + currentKey.getKeyId()); byte[] password = createPassword(identifier.getBytes(), currentKey.getKey()); DelegationTokenInformation tokenInfo = new DelegationTokenInformation(now + tokenRenewInterval, password, getTrackingIdIfEnabled(identifier)); try { storeToken(identifier, tokenInfo); } catch (IOException ioe) { LOG.error("Could not store token !!", ioe); } return password; }