#include "tlbmc/credentials/credential_manager_impl.h"

#include <filesystem>  // NOLINT
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <system_error>  // NOLINT
#include <thread>        // NOLINT
#include <utility>

#include "owner_certificate/owner_verification_cert_configuration.pb.h"
#include "absl/functional/any_invocable.h"
#include "absl/log/log.h"
#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/substitute.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "zatar/x509_certificate.h"
#include "g3/macros.h"
#include "tlbmc/credentials/credential_manager.h"
#include "tlbmc/redfish/routes/action_managers/file_manager.h"
#include "resource.pb.h"
#include "tlbmc/resource/syslog_config_utils.h"
#include "tlbmc/utils/shell_command_executor.h"
#include "zatar/cert_error_handling.h"
#include "zatar/generate_cert.h"
#include "openssl/asn1.h"
#include "zatar/g3_misc.h"
#include "openssl/bio.h"
#include "openssl/bn.h"
#include "openssl/buffer.h"
#include "openssl/evp.h"
#include "openssl/pem.h"
#include "openssl/rsa.h"
#include "openssl/stack.h"
#include "openssl/x509.h"
#include "google/protobuf/text_format.h"
#include "re2/re2.h"

namespace milotic_tlbmc {

using ::milotic::authn::GeneratePrivateKey;
using ::milotic::authn::GetSslErrorOnQueue;
using ::milotic::authn::ReturnErrorIfNotSuccess;
using ::milotic::authn::ReturnErrorIfNull;
using ::owner_certificate::OwnerVerificationCertConfiguration;
using ::owner_certificate::SerialConsoleAccessLevel;
using ::google::protobuf::TextFormat;

namespace {

absl::Status AddNameEntry(X509_NAME* name, std::string_view entry,
                          std::string_view value) {
  ECCLESIA_RETURN_IF_ERROR(ReturnErrorIfNotSuccess(
      X509_NAME_add_entry_by_txt(
          name, std::string(entry).c_str(), MBSTRING_ASC,
          reinterpret_cast<const unsigned char*>(value.data()), value.size(),
          /*loc=*/-1,
          /*set=*/0),
      absl::StrCat("Failed to add name entry: ", value, "",
                   GetSslErrorOnQueue())));
  return absl::OkStatus();
}

std::string GetSyslogOverrideContent(const SyslogTargetConfig& config) {
  std::string protocol_str = "tcp";
  auto protocol_yocto = GetYoctoStringFromSyslogProtocol(config.protocol());
  if (protocol_yocto.ok()) {
    protocol_str = *protocol_yocto;
  } else {
    LOG(ERROR) << "Failed to convert protocol enum to Yocto string: "
               << protocol_yocto.status();
  }

  std::string tls_mode_str = "tls";
  auto tls_mode_yocto = GetYoctoStringFromSyslogTlsMode(config.tls_mode());
  if (tls_mode_yocto.ok()) {
    tls_mode_str = *tls_mode_yocto;
  } else {
    LOG(ERROR) << "Failed to convert TLS mode enum to Yocto string: "
               << tls_mode_yocto.status();
  }

  return absl::StrFormat(
      "[Service]\n"
      "Environment=PROD_SYSLOG_IP=\"%s\"\n"
      "Environment=PROD_SYSLOG_PORT=\"%d\"\n"
      "Environment=PROD_SYSLOG_PROTO=\"%s\"\n"
      "Environment=PROD_SYSLOG_TLS_MODE=\"%s\"\n"
      "TimeoutStopSec=5\n",
      config.target_ip(), static_cast<int>(config.target_port()), protocol_str,
      tls_mode_str);
}

}  // namespace

absl::StatusOr<std::unique_ptr<CredentialManagerImpl>>
CredentialManagerImpl::Create(const CredentialManagerParams& params) {
  // Check that private key are non empty strings and are files in the same
  // folder
  if (params.private_key_path.empty()) {
    return absl::InvalidArgumentError("Private key path is empty");
  }
  if (params.cert_path.empty()) {
    return absl::InvalidArgumentError("Cert path is empty");
  }

  // Check that the private key and cert are in the same folder
  std::filesystem::path private_key_path_fs(params.private_key_path);
  std::filesystem::path cert_path_fs(params.cert_path);
  if (private_key_path_fs.parent_path() != cert_path_fs.parent_path()) {
    return absl::InvalidArgumentError(
        "Private key and cert are not in the same folder");
  }

  if (params.owner_verification_cert_path.empty()) {
    return absl::InvalidArgumentError("Owner verification cert path is empty");
  }

  if (params.owner_verification_config_path.empty()) {
    return absl::InvalidArgumentError(
        "Owner verification config path is empty");
  }

  if (params.bmc_ssh_trusted_user_ca_keys_path.empty()) {
    return absl::InvalidArgumentError(
        "BMC SSH trusted user CA keys path is empty");
  }

  if (params.trust_bundle_path.empty()) {
    return absl::InvalidArgumentError("Trust bundle path is empty");
  }

  if (params.trust_bundle_signature_path.empty()) {
    return absl::InvalidArgumentError("Trust bundle signature path is empty");
  }

  if (params.os_verification_cert_path.empty()) {
    return absl::InvalidArgumentError("OS verification cert path is empty");
  }

  if (params.os_verification_key_path.empty()) {
    return absl::InvalidArgumentError("OS verification key path is empty");
  }

  if (params.serial_console_trusted_user_ca_keys_path.empty()) {
    return absl::InvalidArgumentError(
        "Serial console trusted user CA keys path is empty");
  }

  if (params.serial_console_detatched_signature_path.empty()) {
    return absl::InvalidArgumentError(
        "Serial console detatched signature path is empty");
  }

  if (params.serial_console_access_level_dir.empty()) {
    return absl::InvalidArgumentError(
        "Serial console access level path is empty");
  }
  if (params.syslog_client_conf_override_path.empty()) {
    return absl::InvalidArgumentError(
        "Syslog client conf override path is empty");
  }
  if (params.syslog_root_cert_path.empty()) {
    return absl::InvalidArgumentError("Syslog root cert path is empty");
  }

  return absl::WrapUnique(new CredentialManagerImpl(params));
}

void CredentialManagerImpl::ParseOwnerVerificationCert() {
  // If the write path already exists, then we should read from there.
  absl::StatusOr<std::string> owner_verification_cert =
      FileManager::ReadFile(params_.owner_verification_cert_path);

  if (!owner_verification_cert.ok()) {
    LOG(ERROR) << "Failed to read owner verification certificate: "
               << owner_verification_cert.status()
               << ". All owner verification certificate validation will fail "
                  "as we will use an empty certificate.";
    return;
  }

  LOG(WARNING) << "Successfully read the owner verification certificate.";
  owner_verification_cert_ = std::move(*owner_verification_cert);
}

void CredentialManagerImpl::ParseOwnerVerificationConfiguration() {
  // Reading the Owner Verification Config file
  absl::StatusOr<std::string> owner_verification_config =
      FileManager::ReadFile(params_.owner_verification_config_path);
  if (!owner_verification_config.ok()) {
    LOG(ERROR) << "Failed to read owner verification config: "
               << owner_verification_config.status()
               << ". Using default config which allows firmware updates.";
    return;
  }
  // Parse the owner verification config file.
  OwnerVerificationCertConfiguration owner_verification_cert_configuration;
  TextFormat::Parser parser;
  parser.AllowUnknownField(true);
  if (!parser.ParseFromString(*owner_verification_config,
                              &owner_verification_cert_configuration)) {
    LOG(ERROR) << "Failed to parse owner verification config. Using default "
                  "config which allows firmware updates.";
    return;
  }
  owner_verification_cert_configuration_ =
      std::move(owner_verification_cert_configuration);

  SerialConsoleAccessLevel serial_console_access_level =
      owner_verification_cert_configuration_->serial_console_access_level();

  absl::Status status;
  switch (serial_console_access_level) {
    case SerialConsoleAccessLevel::ACCESS_FULL:
      break;
    case SerialConsoleAccessLevel::ACCESS_DISABLE:
      status = FileManager::WriteToFile(
          "", absl::StrCat(params_.serial_console_access_level_dir,
                           "/serial_console_disabled"));
      if (!status.ok()) {
        LOG(ERROR) << "Failed to write to serial console disabled file: "
                   << status;
      }
      break;
    case SerialConsoleAccessLevel::ACCESS_READONLY:
      status = FileManager::WriteToFile(
          "", absl::StrCat(params_.serial_console_access_level_dir,
                           "/serial_console_readonly"));
      if (!status.ok()) {
        LOG(ERROR) << "Failed to write to serial console readonly file: "
                   << status;
      }
      break;
    default:
      LOG(ERROR) << "Serial console access level is unknown.";
      break;
  }
}

void CredentialManagerImpl::ParseBmcSshTrustedUserCaKeys() {
  absl::StatusOr<std::string> bmc_ssh_trusted_user_ca_keys_signature =
      FileManager::ReadFile(params_.bmc_ssh_trusted_user_ca_keys_path);
  if (!bmc_ssh_trusted_user_ca_keys_signature.ok()) {
    LOG(ERROR) << "Failed to read BMC SSH trusted user CA keys signature: "
               << bmc_ssh_trusted_user_ca_keys_signature.status()
               << ". Assuming no BMC SSH trusted user CA keys signature.";
    return;
  }
  bmc_ssh_trusted_user_ca_keys_signature_ =
      std::move(*bmc_ssh_trusted_user_ca_keys_signature);
}

void CredentialManagerImpl::ParseTrustBundleFiles() {
  absl::StatusOr<std::string> trust_bundle =
      FileManager::ReadFile(params_.trust_bundle_path);
  if (!trust_bundle.ok()) {
    LOG(ERROR) << "Failed to read trust bundle: " << trust_bundle.status()
               << ". Assuming no trust bundle.";
    return;
  }
  trust_bundle_ = std::move(*trust_bundle);

  absl::StatusOr<std::string> trust_bundle_signature =
      FileManager::ReadFile(params_.trust_bundle_signature_path);
  if (!trust_bundle_signature.ok()) {
    LOG(ERROR) << "Failed to read trust bundle signature: "
               << trust_bundle_signature.status()
               << ". Assuming no trust bundle signature.";
    return;
  }
  trust_bundle_signature_ = std::move(*trust_bundle_signature);
}

void CredentialManagerImpl::ParseServerCert() {
  absl::StatusOr<std::string> server_cert =
      FileManager::ReadFile(params_.cert_path);
  if (!server_cert.ok()) {
    LOG(ERROR) << "Failed to read server certificate: " << server_cert.status()
               << ". Assuming no server certificate.";
    return;
  }
  server_cert_ = std::move(*server_cert);
}

void CredentialManagerImpl::ParseOsVerificationCert() {
  absl::StatusOr<std::string> os_verification_cert =
      FileManager::ReadFile(params_.os_verification_cert_path);
  if (!os_verification_cert.ok()) {
    LOG(ERROR) << "Failed to read OS verification certificate: "
               << os_verification_cert.status()
               << ". Assuming no OS verification certificate.";
    return;
  }
  os_verification_cert_ = std::move(*os_verification_cert);
}

void CredentialManagerImpl::ParseSerialConsoleTrustedUserCAKeys() {
  absl::StatusOr<std::string> serial_console_trusted_user_ca_keys =
      FileManager::ReadFile(params_.serial_console_trusted_user_ca_keys_path);
  if (!serial_console_trusted_user_ca_keys.ok()) {
    LOG(ERROR) << "Failed to read serial console trusted user CA keys: "
               << serial_console_trusted_user_ca_keys.status()
               << ". Assuming no serial console trusted user CA keys.";
  } else {
    serial_console_trusted_user_ca_keys_ =
        std::move(*serial_console_trusted_user_ca_keys);
  }

  absl::StatusOr<std::string> serial_console_detatched_signature =
      FileManager::ReadFile(params_.serial_console_detatched_signature_path);
  if (!serial_console_detatched_signature.ok()) {
    LOG(ERROR) << "Failed to read serial console detatched signature: "
               << serial_console_detatched_signature.status()
               << ". Assuming no serial console detatched signature.";
    return;
  }
  serial_console_detatched_signature_ =
      std::move(*serial_console_detatched_signature);
}

void CredentialManagerImpl::ParseSyslogTargetConfig() {
  absl::StatusOr<std::string> syslog_client_conf_override =
      FileManager::ReadFile(params_.syslog_client_conf_override_path);
  if (!syslog_client_conf_override.ok()) {
    LOG(ERROR) << "Failed to read syslog client conf override: "
               << syslog_client_conf_override.status()
               << ". Assuming no syslog client conf override.";
    return;
  }

  std::string target_ip;
  int64_t target_port;
  SyslogProtocol protocol = SYSLOG_PROTOCOL_TCP;
  SyslogTlsMode tls_mode = SYSLOG_TLS_MODE_TLS;
  if (RE2::PartialMatch(*syslog_client_conf_override,
                        "Environment=PROD_SYSLOG_IP=\"([^\"]+)\"",
                        &target_ip) &&
      RE2::PartialMatch(*syslog_client_conf_override,
                        "Environment=PROD_SYSLOG_PORT=\"(\\d+)\"",
                        &target_port)) {
    std::string proto_str;
    if (RE2::PartialMatch(*syslog_client_conf_override,
                          "Environment=PROD_SYSLOG_PROTO=\"([^\"]+)\"",
                          &proto_str)) {
      auto proto_enum = GetSyslogProtocolFromYoctoString(proto_str);
      if (proto_enum.ok()) {
        protocol = *proto_enum;
      } else {
        LOG(ERROR) << "Failed to parse protocol from Yocto config: "
                   << proto_enum.status();
      }
    }
    std::string tls_mode_str;
    if (RE2::PartialMatch(*syslog_client_conf_override,
                          "Environment=PROD_SYSLOG_TLS_MODE=\"([^\"]+)\"",
                          &tls_mode_str)) {
      auto tls_mode_enum = GetSyslogTlsModeFromYoctoString(tls_mode_str);
      if (tls_mode_enum.ok()) {
        tls_mode = *tls_mode_enum;
      } else {
        LOG(ERROR) << "Failed to parse TLS mode from Yocto config: "
                   << tls_mode_enum.status();
      }
    }
    SyslogTargetConfig config;
    config.set_target_ip(target_ip);
    config.set_target_port(target_port);
    config.set_protocol(protocol);
    config.set_tls_mode(tls_mode);
    syslog_cert_config_ = std::move(config);
  }
}

void CredentialManagerImpl::ParseSyslogRootCert() {
  absl::StatusOr<std::string> syslog_root_cert =
      FileManager::ReadFile(params_.syslog_root_cert_path);
  if (!syslog_root_cert.ok()) {
    LOG(ERROR) << "Failed to read syslog root cert: "
               << syslog_root_cert.status()
               << ". Assuming no syslog root cert.";
    return;
  }
  syslog_root_cert_ = std::move(*syslog_root_cert);
}

CredentialManagerImpl::CredentialManagerImpl(
    const CredentialManagerParams& params)
    : params_(params), command_executor_(std::make_unique<ShellExecutor>()) {
  ParseOwnerVerificationCert();
  ParseOwnerVerificationConfiguration();
  ParseBmcSshTrustedUserCaKeys();
  ParseTrustBundleFiles();
  ParseServerCert();
  ParseOsVerificationCert();
  ParseSerialConsoleTrustedUserCAKeys();
  ParseSyslogTargetConfig();
  ParseSyslogRootCert();
}

namespace {

absl::StatusOr<bssl::UniquePtr<X509_REQ>> CreateX509Req(
    const CredentialManagerImpl::CsrParams& csr_params) {
  bssl::UniquePtr<X509_REQ> x509(X509_REQ_new());
  ECCLESIA_RETURN_IF_ERROR(ReturnErrorIfNull(
      x509.get(), absl::StrCat("X509_REQ_new failed: ", GetSslErrorOnQueue())));

  X509_NAME* subject = X509_REQ_get_subject_name(x509.get());
  ECCLESIA_RETURN_IF_ERROR(ReturnErrorIfNull(
      subject, absl::StrCat("Failed to get subject name from X509_REQ: ",
                            GetSslErrorOnQueue())));
  ECCLESIA_RETURN_IF_ERROR(AddNameEntry(subject, "C", csr_params.country));
  ECCLESIA_RETURN_IF_ERROR(AddNameEntry(subject, "ST", csr_params.state));
  ECCLESIA_RETURN_IF_ERROR(AddNameEntry(subject, "L", csr_params.city));
  ECCLESIA_RETURN_IF_ERROR(AddNameEntry(subject, "O", csr_params.organization));
  ECCLESIA_RETURN_IF_ERROR(
      AddNameEntry(subject, "OU", csr_params.organizational_unit));
  ECCLESIA_RETURN_IF_ERROR(AddNameEntry(subject, "CN", csr_params.common_name));

  if (!csr_params.alternative_names.empty()) {
    std::string san_extension;
    for (int i = 0; i < csr_params.alternative_names.size(); ++i) {
      std::string_view san = csr_params.alternative_names[i];
      absl::StrAppend(&san_extension, "DNS:", san);
      if (i < csr_params.alternative_names.size() - 1) {
        absl::StrAppend(&san_extension, ",");
      }
    }

    bssl::UniquePtr<STACK_OF(X509_EXTENSION)> extensions(
        sk_X509_EXTENSION_new_null());
    bssl::UniquePtr<X509_EXTENSION> san_ext(X509V3_EXT_conf_nid(
        nullptr, nullptr, NID_subject_alt_name, san_extension.c_str()));
    ECCLESIA_RETURN_IF_ERROR(ReturnErrorIfNull(
        san_ext.get(), absl::StrCat("Failed to create SAN extension: ",
                                    GetSslErrorOnQueue())));
    ECCLESIA_RETURN_IF_ERROR(ReturnErrorIfNotSuccess(
        sk_X509_EXTENSION_push(extensions.get(), san_ext.release()),
        absl::StrCat("Failed to add SAN extension to CSR: ",
                     GetSslErrorOnQueue())));
    ECCLESIA_RETURN_IF_ERROR(ReturnErrorIfNotSuccess(
        X509_REQ_add_extensions(x509.get(), extensions.get()),
        absl::StrCat("Failed to add extensions to CSR: ",
                     GetSslErrorOnQueue())));
  }
  return x509;
}

absl::StatusOr<std::string> GenerateCsrWithPrivateKey(
    const CredentialManagerImpl::CsrParams& csr_params, EVP_PKEY* private_key) {
  ECCLESIA_ASSIGN_OR_RETURN(bssl::UniquePtr<X509_REQ> x509,
                            CreateX509Req(csr_params));

  ECCLESIA_RETURN_IF_ERROR(ReturnErrorIfNotSuccess(
      X509_REQ_set_pubkey(x509.get(), private_key),
      absl::StrCat("Failed to set public key in CSR: ", GetSslErrorOnQueue())));

  ECCLESIA_RETURN_IF_ERROR(ReturnErrorIfNotSuccess(
      X509_REQ_sign(x509.get(), private_key, EVP_sha256()),
      absl::StrCat("Failed to sign CSR: ", GetSslErrorOnQueue())));

  bssl::UniquePtr<BIO> bio_csr(BIO_new(BIO_s_mem()));
  ECCLESIA_RETURN_IF_ERROR(ReturnErrorIfNotSuccess(
      PEM_write_bio_X509_REQ(bio_csr.get(), x509.get()),
      absl::StrCat("Failed to write CSR to BIO: ", GetSslErrorOnQueue())));
  char* csr = nullptr;
  auto csr_len = BIO_get_mem_data(bio_csr.get(), &csr);
  return std::string(csr, csr_len);
}

}  // namespace

absl::StatusOr<std::string> CredentialManagerImpl::GenerateCsr(
    const CsrParams& csr_params) {
  ECCLESIA_ASSIGN_OR_RETURN(bssl::UniquePtr<EVP_PKEY> pkey,
                            GeneratePrivateKey());
  ECCLESIA_RETURN_IF_ERROR(ReturnErrorIfNull(
      pkey.get(),
      absl::StrCat("Failed to generate private key: ", GetSslErrorOnQueue())));

  ECCLESIA_ASSIGN_OR_RETURN(std::string csr,
                            GenerateCsrWithPrivateKey(csr_params, pkey.get()));

  {
    absl::MutexLock lock(mutex_);
    private_key_ = std::move(pkey);
  }
  return csr;
}

absl::Status CredentialManagerImpl::InstallServerCert(
    std::string_view certificate) {
  absl::MutexLock lock(mutex_);
  // If GenerateCSR has not been called, we cannot install the cert.
  if (private_key_ == nullptr) {
    return absl::InternalError(
        "GenerateCSR must be called before InstallServerCert");
  }

  // 1. Load the certificate from the PEM string
  bssl::UniquePtr<BIO> bio_cert(BIO_new_mem_buf(
      certificate.data(), static_cast<uint32_t>(certificate.length())));
  bssl::UniquePtr<X509> cert(
      PEM_read_bio_X509(bio_cert.get(), nullptr, nullptr, nullptr));
  ECCLESIA_RETURN_IF_ERROR(ReturnErrorIfNull(
      cert.get(),
      absl::StrCat("Failed to parse certificate PEM: ", GetSslErrorOnQueue())));

  ECCLESIA_RETURN_IF_ERROR(ReturnErrorIfNotSuccess(
      X509_check_private_key(cert.get(), private_key_.get()),
      "Certificate does not match the private key"));

  bssl::UniquePtr<BIO> bio_privkey(BIO_new(BIO_s_mem()));
  ECCLESIA_RETURN_IF_ERROR(ReturnErrorIfNotSuccess(
      PEM_write_bio_PrivateKey(bio_privkey.get(), private_key_.get(), nullptr,
                               nullptr, 0, nullptr, nullptr),
      absl::StrCat("PEM_write_bio_PrivateKey failed: ", GetSslErrorOnQueue())));

  char* private_key = nullptr;
  auto private_key_len = BIO_get_mem_data(bio_privkey.get(), &private_key);
  std::string private_key_pem(private_key, private_key_len);

  // Install the cert and key on the machine.
  // We must do directory name change here as the key and cert have to both be
  // changed atomically
  std::string credential_dir =
      std::filesystem::path(params_.cert_path).parent_path();
  std::string cert_filename =
      std::filesystem::path(params_.cert_path).filename();
  std::string private_key_filename =
      std::filesystem::path(params_.private_key_path).filename();

  // Write to a temp dir
  std::string temp_credential_dir = absl::StrCat(credential_dir, "-tmp");
  if (params_.cert_path == params_.private_key_path) {
    // After RestartBmcwebInASeparateThread is called below that bmcweb instance
    // will attempt to read the cert and key. Since the filepaths are the same,
    // we must write both the cert and key to the same file.
    ECCLESIA_RETURN_IF_ERROR(FileManager::WriteToFile(
        absl::StrCat(certificate, "\n", private_key_pem),
        absl::StrCat(temp_credential_dir, "/", cert_filename)));
  } else {
    ECCLESIA_RETURN_IF_ERROR(FileManager::WriteToFile(
        certificate, absl::StrCat(temp_credential_dir, "/", cert_filename)));
    ECCLESIA_RETURN_IF_ERROR(FileManager::WriteToFile(
        private_key_pem,
        absl::StrCat(temp_credential_dir, "/", private_key_filename)));
  }

  // Atomically change both key and cert
  ECCLESIA_RETURN_IF_ERROR(
      FileManager::RenamePath(temp_credential_dir, credential_dir, true));

  RestartBmcwebInASeparateThread();

  return absl::OkStatus();
}

void CredentialManagerImpl::RestartBmcwebInASeparateThread() {
  std::thread([this]() {
    absl::SleepFor(absl::Seconds(kServerRestartDelaySeconds));
    absl::StatusOr<std::string> status =
        command_executor_->Execute(std::string(kRestartBmcWebCommand), false);
    if (!status.ok()) {
      LOG(ERROR) << "Failed to restart bmcweb: " << status.status();
    }
    if (restart_bmcweb_callback_ != nullptr) {
      restart_bmcweb_callback_(status.status());
    }
  }).detach();
}

absl::Status CredentialManagerImpl::InstallTrustBundle(
    std::string_view trust_bundle, std::string_view signature) {
  absl::MutexLock lock(mutex_);
  if (last_install_time_ != absl::InfinitePast() &&
      absl::Now() - last_install_time_ <
          absl::Seconds(kTrustBundleRetryDelaySeconds)) {
    std::string error_message = absl::StrFormat(
        "A trust bundle, installed at %s, is pending to be applied at %s. "
        "Retry after %s.",
        absl::FormatTime(last_install_time_),
        absl::FormatTime(last_install_time_ +
                         absl::Seconds(kServerRestartDelaySeconds)),
        absl::FormatTime(last_install_time_ +
                         absl::Seconds(kTrustBundleRetryDelaySeconds)));
    LOG(ERROR) << error_message;
    return absl::UnavailableError(error_message);
  }

  ECCLESIA_ASSIGN_OR_RETURN(StagedTempFile staged_trust_bundle,
                            VerifyAndStageTrustBundle(trust_bundle, signature));

  last_install_time_ = absl::Now();

  ECCLESIA_RETURN_IF_ERROR(
      FileManager::WriteToFile(trust_bundle, params_.trust_bundle_path));

  ECCLESIA_RETURN_IF_ERROR(
      FileManager::WriteToFile(signature, params_.trust_bundle_signature_path));

  trust_bundle_ = std::string(trust_bundle);
  trust_bundle_signature_ = std::string(signature);

  RestartBmcwebInASeparateThread();

  return absl::OkStatus();
}

absl::StatusOr<StagedTempFile> CredentialManagerImpl::VerifyAndStageTrustBundle(
    std::string_view trust_bundle, std::string_view signature) {
  ECCLESIA_ASSIGN_OR_RETURN(
      StagedTempFile trust_bundle_file,
      StagedTempFile::Create(trust_bundle, kTempTrustBundlePath));
  absl::Status status =
      VerifyAndStageCertificate(trust_bundle_file.path(), signature);
  LOG(WARNING) << "Trust bundle verify result: " << status.message();
  if (!status.ok()) {
    return absl::Status(
        status.code(), absl::StrCat("Failed to verify trust bundle signature. ",
                                    status.message()));
  }
  return trust_bundle_file;
}

absl::Status CredentialManagerImpl::VerifyAndStageCertificate(
    std::string_view cert_path, std::string_view signature) {
  std::error_code ec;
  if (!std::filesystem::exists(params_.owner_verification_cert_path, ec)) {
    return absl::FailedPreconditionError(absl::Substitute(
        "Owner certificate file does not exist or can't be accessed: $0",
        ec.message()));
  }

  ECCLESIA_ASSIGN_OR_RETURN(
      StagedTempFile signature_file,
      StagedTempFile::Create(signature, kTempSignaturePath));
  std::string command =
      absl::StrFormat(kTrustBundleVerifyWithCaCommand, signature_file.path(),
                      cert_path, params_.owner_verification_cert_path);

  return command_executor_->Execute(command, false).status();
}

absl::Status CredentialManagerImpl::InstallOsVerificationCertificate(
    std::string_view cert_string) {
  // Verify the OS verification certificate
  ECCLESIA_RETURN_IF_ERROR(VerifyOsVerificationCertificate(cert_string));
  // Parse the public key
  ECCLESIA_ASSIGN_OR_RETURN(std::string public_key,
                            ecclesia::GetPublicKey(cert_string));

  // Write the cert itself to a file
  ECCLESIA_RETURN_IF_ERROR(
      FileManager::WriteToFile(cert_string, params_.os_verification_cert_path));

  // Write the public key to a file
  ECCLESIA_RETURN_IF_ERROR(
      FileManager::WriteToFile(public_key, params_.os_verification_key_path));

  os_verification_cert_ = std::string(cert_string);

  return absl::OkStatus();
}

absl::Status CredentialManagerImpl::VerifyOsVerificationCertificate(
    std::string_view cert_string) {
  absl::MutexLock lock(mutex_);
  std::error_code ec;
  if (!std::filesystem::exists(params_.owner_verification_cert_path, ec)) {
    return absl::FailedPreconditionError(absl::Substitute(
        "Owner certificate file does not exist or can't be accessed: $0",
        ec.message()));
  }
  ECCLESIA_ASSIGN_OR_RETURN(
      StagedTempFile os_cert_file,
      StagedTempFile::Create(cert_string, kTempOsCertPath));
  std::string command = absl::StrFormat(kOsCertVerifyCommand,
                                        params_.owner_verification_cert_path,
                                        os_cert_file.path());
  absl::Status status = command_executor_->Execute(command, false).status();

  if (!status.ok()) {
    return absl::Status(
        status.code(),
        absl::StrCat("Failed to verify OS verification certificate. ",
                     status.message()));
  }
  return absl::OkStatus();
}

absl::Status
CredentialManagerImpl::VerifyAndStageSerialConsoleTrustedUserCAKeys(
    std::string_view trusted_user_ca_keys, std::string_view signature) {
  ECCLESIA_ASSIGN_OR_RETURN(
      StagedTempFile trusted_user_ca_keys_file,
      StagedTempFile::Create(trusted_user_ca_keys, kTempTrustedUserCAKeysPath));
  absl::Status status =
      VerifyAndStageCertificate(trusted_user_ca_keys_file.path(), signature);
  LOG(WARNING) << "Trusted user CA keys verify result: " << status.message();
  if (!status.ok()) {
    return absl::Status(
        status.code(),
        absl::StrCat("Failed to verify trusted user CA keys signature. ",
                     status.message()));
  }
  return absl::OkStatus();
}

absl::Status CredentialManagerImpl::InstallSerialConsoleTrustedUserCAKeys(
    std::string_view trusted_user_ca_keys, std::string_view signature) {
  absl::MutexLock lock(mutex_);
  ECCLESIA_RETURN_IF_ERROR(VerifyAndStageSerialConsoleTrustedUserCAKeys(
      trusted_user_ca_keys, signature));
  ECCLESIA_RETURN_IF_ERROR(FileManager::WriteToFile(
      trusted_user_ca_keys, params_.serial_console_trusted_user_ca_keys_path));
  ECCLESIA_RETURN_IF_ERROR(FileManager::WriteToFile(
      signature, params_.serial_console_detatched_signature_path));
  serial_console_trusted_user_ca_keys_ = std::string(trusted_user_ca_keys);
  serial_console_detatched_signature_ = std::string(signature);
  return absl::OkStatus();
}

absl::Status CredentialManagerImpl::InstallSyslogCert(
    std::string_view cert_string, std::string_view target_ip,
    int64_t target_port, SyslogProtocol protocol, SyslogTlsMode tls_mode) {
  absl::MutexLock lock(mutex_);
  std::optional<SyslogTargetConfig> config_orig = syslog_cert_config_;

  if (target_ip.empty() && (target_port > 0) && (target_port <= 65535)) {
    return absl::InvalidArgumentError("Target IP is empty.");
  }
  if (!target_ip.empty() && ((target_port <= 0) || (target_port > 65535))) {
    return absl::InvalidArgumentError("Target port is empty.");
  }

  if (protocol == SYSLOG_PROTOCOL_UDP && tls_mode != SYSLOG_TLS_MODE_DISABLED) {
    return absl::InvalidArgumentError(
        "TLS is not supported when protocol is UDP.");
  }

  if (!target_ip.empty() && (target_port != 0)) {
    SyslogTargetConfig new_config;
    new_config.set_target_ip(target_ip);
    new_config.set_target_port(target_port);
    new_config.set_protocol(protocol);
    new_config.set_tls_mode(tls_mode);
    std::string override_content = GetSyslogOverrideContent(new_config);

    ECCLESIA_RETURN_IF_ERROR(FileManager::WriteToFile(
        override_content, params_.syslog_client_conf_override_path));
    syslog_cert_config_ = std::move(new_config);
  }

  absl::Status status =
      FileManager::WriteToFile(cert_string, params_.syslog_root_cert_path);
  if (!status.ok()) {
    // If cert file write fails, revert client conf override file.
    if (config_orig.has_value()) {
      absl::Status revert_status;
      revert_status =
          FileManager::WriteToFile(GetSyslogOverrideContent(*config_orig),
                                   params_.syslog_client_conf_override_path);
      if (!revert_status.ok()) {
        LOG(ERROR) << "Failed to revert client conf override file: "
                   << revert_status;
      }
      syslog_cert_config_ = std::move(config_orig);
    }
    return status;
  }
  syslog_root_cert_ = std::string(cert_string);
  return absl::OkStatus();
}

}  // namespace milotic_tlbmc
