@Override protected void addKey(KeyIdentifier key) { allKeys.put(key.getKeyId(), key); } }
@Override protected void addKey(KeyIdentifier key) { keyCache.put(Integer.toString(key.getKeyId()), key); }
@Override public int hashCode() { return Objects.hashCode(getKey(), getKeyId(), encodedKey, algorithm, expiration); }
@Override public synchronized void onResourceUpdate(String name, KeyIdentifier instance) { LOG.debug("SharedResourceCache triggered update: leader={}, resource key={}", leader, name); if (currentKey == null || instance.getExpiration() > currentKey.getExpiration()) { currentKey = instance; LOG.debug("Set current key: leader={}, key={}", leader, currentKey.getKeyId()); } }
@Override public synchronized void onUpdate() { LOG.debug("SharedResourceCache triggered update on key: leader={}", leader); for (KeyIdentifier keyEntry : keyCache.getResources()) { if (currentKey == null || keyEntry.getExpiration() > currentKey.getExpiration()) { currentKey = keyEntry; LOG.debug("Set current key: leader={}, key={}", leader, currentKey.getKeyId()); } } }
private synchronized void rotateKey() { long now = System.currentTimeMillis(); // create a new secret key generateKey(); // clear out any expired keys for (KeyIdentifier keyIdent : keyCache.getResources()) { // we can only remove keys that expired prior to the oldest non-expired token if (keyIdent.getExpiration() < (now - maxTokenExpiration)) { LOG.debug("Removing expired key: id={}, expiration={}", keyIdent.getKeyId(), keyIdent.getExpiration()); keyCache.remove(Integer.toString(keyIdent.getKeyId())); } } lastKeyUpdate = now; }
@Override public void doInit() throws IOException { File keyFile = new File(keyFilePath); String keyFileDirectory = keyFile.getParent(); File keyFileDir = new File(keyFileDirectory); // Create directory for keyfile if it doesn't exist already. if (!keyFileDir.exists() && !keyFileDir.mkdir()) { throw new IOException("Failed to create directory " + keyFileDirectory + " for keyfile storage."); } else { Preconditions.checkState(keyFileDir.isDirectory(), "Configured keyFile directory " + keyFileDirectory + " is not a directory!"); Preconditions.checkState(keyFileDir.canRead(), "Configured keyFile directory " + keyFileDirectory + " exists but is not readable!"); } // Read existing key from file. if (keyFile.exists()) { KeyIdentifier storedKey = keyIdentifierCodec.decode(Files.toByteArray(keyFile)); this.currentKey = storedKey; // the file-based key is considered valid forever allKeys.put(storedKey.getKeyId(), storedKey); } else { Preconditions.checkState(keyFileDir.canWrite(), "Configured keyFile directory " + keyFileDirectory + " exists but is not writable!"); // Create a new key and write to file. generateKey(); keyFile.createNewFile(); Files.write(keyIdentifierCodec.encode(currentKey), keyFile); } }
@Override public final DigestId generateMAC(byte[] message) throws InvalidKeyException { KeyIdentifier signingKey = currentKey; byte[] digest = generateMAC(signingKey.getKey(), message); return new DigestId(signingKey.getKeyId(), digest); }
@Test public void testKeyDistribution() throws Exception { DistributedKeyManager manager1 = getKeyManager(injector1, true); DistributedKeyManager manager2 = getKeyManager(injector2, false); TimeUnit.MILLISECONDS.sleep(1000); TestingTokenManager tokenManager1 = new TestingTokenManager(manager1, injector1.getInstance(AccessTokenIdentifierCodec.class)); TestingTokenManager tokenManager2 = new TestingTokenManager(manager2, injector2.getInstance(AccessTokenIdentifierCodec.class)); tokenManager1.startAndWait(); tokenManager2.startAndWait(); long now = System.currentTimeMillis(); AccessTokenIdentifier ident1 = new AccessTokenIdentifier("testuser", Lists.newArrayList("users", "admins"), now, now + 60 * 60 * 1000); AccessToken token1 = tokenManager1.signIdentifier(ident1); // make sure the second token manager has the secret key required to validate the signature tokenManager2.waitForKey(tokenManager1.getCurrentKey().getKeyId(), 2000, TimeUnit.MILLISECONDS); tokenManager2.validateSecret(token1); tokenManager2.waitForCurrentKey(2000, TimeUnit.MILLISECONDS); AccessToken token2 = tokenManager2.signIdentifier(ident1); tokenManager1.validateSecret(token2); assertEquals(token1.getIdentifier().getUsername(), token2.getIdentifier().getUsername()); assertEquals(token1.getIdentifier().getGroups(), token2.getIdentifier().getGroups()); assertEquals(token1, token2); tokenManager1.stopAndWait(); tokenManager2.stopAndWait(); }