/** * Add a previously used master key to cache (when NN restarts), should be called before * activate(). */ public synchronized void addKey(DelegationKey key) throws IOException { if (running) // a safety check throw new IOException("Can't add delegation key to a running SecretManager."); if (key.getKeyId() > currentId) { currentId = key.getKeyId(); } allKeys.put(key.getKeyId(), key); }
/** * Update the current master key for generating delegation tokens It should be called only by * tokenRemoverThread. */ void rollMasterKey() throws IOException { synchronized (this) { removeExpiredKeys(); /* set final expiry date for retiring currentKey */ currentKey.setExpiryDate(System.currentTimeMillis() + tokenMaxLifetime); /* * currentKey might have been removed by removeExpiredKeys(), if * updateMasterKey() isn't called at expected interval. Add it back to * allKeys just in case. */ allKeys.put(currentKey.getKeyId(), currentKey); } updateCurrentKey(); }
/** * Renew a delegation token. * * @param token the token to renew * @param renewer the full principal name of the user doing the renewal * @return the new expiration time * @throws InvalidToken if the token is invalid * @throws AccessControlException if the user can't renew token */ public synchronized long renewToken(Token<TokenIdent> token, String renewer) throws InvalidToken, IOException { long now = System.currentTimeMillis(); ByteArrayInputStream buf = new ByteArrayInputStream(token.getIdentifier()); DataInputStream in = new DataInputStream(buf); TokenIdent id = createIdentifier(); id.readFields(in); LOG.info("Token renewal requested for identifier: " + id); if (id.getMaxDate() < now) { throw new InvalidToken("User " + renewer + " tried to renew an expired token"); } if ((id.getRenewer() == null) || ("".equals(id.getRenewer().toString()))) { throw new AccessControlException( "User " + renewer + " tried to renew a token without " + "a renewer"); } if (!id.getRenewer().toString().equals(renewer)) { throw new AccessControlException( "Client " + renewer + " tries to renew a token with " + "renewer specified as " + id.getRenewer()); } DelegationKey key = allKeys.get(id.getMasterKeyId()); if (key == null) { throw new InvalidToken( "Unable to find master key for keyId=" + id.getMasterKeyId() + " from cache. Failed to renew an unexpired token" + " with sequenceNumber=" + id.getSequenceNumber()); } byte[] password = createPassword(token.getIdentifier(), key.getKey()); if (!Arrays.equals(password, token.getPassword())) { throw new AccessControlException( "Client " + renewer + " is trying to renew a token with " + "wrong password"); } long renewTime = Math.min(id.getMaxDate(), now + tokenRenewInterval); DelegationTokenInformation info = new DelegationTokenInformation(renewTime, password); if (currentTokens.get(id) == null) { throw new InvalidToken("Renewal request for unknown token"); } currentTokens.put(id, info); return renewTime; }
/** * 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 = currentId + 1; } DelegationKey newKey = new DelegationKey( newCurrentId, System.currentTimeMillis() + keyUpdateInterval + tokenMaxLifetime, generateSecret()); // Log must be invoked outside the lock on 'this' logUpdateMasterKey(newKey); synchronized (this) { currentId = newKey.getKeyId(); currentKey = newKey; allKeys.put(currentKey.getKeyId(), currentKey); } }
@Override protected synchronized byte[] createPassword(TokenIdent identifier) { LOG.info("Creating password for identifier: " + identifier); int sequenceNum; long now = System.currentTimeMillis(); sequenceNum = ++delegationTokenSequenceNumber; identifier.setIssueDate(now); identifier.setMaxDate(now + tokenMaxLifetime); identifier.setMasterKeyId(currentId); identifier.setSequenceNumber(sequenceNum); byte[] password = createPassword(identifier.getBytes(), currentKey.getKey()); currentTokens.put( identifier, new DelegationTokenInformation(now + tokenRenewInterval, password)); return password; }