package com.intrbiz.bergamot.command.admin;
import java.io.IOException;
import java.security.KeyPair;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import com.intrbiz.bergamot.BergamotCLI;
import com.intrbiz.bergamot.BergamotCLICommand;
import com.intrbiz.bergamot.BergamotCLIException;
import com.intrbiz.bergamot.agent.server.config.BergamotAgentServerCfg;
import com.intrbiz.bergamot.config.UICfg;
import com.intrbiz.bergamot.crypto.util.PEMUtil;
import com.intrbiz.bergamot.crypto.util.RSAUtil;
import com.intrbiz.bergamot.model.message.agent.manager.AgentManagerRequest;
import com.intrbiz.bergamot.model.message.agent.manager.AgentManagerResponse;
import com.intrbiz.bergamot.model.message.agent.manager.request.GetRootCA;
import com.intrbiz.bergamot.model.message.agent.manager.request.SignServer;
import com.intrbiz.bergamot.model.message.agent.manager.response.GotRootCA;
import com.intrbiz.bergamot.model.message.agent.manager.response.SignedServer;
import com.intrbiz.bergamot.queue.BergamotAgentManagerQueue;
import com.intrbiz.queue.QueueManager;
import com.intrbiz.queue.RPCClient;
import com.intrbiz.queue.name.RoutingKey;
import com.intrbiz.queue.rabbit.RabbitPool;
public class ServerCommand extends BergamotCLICommand
{
public ServerCommand()
{
super();
}
@Override
public String name()
{
return "server";
}
@Override
public boolean admin()
{
return true;
}
@Override
public String usage()
{
return "generate ...";
}
@Override
public String help()
{
return "Manager Bergamot Agent Server certificates\n" +
"\n" +
"Commands:\n" +
" generate <common-name> - generate and sign a key pair for a Bergamot Agent Server, returning a configuration file\n" +
"\n";
}
@Override
public int execute(BergamotCLI cli, List<String> args) throws Exception
{
if (args.size() < 1) throw new BergamotCLIException("No command given");
String command = args.remove(0);
if ("generate".equalsIgnoreCase(command))
{
if (args.size() != 1) throw new BergamotCLIException("No server common name given");
String commonName = args.remove(0);
// read the UI config and connect to the database
UICfg config = UICfg.loadConfiguration();
// setup the queue manager
QueueManager.getInstance().registerDefaultBroker(new RabbitPool(config.getBroker().getUrl(), config.getBroker().getUsername(), config.getBroker().getPassword()));
// sign the server
try (BergamotAgentManagerQueue queue = BergamotAgentManagerQueue.open())
{
try (RPCClient<AgentManagerRequest, AgentManagerResponse, RoutingKey> client = queue.createBergamotAgentManagerRPCClient())
{
// get the root CA
Certificate rootCrt = this.getRootCA(client);
// generate a key pair
KeyPair pair = RSAUtil.generateRSAKeyPair(2048);
// sign the key
Certificate serverCrt = this.signServer(client, commonName, pair.getPublic());
// build the config
BergamotAgentServerCfg cfg = new BergamotAgentServerCfg();
cfg.setCaCertificate(PEMUtil.saveCertificate(rootCrt));
cfg.setCertificate(PEMUtil.saveCertificate(serverCrt));
cfg.setKey(PEMUtil.saveKey(pair.getPrivate()));
cfg.setPort(15443);
cfg.setName(commonName);
System.out.println(cfg.toString());
System.out.println("<!-- Server CN=" + commonName + " -->");
return 0;
}
}
}
else
{
throw new BergamotCLIException("Unknown sub command: " + command);
}
}
private Certificate signServer(RPCClient<AgentManagerRequest, AgentManagerResponse, RoutingKey> client, String commonName, PublicKey key) throws BergamotCLIException
{
try
{
AgentManagerResponse response = client.publish(new SignServer(commonName, PEMUtil.savePublicKey(key))).get(5, TimeUnit.SECONDS);
if (response instanceof SignedServer)
{
return PEMUtil.loadCertificate(((SignedServer) response).getCertificatePEM());
}
else
{
throw new BergamotCLIException("Failed to communicate with Bergamot Agent Manager");
}
}
catch (InterruptedException | ExecutionException | TimeoutException | IOException e)
{
throw new BergamotCLIException("Failed to communicate with Bergamot Agent Manager", e);
}
}
private Certificate getRootCA(RPCClient<AgentManagerRequest, AgentManagerResponse, RoutingKey> client) throws BergamotCLIException
{
try
{
AgentManagerResponse response = client.publish(new GetRootCA()).get(5, TimeUnit.SECONDS);
if (response instanceof GotRootCA)
{
return PEMUtil.loadCertificate(((GotRootCA) response).getCertificatePEM());
}
else
{
throw new BergamotCLIException("Failed to communicate with Bergamot Agent Manager");
}
}
catch (InterruptedException | ExecutionException | TimeoutException | IOException e)
{
throw new BergamotCLIException("Failed to communicate with Bergamot Agent Manager", e);
}
}
}