package com.intrbiz.bergamot.agent.handler; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.net.InetAddress; import java.net.UnknownHostException; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; import java.util.UUID; import org.apache.log4j.Logger; import com.intrbiz.bergamot.agent.BergamotAgent; import com.intrbiz.bergamot.agent.KeyStoreUtil; import com.intrbiz.bergamot.agent.config.BergamotAgentCfg; import com.intrbiz.bergamot.agent.config.CfgParameter; import com.intrbiz.bergamot.model.message.agent.AgentMessage; import com.intrbiz.bergamot.model.message.agent.registration.AgentRegistrationComplete; import com.intrbiz.bergamot.model.message.agent.registration.AgentRegistrationFailed; import com.intrbiz.bergamot.model.message.agent.registration.AgentRegistrationRequest; import com.intrbiz.bergamot.model.message.agent.registration.AgentRegistrationRequired; public class AgentRegistrationHandler extends AbstractAgentHandler { private Logger logger = Logger.getLogger(AgentRegistrationHandler.class); private UUID hostId; private String hostName; private KeyPair currentKeyPair; private long registrationStartedAt; public AgentRegistrationHandler() { super(); } @Override public Class<?>[] getMessages() { return new Class[] { AgentRegistrationRequired.class, AgentRegistrationComplete.class, AgentRegistrationFailed.class }; } @Override public AgentMessage handle(AgentMessage request) { if (request instanceof AgentRegistrationRequired) { synchronized (this) { if (this.currentKeyPair == null) { try { logger.info("Starting agent registration process"); registrationStartedAt = System.currentTimeMillis(); // first compute our host name this.hostId = this.getHostId(); this.hostName = this.getHostName(); // now generate an RSA key pair KeyPairGenerator jenny = KeyPairGenerator.getInstance("RSA"); jenny.initialize(2048, new SecureRandom()); this.currentKeyPair = jenny.generateKeyPair(); // ask for us to be registered AgentRegistrationRequest regReq = new AgentRegistrationRequest(); regReq.setAgentId(this.hostId); regReq.setCommonName(hostName); regReq.setPublicKey(KeyStoreUtil.savePublicKey(this.currentKeyPair.getPublic())); // fill out the registration request return regReq; } catch (NoSuchAlgorithmException e) { throw new RuntimeException("Failed to generate RSA key", e); } } else { logger.info("Agent registration attempt already in progress, started: " + (System.currentTimeMillis() - registrationStartedAt) + " ms ago"); } } } else if (request instanceof AgentRegistrationComplete) { AgentRegistrationComplete complete = ((AgentRegistrationComplete) request); logger.info("Successfully got signed agent certificate:\n" + complete.getCertificate()); // build the new configuration file BergamotAgentCfg currentConfig = this.getAgent().getConfiguration(); // set the id currentConfig.getParameters().clear(); currentConfig.addParameter(new CfgParameter("agent-id", null, null, complete.getAgentId().toString())); // set the name currentConfig.setName(complete.getCommonName()); // update the certificates currentConfig.setCertificate(complete.getCertificate()); currentConfig.setKey(KeyStoreUtil.saveKey(this.currentKeyPair.getPrivate())); // save the config try { BergamotAgent.saveConfig(currentConfig); } catch (Exception e) { logger.error("Failed to save Bergamot Agent configuration after registration"); } // restart the agent to reconnect this.getAgent().restart(currentConfig); } else if (request instanceof AgentRegistrationFailed) { logger.error("Failed to get signed agent certificate: " + ((AgentRegistrationFailed) request).getErrorCode() + " " + ((AgentRegistrationFailed) request).getMessage()); this.currentKeyPair = null; } else { logger.warn("Ignoring unexpected registration message: " + request); } return null; } private String getHostName() { // first off allow for the host name to be overridden using a bergamot parameter String hostName = System.getProperty("bergamot.host.name"); if (hostName == null || hostName.length() <= 0) { // next try the gerald host parameter hostName = System.getProperty("gerald.host.name"); if (hostName == null || hostName.length() <= 0) { try { // look at localhost address hostName = InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException e) { throw new RuntimeException("Unable to get host name, please set the proprty: gerald.host.name."); } } } return hostName; } private UUID getHostId() { String hostId = System.getProperty("bergamot.host.id"); if (hostId == null || hostId.length() <= 0) { hostId = this.readHostIdFile("bergamot.host.id"); } if (hostId == null || hostId.length() <= 0) { hostId = System.getProperty("gerald.host.id"); } if (hostId == null || hostId.length() <= 0) { hostId = this.readHostIdFile("gerald.host.id"); } if (hostId == null || hostId.length() <= 0) { hostId = UUID.randomUUID().toString(); } return UUID.fromString(hostId); } private String readHostIdFile(String fileName) { try { File file = new File("/etc/" + fileName); if (file.exists()) { BufferedReader reader = new BufferedReader(new FileReader(file)); try { String id = reader.readLine(); if (id != null) return UUID.fromString(id.trim()).toString(); } finally { reader.close(); } } } catch (Exception e) { } return null; } }