package io.fathom.cloud.keyczar; import io.fathom.cloud.zookeeper.ZookeeperClient; import javax.inject.Inject; import javax.inject.Singleton; import org.keyczar.Crypter; import org.keyczar.GenericKeyczar; import org.keyczar.KeyMetadata; import org.keyczar.KeyVersion; import org.keyczar.KeyczarEncryptedWriter; import org.keyczar.enums.KeyStatus; import org.keyczar.exceptions.KeyczarException; import org.keyczar.interfaces.KeyczarReader; import org.keyczar.interfaces.KeyczarWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.fathomdb.Configuration; @Singleton public class ZookeeperKeyczarFactory implements KeyczarFactory { private static final Logger log = LoggerFactory.getLogger(ZookeeperKeyczarFactory.class); final ZookeeperClient zk; final String base; public ZookeeperKeyczarFactory(ZookeeperClient zk, String base) { this.zk = zk; if (!base.endsWith("/")) { base += "/"; } this.base = base; } @Inject public ZookeeperKeyczarFactory(ZookeeperClient zk, Configuration config) { this(zk, config.lookup("keystore.zookeeper.path", "/keystore")); } public GenericKeyczar find(String key) throws KeyczarException { return find(key, null); } @Override public GenericKeyczar find(String key, Crypter crypter) throws KeyczarException { KeyczarWriter reader = getReader(key, crypter); if (!hasMetadata(reader)) { return null; } return new GenericKeyczar(reader); } @Override public KeyczarWriter getReader(String key, Crypter crypter) throws KeyczarException { String location = base + key; KeyczarWriter reader = buildStore(zk, location, crypter); return reader; } @Override public GenericKeyczar create(String key, KeyMetadata kmd, Crypter crypter) throws KeyczarException { String location = base + key; KeyczarWriter reader = buildStore(zk, location, crypter); if (hasMetadata(reader)) { throw new IllegalStateException(); } GenericKeyczar keyczar = GenericKeyczar.create(reader, kmd); return keyczar; } private boolean hasMetadata(KeyczarWriter reader) { try { reader.getMetadata(); return true; } catch (KeyczarException e) { return false; } } private KeyczarWriter buildStore(ZookeeperClient zk, String location, Crypter crypter) { ZookeeperKeyczarStore store = new ZookeeperKeyczarStore(zk, location); if (crypter == null) { return store; } else { return new KeyczarEncryptedWriter(store, crypter, crypter); } } @Override public boolean ensureKeyCreated(GenericKeyczar store) throws KeyczarException { KeyVersion primaryVersion = store.getMetadata().findPrimaryVersion(); if (primaryVersion != null) { return false; } log.info("Creating new KeyCzar key"); store.addVersion(KeyStatus.PRIMARY); store.write(); return true; } @Override public void publicKeyExport(String dest, GenericKeyczar src) throws KeyczarException { String destLocation = base + dest; src.publicKeyExport(new ZookeeperKeyczarStore(zk, destLocation)); } @Override public KeyczarReader getReader(String key) throws KeyczarException { return getReader(key, null); } }