/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.slider.server.services.security;

import com.google.inject.Singleton;
import org.apache.commons.io.FileUtils;
import org.apache.slider.common.SliderKeys;
import org.apache.slider.core.conf.MapOperations;
import org.apache.slider.core.exceptions.SliderException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.Charset;
import java.text.MessageFormat;

@Singleton
public class CertificateManager {

  private static final Logger LOG =
      LoggerFactory.getLogger(CertificateManager.class);

  private static final String GEN_SRVR_KEY = "openssl genrsa -des3 " +
      "-passout pass:{0} -out {1}/{2} 4096 ";
  private static final String GEN_SRVR_REQ = "openssl req -passin pass:{0} " +
      "-new -key {1}/{2} -out {1}/{5} -batch";
  private static final String SIGN_SRVR_CRT = "openssl ca -create_serial " +
    "-out {1}/{3} -days 365 -keyfile {1}/{2} -key {0} -selfsign " +
    "-extensions jdk7_ca -config {1}/ca.config -batch " +
    "-infiles {1}/{5}";
  private static final String EXPRT_KSTR = "openssl pkcs12 -export" +
      " -in {1}/{3} -inkey {1}/{2} -certfile {1}/{3} -out {1}/{4} " +
      "-password pass:{0} -passin pass:{0} \n";
  private static final String REVOKE_AGENT_CRT = "openssl ca " +
      "-config {0}/ca.config -keyfile {0}/{4} -revoke {0}/{2} -batch " +
      "-passin pass:{3} -cert {0}/{5}";
  private static final String SIGN_AGENT_CRT = "openssl ca -config " +
      "{0}/ca.config -in {0}/{1} -out {0}/{2} -batch -passin pass:{3} " +
      "-keyfile {0}/{4} -cert {0}/{5}";
  private static final String GEN_AGENT_KEY="openssl req -new -newkey " +
      "rsa:1024 -nodes -keyout {0}/{2}.key -subj /OU={1}/CN={2} -out {0}/{2}.csr";
  private String passphrase;

  /**
    * Verify that root certificate exists, generate it otherwise.
    */
  public void initialize(MapOperations compOperations) {
    SecurityUtils.initializeSecurityParameters(compOperations);

    LOG.info("Initialization of root certificate");
    boolean certExists = isCertExists();
    LOG.info("Certificate exists:" + certExists);

    if (!certExists) {
      generateServerCertificate();
    }

  }

  /**
   * Checks root certificate state.
   * @return "true" if certificate exists
   */
  private boolean isCertExists() {

    String srvrKstrDir = SecurityUtils.getSecurityDir();
    String srvrCrtName = SliderKeys.CRT_FILE_NAME;
    File certFile = new File(srvrKstrDir + File.separator + srvrCrtName);
    LOG.debug("srvrKstrDir = " + srvrKstrDir);
    LOG.debug("srvrCrtName = " + srvrCrtName);
    LOG.debug("certFile = " + certFile.getAbsolutePath());

    return certFile.exists();
  }

  public void setPassphrase(String passphrase) {
    this.passphrase = passphrase;
  }

  class StreamConsumer extends Thread
  {
    InputStream is;
    boolean logOutput;

    StreamConsumer(InputStream is, boolean logOutput)
    {
      this.is = is;
      this.logOutput = logOutput;
    }

    StreamConsumer(InputStream is)
    {
      this(is, false);
    }

    public void run()
    {
      try
      {
        InputStreamReader isr = new InputStreamReader(is,
                                                      Charset.forName("UTF8"));
        BufferedReader br = new BufferedReader(isr);
        String line;
        while ( (line = br.readLine()) != null)
          if (logOutput) {
            LOG.info(line);
          }
      } catch (IOException e)
      {
        LOG.error("Error during processing of process stream", e);
      }
    }
  }


