synchronized void rollCurrentKey() {
    if (!leaderElector.isMaster()) {
      LOG.info("Skipping rollCurrentKey() because not running as master.");
      return;
    }

    long now = EnvironmentEdgeManager.currentTime();
    AuthenticationKey prev = currentKey;
    AuthenticationKey newKey =
        new AuthenticationKey(
            ++idSeq,
            Long.MAX_VALUE, // don't allow to expire until it's replaced by a new key
            generateSecret());
    allKeys.put(newKey.getKeyId(), newKey);
    currentKey = newKey;
    zkWatcher.addKeyToZK(newKey);
    lastKeyUpdate = now;

    if (prev != null) {
      // make sure previous key is still stored
      prev.setExpiration(now + tokenMaxLifetime);
      allKeys.put(prev.getKeyId(), prev);
      zkWatcher.updateKeyInZK(prev);
    }
  }
 @Override
 protected byte[] createPassword(AuthenticationTokenIdentifier identifier) {
   long now = EnvironmentEdgeManager.currentTime();
   AuthenticationKey secretKey = currentKey;
   identifier.setKeyId(secretKey.getKeyId());
   identifier.setIssueDate(now);
   identifier.setExpirationDate(now + tokenMaxLifetime);
   identifier.setSequenceNumber(tokenSeq.getAndIncrement());
   return createPassword(identifier.getBytes(), secretKey.getKey());
 }
 @Override
 public boolean equals(Object obj) {
   if (obj == null || !(obj instanceof AuthenticationKey)) {
     return false;
   }
   AuthenticationKey other = (AuthenticationKey) obj;
   return id == other.getKeyId()
       && expirationDate == other.getExpiration()
       && (secret == null
           ? other.getKey() == null
           : other.getKey() != null
               && Bytes.equals(secret.getEncoded(), other.getKey().getEncoded()));
 }
 @Override
 public byte[] retrievePassword(AuthenticationTokenIdentifier identifier) throws InvalidToken {
   long now = EnvironmentEdgeManager.currentTime();
   if (identifier.getExpirationDate() < now) {
     throw new InvalidToken("Token has expired");
   }
   AuthenticationKey masterKey = allKeys.get(identifier.getKeyId());
   if (masterKey == null) {
     throw new InvalidToken("Unknown master key for token (id=" + identifier.getKeyId() + ")");
   }
   // regenerate the password
   return createPassword(identifier.getBytes(), masterKey.getKey());
 }
  synchronized void removeExpiredKeys() {
    if (!leaderElector.isMaster()) {
      LOG.info("Skipping removeExpiredKeys() because not running as master.");
      return;
    }

    long now = EnvironmentEdgeManager.currentTime();
    Iterator<AuthenticationKey> iter = allKeys.values().iterator();
    while (iter.hasNext()) {
      AuthenticationKey key = iter.next();
      if (key.getExpiration() < now) {
        if (LOG.isDebugEnabled()) {
          LOG.debug("Removing expired key " + key.getKeyId());
        }
        iter.remove();
        zkWatcher.removeKeyFromZK(key);
      }
    }
  }
  public synchronized void addKey(AuthenticationKey key) throws IOException {
    // ignore zk changes when running as master
    if (leaderElector.isMaster()) {
      if (LOG.isDebugEnabled()) {
        LOG.debug("Running as master, ignoring new key " + key.getKeyId());
      }
      return;
    }

    if (LOG.isDebugEnabled()) {
      LOG.debug("Adding key " + key.getKeyId());
    }

    allKeys.put(key.getKeyId(), key);
    if (currentKey == null || key.getKeyId() > currentKey.getKeyId()) {
      currentKey = key;
    }
    // update current sequence
    if (key.getKeyId() > idSeq) {
      idSeq = key.getKeyId();
    }
  }