package io.fathom.cloud.identity.commands;
import io.fathom.cloud.commands.Cmdlet;
import io.fathom.cloud.identity.LoginService;
import io.fathom.cloud.identity.secrets.Secrets;
import io.fathom.cloud.identity.services.IdentityService;
import io.fathom.cloud.keyczar.KeyczarFactory;
import java.io.File;
import javax.inject.Inject;
import org.keyczar.Crypter;
import org.keyczar.DefaultKeyType;
import org.keyczar.GenericKeyczar;
import org.keyczar.KeyMetadata;
import org.keyczar.KeyVersion;
import org.keyczar.KeyczarFileReader;
import org.keyczar.enums.KeyPurpose;
import org.keyczar.enums.KeyStatus;
import org.keyczar.enums.RsaPadding;
import org.keyczar.exceptions.KeyczarException;
import org.keyczar.keyparams.KeyParameters;
import org.keyczar.keyparams.RsaKeyParameters;
import org.kohsuke.args4j.Option;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fathomdb.io.IoUtils;
public class PasswordRecoveryCreateCmdlet extends Cmdlet {
public PasswordRecoveryCreateCmdlet() {
super("id-passwordrecovery-create");
}
private static final Logger log = LoggerFactory.getLogger(PasswordRecoveryCreateCmdlet.class);
@Inject
IdentityService identityService;
@Inject
LoginService loginService;
@Inject
KeyczarFactory keyczarFactory;
@Option(name = "-o", usage = "path for private key store", required = false)
public File path;
@Override
public void run() throws Exception {
if (path == null) {
path = IoUtils.resolve("~/passwordrecovery");
}
log.info("Checking for existing password-recovery key");
{
Crypter crypter = null;
GenericKeyczar store = keyczarFactory.find(Secrets.KEY_FORGOT_PASSWORD_PUBLIC, crypter);
if (store != null) {
// TODO: Should we allow key rotation? Replacement?
log.info("Password-recovery key already exists");
return;
}
}
log.info("Creating password recovery key");
String nameFlag = "Password recovery keystore";
String metadata = null;
{
path.mkdirs();
KeyczarFileReader store = new KeyczarFileReader(path.getAbsolutePath());
try {
metadata = store.getMetadata();
} catch (Exception e) {
log.info("Metadata not found");
}
if (metadata == null) {
KeyMetadata kmd = new KeyMetadata(nameFlag, KeyPurpose.DECRYPT_AND_ENCRYPT, DefaultKeyType.RSA_PRIV);
GenericKeyczar.create(store, kmd);
}
}
{
KeyczarFileReader store = new KeyczarFileReader(path.getAbsolutePath());
GenericKeyczar keyczar = new GenericKeyczar(store);
for (KeyVersion version : keyczar.getVersions()) {
log.info("Local password recovery key already exists; exiting for safety");
return;
}
KeyParameters keyParameters = DefaultKeyType.RSA_PRIV.applyDefaultParameters(new RsaKeyParameters() {
@Override
public int getKeySize() throws KeyczarException {
return 4096;
}
@Override
public RsaPadding getRsaPadding() throws KeyczarException {
// Use default
return null;
}
});
keyczar.addVersion(KeyStatus.PRIMARY, keyParameters);
keyczar.write();
log.info("Storing public key in zookeeper");
keyczarFactory.publicKeyExport(Secrets.KEY_FORGOT_PASSWORD_PUBLIC, keyczar);
log.info("Saved public key in zookeeper");
log.info("Store the private key in a _very_ safe place");
log.info("Backup the entire directory: {}", path);
}
}
}