class CertificateManager {

  public synchronized SignCertResponse signAgentCrt(String agentHostname, String agentCrtReqContent, String passphraseAgent) {
    SignCertResponse response = new SignCertResponse();
    LOG.info("Signing agent certificate");

    // Ensure the hostname is not empty or null...
    agentHostname = StringUtils.trim(agentHostname);

    if(StringUtils.isEmpty(agentHostname)) {
      LOG.warn("The agent hostname is missing");
      response.setResult(SignCertResponse.ERROR_STATUS);
      response.setMessage("The agent hostname is missing");
      return response;
    }

    // Optionally check the supplied hostname to make sure it is a valid hostname.
    // By default, this feature is turned on.  If this check is not desired (maybe the validation
    // rules are too strict), the feature may be turned off by setting the following
    // property in the ambari.properties file:
    //
    //    security.agent.hostname.validate = "false"
    //
    if(configs.validateAgentHostnames()) {
      LOG.info("Validating agent hostname: {}", agentHostname);
      if(!HostUtils.isValidHostname(agentHostname)) {
        LOG.warn("The agent hostname is not a valid hostname");
        response.setResult(SignCertResponse.ERROR_STATUS);
        response.setMessage("The agent hostname is not a valid hostname");
        return response;
      }
    }
    else {
      LOG.info("Skipping validation of agent hostname: {}", agentHostname);
    }

    LOG.info("Verifying passphrase");

    String passphraseSrvr = configs.getConfigsMap().get(Configuration.
        PASSPHRASE.getKey()).trim();

    if (!passphraseSrvr.equals(passphraseAgent.trim())) {
      LOG.warn("Incorrect passphrase from the agent");
      response.setResult(SignCertResponse.ERROR_STATUS);
      response.setMessage("Incorrect passphrase from the agent");
      return response;
    }

    Map<String, String> configsMap = configs.getConfigsMap();
    String srvrKstrDir = configsMap.get(Configuration.SRVR_KSTR_DIR.getKey());
    String srvrCrtPass = configsMap.get(Configuration.SRVR_CRT_PASS.getKey());
    String srvrCrtName = configsMap.get(Configuration.SRVR_CRT_NAME.getKey());
    String srvrKeyName = configsMap.get(Configuration.SRVR_KEY_NAME.getKey());
    String agentCrtReqName = agentHostname + ".csr";
    String agentCrtName = agentHostname + ".crt";

    Object[] scriptArgs = {srvrKstrDir, agentCrtReqName, agentCrtName,
        srvrCrtPass, srvrKeyName, srvrCrtName};

    //Revoke previous agent certificate if exists
    File agentCrtFile = new File(srvrKstrDir + File.separator + agentCrtName);

    if (agentCrtFile.exists()) {
      LOG.info("Revoking of " + agentHostname + " certificate.");
      String command = MessageFormat.format(REVOKE_AGENT_CRT, scriptArgs);
      int commandExitCode = runCommand(command);
      if (commandExitCode != 0) {
        response.setResult(SignCertResponse.ERROR_STATUS);
        response.setMessage(ShellCommandUtil.getOpenSslCommandResult(command, commandExitCode));
        return response;
      }
    }

    File agentCrtReqFile = new File(srvrKstrDir + File.separator +
        agentCrtReqName);
    try {
      FileUtils.writeStringToFile(agentCrtReqFile, agentCrtReqContent, Charset.defaultCharset());
    } catch (IOException e1) {
      // TODO Auto-generated catch block
      e1.printStackTrace();
    }

    String command = MessageFormat.format(SIGN_AGENT_CRT, scriptArgs);

    LOG.debug(ShellCommandUtil.hideOpenSslPassword(command));

    int commandExitCode = runCommand(command); // ssl command execution
    if (commandExitCode != 0) {
      response.setResult(SignCertResponse.ERROR_STATUS);
      response.setMessage(ShellCommandUtil.getOpenSslCommandResult(command, commandExitCode));
      //LOG.warn(ShellCommandUtil.getOpenSslCommandResult(command, commandExitCode));
      return response;
    }

    String agentCrtContent = "";
    try {
      agentCrtContent = FileUtils.readFileToString(agentCrtFile, Charset.defaultCharset());
    } catch (IOException e) {
      e.printStackTrace();
      LOG.error("Error reading signed agent certificate");
      response.setResult(SignCertResponse.ERROR_STATUS);
      response.setMessage("Error reading signed agent certificate");
      return response;
    }
    response.setResult(SignCertResponse.OK_STATUS);
    response.setSignedCa(agentCrtContent);
    //LOG.info(ShellCommandUtil.getOpenSslCommandResult(command, commandExitCode));
    return response;
  }

}