  /**
   * Runs os command
   *
   * @return command execution exit code
   */
  private int runCommand(String command) throws SliderException {
    int exitCode = -1;
    String line = null;
    Process process = null;
    BufferedReader br= null;
    try {
      process = Runtime.getRuntime().exec(command);
      StreamConsumer outputConsumer =
          new StreamConsumer(process.getInputStream(), true);
      StreamConsumer errorConsumer =
          new StreamConsumer(process.getErrorStream());

      outputConsumer.start();
      errorConsumer.start();

      try {
        process.waitFor();
        SecurityUtils.logOpenSslExitCode(command, process.exitValue());
        exitCode = process.exitValue();
        if (exitCode != 0) {
          throw new SliderException(exitCode, "Error running command %s", command);
        }
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      if (br != null) {
        try {
          br.close();
        } catch (IOException ioe) {
          ioe.printStackTrace();
        }
      }
    }

    return exitCode;//some exception occurred

  }

  public synchronized void generateAgentCertificate(String agentHostname, String containerId) {
    LOG.info("Generation of agent certificate for {}", agentHostname);

    String srvrKstrDir = SecurityUtils.getSecurityDir();
    Object[] scriptArgs = {srvrKstrDir, agentHostname, containerId};

    try {
      String command = MessageFormat.format(GEN_AGENT_KEY, scriptArgs);
      runCommand(command);

      signAgentCertificate(containerId);

    } catch (SliderException e) {
      LOG.error("Error generating the agent certificate", e);
    }
  }

  private void generateServerCertificate(){
    LOG.info("Generation of server certificate");

    String srvrKstrDir = SecurityUtils.getSecurityDir();
    String srvrCrtName = SliderKeys.CRT_FILE_NAME;
    String srvrCsrName = SliderKeys.CSR_FILE_NAME;
    String srvrKeyName = SliderKeys.KEY_FILE_NAME;
    String kstrName = SliderKeys.KEYSTORE_FILE_NAME;
    String srvrCrtPass = SecurityUtils.getKeystorePass();

    Object[] scriptArgs = {srvrCrtPass, srvrKstrDir, srvrKeyName,
        srvrCrtName, kstrName, srvrCsrName};

    try {
      String command = MessageFormat.format(GEN_SRVR_KEY,scriptArgs);
      runCommand(command);

      command = MessageFormat.format(GEN_SRVR_REQ,scriptArgs);
      runCommand(command);

      command = MessageFormat.format(SIGN_SRVR_CRT,scriptArgs);
      runCommand(command);

      command = MessageFormat.format(EXPRT_KSTR,scriptArgs);
      runCommand(command);
    } catch (SliderException e) {
      LOG.error("Error generating the server certificate", e);
    }

  }

  /**
   * Returns server certificate content
   * @return string with server certificate content
   */
  public String getServerCert() {
    File certFile = getServerCertficateFilePath();
    String srvrCrtContent = null;
    try {
      srvrCrtContent = FileUtils.readFileToString(certFile);
    } catch (IOException e) {
      LOG.error(e.getMessage());
    }
    return srvrCrtContent;
  }

  public static File getServerCertficateFilePath() {
    return new File(SecurityUtils.getSecurityDir() +
          File.separator + SliderKeys.CRT_FILE_NAME);
  }

  public static File getAgentCertficateFilePath(String containerId) {
    return new File(SecurityUtils.getSecurityDir() +
                    File.separator + containerId + ".crt");
  }

  public static File getAgentKeyFilePath(String containerId) {
    return new File(SecurityUtils.getSecurityDir() +
                    File.separator + containerId + ".key");
  }

  /**
   * Signs agent certificate
   * Adds agent certificate to server keystore
   * @return string with agent signed certificate content
   */
  public synchronized SignCertResponse signAgentCrt(String agentHostname,
                                                    String agentCrtReqContent,
                                                    String passphraseAgent) {
    SignCertResponse response = new SignCertResponse();
    LOG.info("Signing of agent certificate");
    LOG.info("Verifying passphrase");

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

    String srvrKstrDir = SecurityUtils.getSecurityDir();
    String srvrCrtPass = SecurityUtils.getKeystorePass();
    String srvrCrtName = SliderKeys.CRT_FILE_NAME;
    String srvrKeyName = SliderKeys.KEY_FILE_NAME;
    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);

    String command = null;
    if (agentCrtFile.exists()) {
      LOG.info("Revoking of " + agentHostname + " certificate.");
      command = MessageFormat.format(REVOKE_AGENT_CRT, scriptArgs);
      try {
        runCommand(command);
      } catch (SliderException e) {
        int commandExitCode = e.getExitCode();
        response.setResult(SignCertResponse.ERROR_STATUS);
        response.setMessage(
            SecurityUtils.getOpenSslCommandResult(command, commandExitCode));
        return response;
      }
    }

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

    command = MessageFormat.format(SIGN_AGENT_CRT, scriptArgs);

    LOG.debug(SecurityUtils.hideOpenSslPassword(command));
    try {
      runCommand(command);
    } catch (SliderException e) {
      int commandExitCode = e.getExitCode();
      response.setResult(SignCertResponse.ERROR_STATUS);
      response.setMessage(
          SecurityUtils.getOpenSslCommandResult(command, commandExitCode));
      return response;
    }

    String agentCrtContent = "";
    try {
      agentCrtContent = FileUtils.readFileToString(agentCrtFile);
    } 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;
  }

  private String signAgentCertificate (String containerId)
      throws SliderException {
    String srvrKstrDir = SecurityUtils.getSecurityDir();
    String srvrCrtPass = SecurityUtils.getKeystorePass();
    String srvrCrtName = SliderKeys.CRT_FILE_NAME;
    String srvrKeyName = SliderKeys.KEY_FILE_NAME;
    String agentCrtReqName = containerId + ".csr";
    String agentCrtName = containerId + ".crt";

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

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

    String command;
    if (agentCrtFile.exists()) {
      LOG.info("Revoking of " + containerId + " certificate.");
      command = MessageFormat.format(REVOKE_AGENT_CRT, scriptArgs);
      runCommand(command);
    }

    command = MessageFormat.format(SIGN_AGENT_CRT, scriptArgs);

    LOG.debug(SecurityUtils.hideOpenSslPassword(command));
    runCommand(command);

    return agentCrtName;

  }
}
