#ifndef THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_CERTIFICATE_SERVICE_H_
#define THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_CERTIFICATE_SERVICE_H_

#include <array>
#include <chrono>  // NOLINT
#include <cstddef>
#include <cstdint>
#include <filesystem>  // NOLINT
#include <fstream>
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <system_error>  // NOLINT
#include <utility>
#include <vector>

#include "boost/system/linux_error.hpp"  // NOLINT
#include "app.hpp"
#include "http_request.hpp"
#include "http_response.hpp"
#include "logging.hpp"
#include "parsing.hpp"
#include "utility.hpp"
#include "async_resp.hpp"
#include "dbus_utility.hpp"
#include "error_messages.hpp"
#include "privileges.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "collection.hpp"
#include "dbus_utils.hpp"
#include "json_utils.hpp"
#include "time_utils.hpp"
#include <nlohmann/json.hpp>
#include "managed_store.hpp"
#include "managed_store_types.hpp"
#include "sdbusplus/message.hpp"
#include "sdbusplus/message/native_types.hpp"
#include "sdbusplus/bus/match.hpp"
#include "sdbusplus/unpack_properties.hpp"

#ifdef UNIT_TEST_BUILD
#include "test/g3/mock_managed_store.hpp"  // NOLINT
#endif

namespace redfish {
namespace certs {
constexpr char const* certInstallIntf = "xyz.openbmc_project.Certs.Install";
constexpr char const* certReplaceIntf = "xyz.openbmc_project.Certs.Replace";
constexpr char const* objDeleteIntf = "xyz.openbmc_project.Object.Delete";
constexpr char const* certPropIntf = "xyz.openbmc_project.Certs.Certificate";
constexpr char const* dbusPropIntf = "org.freedesktop.DBus.Properties";
constexpr char const* dbusObjManagerIntf = "org.freedesktop.DBus.ObjectManager";
constexpr char const* httpsServiceName =
    "xyz.openbmc_project.Certs.Manager.Server.Https";
constexpr char const* ldapServiceName =
    "xyz.openbmc_project.Certs.Manager.Client.Ldap";
constexpr char const* authorityServiceName =
    "xyz.openbmc_project.Certs.Manager.Authority.Ldap";
constexpr char const* baseObjectPath = "/xyz/openbmc_project/certs";
constexpr char const* httpsObjectPath =
    "/xyz/openbmc_project/certs/server/https";
constexpr char const* ldapObjectPath = "/xyz/openbmc_project/certs/client/ldap";
constexpr char const* authorityObjectPath =
    "/xyz/openbmc_project/certs/authority/ldap";
constexpr char const* chassisObjectPath = "/xyz/openbmc_project/certs/chassis";
}  // namespace certs

/**
 * The Certificate schema defines a Certificate Service which represents the
 * actions available to manage certificates and links to where certificates
 * are installed.
 */

inline std::string getCertificateFromReqBody(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const crow::Request& req) {
  nlohmann::json reqJson;
  JsonParseResult ret = parseRequestAsJson(req, reqJson);
  if (ret != JsonParseResult::Success) {
    // We did not receive JSON request, proceed as it is RAW data
    return req.body();
  }

  std::string certificate;
  std::optional<std::string> certificateType = "PEM";

  if (!json_util::readJsonPatch(req, asyncResp->res, "CertificateString",
                                certificate, "CertificateType",
                                certificateType)) {
    BMCWEB_LOG_ERROR << "Required parameters are missing";
    messages::internalError(asyncResp->res);
    return {};
  }

  if (*certificateType != "PEM") {
    messages::propertyValueNotInList(asyncResp->res, *certificateType,
                                     "CertificateType");
    return {};
  }

  return certificate;
}

/**
 * Class to create a temporary certificate file for uploading to system
 */
class CertificateFile {
 public:
  CertificateFile() = delete;
  CertificateFile(const CertificateFile&) = delete;
  CertificateFile& operator=(const CertificateFile&) = delete;
  CertificateFile(CertificateFile&&) = delete;
  CertificateFile& operator=(CertificateFile&&) = delete;
  explicit CertificateFile(const std::string& certString) {
    std::array<char, 18> dirTemplate = {'/', 't', 'm', 'p', '/', 'C',
                                        'e', 'r', 't', 's', '.', 'X',
                                        'X', 'X', 'X', 'X', 'X', '\0'};
    char* tempDirectory = mkdtemp(dirTemplate.data());
    if (tempDirectory != nullptr) {
      certDirectory = tempDirectory;
      certificateFile = certDirectory / "cert.pem";
      std::ofstream out(certificateFile, std::ofstream::out |
                                             std::ofstream::binary |
                                             std::ofstream::trunc);
      out << certString;
      out.close();
      BMCWEB_LOG_DEBUG << "Creating certificate file"
                       << certificateFile.string();
    }
  }
  ~CertificateFile() {
    if (std::filesystem::exists(certDirectory)) {
      BMCWEB_LOG_DEBUG << "Removing certificate file"
                       << certificateFile.string();
      std::error_code ec;
      std::filesystem::remove_all(certDirectory, ec);
      if (ec) {
        BMCWEB_LOG_ERROR << "Failed to remove temp directory"
                         << certDirectory.string();
      }
    }
  }
  std::string getCertFilePath() { return certificateFile; }

 private:
  std::filesystem::path certificateFile;
  std::filesystem::path certDirectory;
};

/**
 * @brief Parse and update Certificate Issue/Subject property
 *
 * @param[in] asyncResp Shared pointer to the response message
 * @param[in] str  Issuer/Subject value in key=value pairs
 * @param[in] type Issuer/Subject
 * @return None
 */
static void updateCertIssuerOrSubject(nlohmann::json& out,
                                      std::string_view value) {
  // example: O=openbmc-project.xyz,CN=localhost
  std::string_view::iterator i = value.begin();
  while (i != value.end()) {
    std::string_view::iterator tokenBegin = i;
    while (i != value.end() && *i != '=') {
      ++i;
    }
    if (i == value.end()) {
      break;
    }
    std::string_view key(tokenBegin, static_cast<size_t>(i - tokenBegin));
    ++i;
    tokenBegin = i;
    while (i != value.end() && *i != ',') {
      ++i;
    }
    std::string_view val(tokenBegin, static_cast<size_t>(i - tokenBegin));
    if (key == "L") {
      out["City"] = val;
    } else if (key == "CN") {
      out["CommonName"] = val;
    } else if (key == "C") {
      out["Country"] = val;
    } else if (key == "O") {
      out["Organization"] = val;
    } else if (key == "OU") {
      out["OrganizationalUnit"] = val;
    } else if (key == "ST") {
      out["State"] = val;
    }
    // skip comma character
    if (i != value.end()) {
      ++i;
    }
  }
}

/**
 * @brief Retrieve the installed certificate list
 *
 * @param[in] asyncResp Shared pointer to the response message
 * @param[in] basePath DBus object path to search
 * @param[in] listPtr Json pointer to the list in asyncResp
 * @param[in] countPtr Json pointer to the count in asyncResp
 * @return None
 */
static void getCertificateList(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& basePath, const nlohmann::json::json_pointer& listPtr,
    const nlohmann::json::json_pointer& countPtr) {
  constexpr std::array<std::string_view, 1> interfaces = {certs::certPropIntf};
  managedStore::ManagedObjectStoreContext requestContext(asyncResp);
  managedStore::GetManagedObjectStore()->getSubTreePaths(
      basePath, 0, interfaces, requestContext,
      [asyncResp, listPtr, countPtr](
          const boost::system::error_code& ec,
          const dbus::utility::MapperGetSubTreePathsResponse& certPaths) {
        if (ec) {
          BMCWEB_LOG_ERROR << "Certificate collection query failed: " << ec;
          messages::internalError(asyncResp->res);
          return;
        }

        nlohmann::json& links = asyncResp->res.jsonValue[listPtr];
        links = nlohmann::json::array();
        for (const auto& certPath : certPaths) {
          sdbusplus::message::object_path objPath(certPath);
          std::string certId = objPath.filename();
          if (certId.empty()) {
            BMCWEB_LOG_ERROR << "Invalid certificate objPath " << certPath;
            continue;
          }

          boost::urls::url certURL;
          if (objPath.parent_path() == certs::httpsObjectPath) {
            certURL = crow::utility::urlFromPieces(
                "redfish", "v1", "Managers", "bmc", "NetworkProtocol", "HTTPS",
                "Certificates", certId);
          } else if (objPath.parent_path() == certs::ldapObjectPath) {
            certURL =
                crow::utility::urlFromPieces("redfish", "v1", "AccountService",
                                             "LDAP", "Certificates", certId);
          } else if (objPath.parent_path() == certs::authorityObjectPath) {
            certURL = crow::utility::urlFromPieces("redfish", "v1", "Managers",
                                                   "bmc", "Truststore",
                                                   "Certificates", certId);
          } else {
            continue;
          }

          nlohmann::json::object_t link;
          link["@odata.id"] = certURL;
          links.emplace_back(std::move(link));
        }

        asyncResp->res.jsonValue[countPtr] = links.size();
      });
}

/**
 * @brief Retrieve the certificates properties and append to the response
 * message
 *
 * @param[in] asyncResp Shared pointer to the response message
 * @param[in] objectPath  Path of the D-Bus service object
 * @param[in] certId  Id of the certificate
 * @param[in] certURL  URL of the certificate object
 * @param[in] name  name of the certificate
 * @return None
 */
static void getCertificateProperties(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& objectPath, const std::string& service,
    const std::string& certId, const boost::urls::url& certURL,
    const std::string& name) {
  BMCWEB_LOG_DEBUG << "getCertificateProperties Path=" << objectPath
                   << " certId=" << certId << " certURl=" << certURL;
  managedStore::ManagedObjectStoreContext context(asyncResp);
  managedStore::GetManagedObjectStore()->getAllProperties(
      service, objectPath, certs::certPropIntf, context,
      [asyncResp, certURL, certId, name](
          const boost::system::error_code& ec,
          const dbus::utility::DBusPropertiesMap& properties) {
        if (ec) {
          BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
          messages::resourceNotFound(asyncResp->res, "Certificate", certId);
          return;
        }

        const std::string* certificateString = nullptr;
        const std::vector<std::string>* keyUsage = nullptr;
        const std::string* issuer = nullptr;
        const std::string* subject = nullptr;
        const uint64_t* validNotAfter = nullptr;
        const uint64_t* validNotBefore = nullptr;

        const bool success = sdbusplus::unpackPropertiesNoThrow(
            dbus_utils::UnpackErrorPrinter(), properties, "CertificateString",
            certificateString, "KeyUsage", keyUsage, "Issuer", issuer,
            "Subject", subject, "ValidNotAfter", validNotAfter,
            "ValidNotBefore", validNotBefore);

        if (!success) {
          messages::internalError(asyncResp->res);
          return;
        }

        asyncResp->res.jsonValue["@odata.id"] = certURL;
        asyncResp->res.jsonValue["@odata.type"] =
            "#Certificate.v1_0_0.Certificate";
        asyncResp->res.jsonValue["Id"] = certId;
        asyncResp->res.jsonValue["Name"] = name;
        asyncResp->res.jsonValue["Description"] = name;
        asyncResp->res.jsonValue["CertificateString"] = "";
        asyncResp->res.jsonValue["KeyUsage"] = nlohmann::json::array();

        if (certificateString != nullptr) {
          asyncResp->res.jsonValue["CertificateString"] = *certificateString;
        }

        if (keyUsage != nullptr) {
          asyncResp->res.jsonValue["KeyUsage"] = *keyUsage;
        }

        if (issuer != nullptr) {
          updateCertIssuerOrSubject(asyncResp->res.jsonValue["Issuer"],
                                    *issuer);
        }

        if (subject != nullptr) {
          updateCertIssuerOrSubject(asyncResp->res.jsonValue["Subject"],
                                    *subject);
        }

        if (validNotAfter != nullptr) {
          asyncResp->res.jsonValue["ValidNotAfter"] =
              redfish::time_utils::getDateTimeUint(*validNotAfter);
        }

        if (validNotBefore != nullptr) {
          asyncResp->res.jsonValue["ValidNotBefore"] =
              redfish::time_utils::getDateTimeUint(*validNotBefore);
        }

        asyncResp->res.addHeader(
            boost::beast::http::field::location,
            std::string_view(certURL.data(), certURL.size()));
      });
}

static void deleteCertificate(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& service,
    const sdbusplus::message::object_path& objectPath) {
  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      asyncResp->strand_,
      [asyncResp,
       id{objectPath.filename()}](const boost::system::error_code& ec) {
        if (ec) {
          messages::resourceNotFound(asyncResp->res, "Certificate", id);
          return;
        }
        BMCWEB_LOG_INFO << "Certificate deleted";
        asyncResp->res.result(boost::beast::http::status::no_content);
      },
      service, objectPath, certs::objDeleteIntf, "Delete");
}

inline void handleCertificateServiceGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  asyncResp->res.jsonValue["@odata.type"] =
      "#CertificateService.v1_0_0.CertificateService";
  asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/CertificateService";
  asyncResp->res.jsonValue["Id"] = "CertificateService";
  asyncResp->res.jsonValue["Name"] = "Certificate Service";
  asyncResp->res.jsonValue["Description"] =
      "Actions available to manage certificates";
  // /redfish/v1/CertificateService/CertificateLocations is something
  // only ConfigureManager can access then only display when the user
  // has permissions ConfigureManager
  Privileges effectiveUserPrivileges = redfish::getUserPrivileges(req.userRole);
  if (isOperationAllowedWithPrivileges({{"ConfigureManager"}},
                                       effectiveUserPrivileges)) {
    asyncResp->res.jsonValue["CertificateLocations"]["@odata.id"] =
        "/redfish/v1/CertificateService/CertificateLocations";
  }
  nlohmann::json& actions = asyncResp->res.jsonValue["Actions"];
  nlohmann::json& replace = actions["#CertificateService.ReplaceCertificate"];
  replace["target"] =
      "/redfish/v1/CertificateService/Actions/"
      "CertificateService.ReplaceCertificate";
  nlohmann::json::array_t allowed;
  allowed.emplace_back("PEM");
  replace["CertificateType@Redfish.AllowableValues"] = std::move(allowed);
  actions["#CertificateService.GenerateCSR"]["target"] =
      "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR";
}

inline void handleCertificateLocationsGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  asyncResp->res.jsonValue["@odata.id"] =
      "/redfish/v1/CertificateService/CertificateLocations";
  asyncResp->res.jsonValue["@odata.type"] =
      "#CertificateLocations.v1_0_0.CertificateLocations";
  asyncResp->res.jsonValue["Name"] = "Certificate Locations";
  asyncResp->res.jsonValue["Id"] = "CertificateLocations";
  asyncResp->res.jsonValue["Description"] =
      "Defines a resource that an administrator can use in order to "
      "locate all certificates installed on a given service";

  getCertificateList(asyncResp, certs::baseObjectPath,
                     "/Links/Certificates"_json_pointer,
                     "/Links/Certificates@odata.count"_json_pointer);
}

inline void handleReplaceCertificateAction(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  std::string certificate;
  nlohmann::json certificateUri;
  std::optional<std::string> certificateType = "PEM";

  if (!json_util::readJsonAction(req, asyncResp->res, "CertificateString",
                                 certificate, "CertificateUri", certificateUri,
                                 "CertificateType", certificateType)) {
    BMCWEB_LOG_ERROR << "Required parameters are missing";
    messages::internalError(asyncResp->res);
    return;
  }

  if (!certificateType) {
    // should never happen, but it never hurts to be paranoid.
    return;
  }
  if (certificateType != "PEM") {
    messages::actionParameterNotSupported(asyncResp->res, "CertificateType",
                                          "ReplaceCertificate");
    return;
  }

  std::string certURI;
  if (!redfish::json_util::readJson(certificateUri, asyncResp->res, "@odata.id",
                                    certURI)) {
    messages::actionParameterMissing(asyncResp->res, "ReplaceCertificate",
                                     "CertificateUri");
    return;
  }
  BMCWEB_LOG_INFO << "Certificate URI to replace: " << certURI;

  auto parsedUrl = boost::urls::parse_relative_ref(certURI);
  if (!parsedUrl) {
    messages::actionParameterValueFormatError(
        asyncResp->res, certURI, "CertificateUri", "ReplaceCertificate");
    return;
  }

  std::string id;
  sdbusplus::message::object_path objectPath;
  std::string name;
  std::string service;
  if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1", "Managers",
                                     "bmc", "NetworkProtocol", "HTTPS",
                                     "Certificates", std::ref(id))) {
    objectPath = sdbusplus::message::object_path(certs::httpsObjectPath) / id;
    name = "HTTPS certificate";
    service = certs::httpsServiceName;
  } else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1",
                                            "AccountService", "LDAP",
                                            "Certificates", std::ref(id))) {
    objectPath = sdbusplus::message::object_path(certs::ldapObjectPath) / id;
    name = "LDAP certificate";
    service = certs::ldapServiceName;
  } else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1",
                                            "Managers", "bmc", "Truststore",
                                            "Certificates", std::ref(id))) {
    objectPath =
        sdbusplus::message::object_path(certs::authorityObjectPath) / id;
    name = "TrustStore certificate";
    service = certs::authorityServiceName;
  } else {
    messages::actionParameterNotSupported(asyncResp->res, "CertificateUri",
                                          "ReplaceCertificate");
    return;
  }

  std::shared_ptr<CertificateFile> certFile =
      std::make_shared<CertificateFile>(certificate);
  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      asyncResp->strand_,
      [asyncResp, certFile, objectPath, service, url{*parsedUrl}, id,
       name](const boost::system::error_code& ec) {
        if (ec) {
          BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
          if (ec.value() ==
              boost::system::linux_error::bad_request_descriptor) {
            messages::resourceNotFound(asyncResp->res, "Certificate", id);
            return;
          }
          messages::internalError(asyncResp->res);
          return;
        }
        getCertificateProperties(asyncResp, objectPath, service, id, url, name);
        BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
                         << certFile->getCertFilePath();
      },
      service, objectPath, certs::certReplaceIntf, "Replace",
      certFile->getCertFilePath());
}

// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
static std::unique_ptr<sdbusplus::bus::match_t> csrMatcher;
/**
 * @brief Read data from CSR D-bus object and set to response
 *
 * @param[in] asyncResp Shared pointer to the response message
 * @param[in] certURI Link to certifiate collection URI
 * @param[in] service D-Bus service name
 * @param[in] certObjPath certificate D-Bus object path
 * @param[in] csrObjPath CSR D-Bus object path
 * @return None
 */
static void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                   const std::string& certURI, const std::string& service,
                   const std::string& certObjPath,
                   const std::string& csrObjPath) {
  BMCWEB_LOG_DEBUG << "getCSR CertObjectPath" << certObjPath
                   << " CSRObjectPath=" << csrObjPath << " service=" << service;
  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      asyncResp->strand_,
      [asyncResp, certURI](const boost::system::error_code& ec,
                           const std::string& csr) {
        if (ec) {
          BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
          messages::internalError(asyncResp->res);
          return;
        }
        if (csr.empty()) {
          BMCWEB_LOG_ERROR << "CSR read is empty";
          messages::internalError(asyncResp->res);
          return;
        }
        asyncResp->res.jsonValue["CSRString"] = csr;
        asyncResp->res.jsonValue["CertificateCollection"]["@odata.id"] =
            certURI;
      },
      service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR");
}

inline void handleGenerateCSRAction(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  static const int rsaKeyBitLength = 2048;

  // Required parameters
  std::string city;
  std::string commonName;
  std::string country;
  std::string organization;
  std::string organizationalUnit;
  std::string state;
  nlohmann::json certificateCollection;

  // Optional parameters
  std::optional<std::vector<std::string>> optAlternativeNames =
      std::vector<std::string>();
  std::optional<std::string> optContactPerson = "";
  std::optional<std::string> optChallengePassword = "";
  std::optional<std::string> optEmail = "";
  std::optional<std::string> optGivenName = "";
  std::optional<std::string> optInitials = "";
  std::optional<int64_t> optKeyBitLength = rsaKeyBitLength;
  std::optional<std::string> optKeyCurveId = "secp384r1";
  std::optional<std::string> optKeyPairAlgorithm = "EC";
  std::optional<std::vector<std::string>> optKeyUsage =
      std::vector<std::string>();
  std::optional<std::string> optSurname = "";
  std::optional<std::string> optUnstructuredName = "";
  if (!json_util::readJsonAction(
          req, asyncResp->res, "City", city, "CommonName", commonName,
          "ContactPerson", optContactPerson, "Country", country, "Organization",
          organization, "OrganizationalUnit", organizationalUnit, "State",
          state, "CertificateCollection", certificateCollection,
          "AlternativeNames", optAlternativeNames, "ChallengePassword",
          optChallengePassword, "Email", optEmail, "GivenName", optGivenName,
          "Initials", optInitials, "KeyBitLength", optKeyBitLength,
          "KeyCurveId", optKeyCurveId, "KeyPairAlgorithm", optKeyPairAlgorithm,
          "KeyUsage", optKeyUsage, "Surname", optSurname, "UnstructuredName",
          optUnstructuredName)) {
    return;
  }

  // bmcweb has no way to store or decode a private key challenge
  // password, which will likely cause bmcweb to crash on startup
  // if this is not set on a post so not allowing the user to set
  // value
  if (!optChallengePassword->empty()) {
    messages::actionParameterNotSupported(asyncResp->res, "GenerateCSR",
                                          "ChallengePassword");
    return;
  }

  std::string certURI;
  if (!redfish::json_util::readJson(certificateCollection, asyncResp->res,
                                    "@odata.id", certURI)) {
    return;
  }

  std::string objectPath;
  std::string service;
  if (certURI.starts_with(
          "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) {
    objectPath = certs::httpsObjectPath;
    service = certs::httpsServiceName;
  } else if (certURI.starts_with(
                 "/redfish/v1/AccountService/LDAP/Certificates")) {
    objectPath = certs::ldapObjectPath;
    service = certs::ldapServiceName;
  } else {
    messages::actionParameterNotSupported(
        asyncResp->res, "CertificateCollection", "GenerateCSR");
    return;
  }

  // supporting only EC and RSA algorithm
  if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA") {
    messages::actionParameterNotSupported(asyncResp->res, "KeyPairAlgorithm",
                                          "GenerateCSR");
    return;
  }

  // supporting only 2048 key bit length for RSA algorithm due to
  // time consumed in generating private key
  if (*optKeyPairAlgorithm == "RSA" && *optKeyBitLength != rsaKeyBitLength) {
    messages::propertyValueNotInList(
        asyncResp->res, std::to_string(*optKeyBitLength), "KeyBitLength");
    return;
  }

  // validate KeyUsage supporting only 1 type based on URL
  if (certURI.starts_with(
          "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) {
    if (optKeyUsage->empty()) {
      optKeyUsage->emplace_back("ServerAuthentication");
    } else if (optKeyUsage->size() == 1) {
      if ((*optKeyUsage)[0] != "ServerAuthentication") {
        messages::propertyValueNotInList(asyncResp->res, (*optKeyUsage)[0],
                                         "KeyUsage");
        return;
      }
    } else {
      messages::actionParameterNotSupported(asyncResp->res, "KeyUsage",
                                            "GenerateCSR");
      return;
    }
  } else if (certURI.starts_with(
                 "/redfish/v1/AccountService/LDAP/Certificates")) {
    if (optKeyUsage->empty()) {
      optKeyUsage->emplace_back("ClientAuthentication");
    } else if (optKeyUsage->size() == 1) {
      if ((*optKeyUsage)[0] != "ClientAuthentication") {
        messages::propertyValueNotInList(asyncResp->res, (*optKeyUsage)[0],
                                         "KeyUsage");
        return;
      }
    } else {
      messages::actionParameterNotSupported(asyncResp->res, "KeyUsage",
                                            "GenerateCSR");
      return;
    }
  }

  // Only allow one CSR matcher at a time so setting retry
  // time-out and timer expiry to 10 seconds for now.
  static const int timeOut = 10;
  if (csrMatcher) {
    messages::serviceTemporarilyUnavailable(asyncResp->res,
                                            std::to_string(timeOut));
    return;
  }

  // Make this static so it survives outside this method
  static boost::asio::steady_timer timeout(*req.ioService);
  timeout.expires_after(std::chrono::seconds(timeOut));
  timeout.async_wait([asyncResp](const boost::system::error_code& ec) {
    csrMatcher = nullptr;
    if (ec) {
      // operation_aborted is expected if timer is canceled
      // before completion.
      if (ec != boost::asio::error::operation_aborted) {
        BMCWEB_LOG_ERROR << "Async_wait failed " << ec;
      }
      return;
    }
    BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR";
    messages::internalError(asyncResp->res);
  });

  // create a matcher to wait on CSR object
  BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath;
  std::string match(
      "type='signal',"
      "interface='org.freedesktop.DBus.ObjectManager',"
      "path='" +
      objectPath +
      "',"
      "member='InterfacesAdded'");
  csrMatcher = std::make_unique<sdbusplus::bus::match_t>(
      *(managedStore::GetManagedObjectStore()
            ->GetDeprecatedThreadUnsafeSystemBus()),
      match,
      [asyncResp, service, objectPath, certURI](sdbusplus::message_t& m) {
        timeout.cancel();
        if (m.is_method_error()) {
          BMCWEB_LOG_ERROR << "Dbus method error!!!";
          messages::internalError(asyncResp->res);
          return;
        }

        dbus::utility::DBusInteracesMap interfacesProperties;

        sdbusplus::message::object_path csrObjectPath;
        m.read(csrObjectPath, interfacesProperties);
        BMCWEB_LOG_DEBUG << "CSR object added" << csrObjectPath.str;
        for (const auto& interface : interfacesProperties) {
          if (interface.first == "xyz.openbmc_project.Certs.CSR") {
            getCSR(asyncResp, certURI, service, objectPath, csrObjectPath.str);
            break;
          }
        }
      });
#ifndef UNIT_TEST_BUILD
  // Mocking this seems to break
  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      asyncResp->strand_,
      [asyncResp](const boost::system::error_code& ec, const std::string&) {
        if (ec) {
          BMCWEB_LOG_ERROR << "DBUS response error: " << ec.message();
          messages::internalError(asyncResp->res);
          return;
        }
      },
      service, objectPath, "xyz.openbmc_project.Certs.CSR.Create",
      "GenerateCSR", *optAlternativeNames, *optChallengePassword, city,
      commonName, *optContactPerson, country, *optEmail, *optGivenName,
      *optInitials, *optKeyBitLength, *optKeyCurveId, *optKeyPairAlgorithm,
      *optKeyUsage, organization, organizationalUnit, state, *optSurname,
      *optUnstructuredName);
#endif
}

inline void requestRoutesCertificateService(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/")
      .privileges(redfish::privileges::getCertificateService)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleCertificateServiceGet, std::ref(app)));

  BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/")
      .privileges(redfish::privileges::getCertificateLocations)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleCertificateLocationsGet, std::ref(app)));

  BMCWEB_ROUTE(app,
               "/redfish/v1/CertificateService/Actions/"
               "CertificateService.ReplaceCertificate/")
      .privileges(redfish::privileges::postCertificateService)
      .methods(boost::beast::http::verb::post)(
          std::bind_front(handleReplaceCertificateAction, std::ref(app)));

  BMCWEB_ROUTE(app,
               "/redfish/v1/CertificateService/Actions/"
               "CertificateService.GenerateCSR/")
      .privileges(redfish::privileges::postCertificateService)
      .methods(boost::beast::http::verb::post)(
          std::bind_front(handleGenerateCSRAction, std::ref(app)));
}  // requestRoutesCertificateService

inline void handleHTTPSCertificateCollectionGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  asyncResp->res.jsonValue["@odata.id"] =
      "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates";
  asyncResp->res.jsonValue["@odata.type"] =
      "#CertificateCollection.CertificateCollection";
  asyncResp->res.jsonValue["Name"] = "HTTPS Certificates Collection";
  asyncResp->res.jsonValue["Description"] =
      "A Collection of HTTPS certificate instances";

  getCertificateList(asyncResp, certs::httpsObjectPath, "/Members"_json_pointer,
                     "/Members@odata.count"_json_pointer);
}

inline void handleHTTPSCertificateCollectionPost(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost";

  asyncResp->res.jsonValue["Name"] = "HTTPS Certificate";
  asyncResp->res.jsonValue["Description"] = "HTTPS Certificate";

  std::string certFileBody = getCertificateFromReqBody(asyncResp, req);

  if (certFileBody.empty()) {
    BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
    messages::unrecognizedRequestBody(asyncResp->res);
    return;
  }

  std::shared_ptr<CertificateFile> certFile =
      std::make_shared<CertificateFile>(certFileBody);

  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      asyncResp->strand_,
      [asyncResp, certFile](const boost::system::error_code& ec,
                            const std::string& objectPath) {
        if (ec) {
          BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
          messages::internalError(asyncResp->res);
          return;
        }

        sdbusplus::message::object_path path(objectPath);
        std::string certId = path.filename();
        const boost::urls::url certURL = crow::utility::urlFromPieces(
            "redfish", "v1", "Managers", "bmc", "NetworkProtocol", "HTTPS",
            "Certificates", certId);
        getCertificateProperties(asyncResp, objectPath, certs::httpsServiceName,
                                 certId, certURL, "HTTPS Certificate");
        BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
                         << certFile->getCertFilePath();
      },
      certs::httpsServiceName, certs::httpsObjectPath, certs::certInstallIntf,
      "Install", certFile->getCertFilePath());
}

inline void handleHTTPSCertificateGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& id) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  BMCWEB_LOG_DEBUG << "HTTPS Certificate ID=" << id;
  const boost::urls::url certURL = crow::utility::urlFromPieces(
      "redfish", "v1", "Managers", "bmc", "NetworkProtocol", "HTTPS",
      "Certificates", id);
  std::string objPath =
      sdbusplus::message::object_path(certs::httpsObjectPath) / id;
  getCertificateProperties(asyncResp, objPath, certs::httpsServiceName, id,
                           certURL, "HTTPS Certificate");
}

inline void requestRoutesHTTPSCertificate(App& app) {
  BMCWEB_ROUTE(app,
               "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
      .privileges(redfish::privileges::getCertificateCollection)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleHTTPSCertificateCollectionGet, std::ref(app)));

  BMCWEB_ROUTE(app,
               "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
      .privileges(redfish::privileges::postCertificateCollection)
      .methods(boost::beast::http::verb::post)(
          std::bind_front(handleHTTPSCertificateCollectionPost, std::ref(app)));

  BMCWEB_ROUTE(
      app, "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/<str>/")
      .privileges(redfish::privileges::getCertificate)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleHTTPSCertificateGet, std::ref(app)));
}

inline void handleLDAPCertificateCollectionGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  asyncResp->res.jsonValue["@odata.id"] =
      "/redfish/v1/AccountService/LDAP/Certificates";
  asyncResp->res.jsonValue["@odata.type"] =
      "#CertificateCollection.CertificateCollection";
  asyncResp->res.jsonValue["Name"] = "LDAP Certificates Collection";
  asyncResp->res.jsonValue["Description"] =
      "A Collection of LDAP certificate instances";

  getCertificateList(asyncResp, certs::ldapObjectPath, "/Members"_json_pointer,
                     "/Members@odata.count"_json_pointer);
}

inline void handleLDAPCertificateCollectionPost(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  std::string certFileBody = getCertificateFromReqBody(asyncResp, req);

  if (certFileBody.empty()) {
    BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
    messages::unrecognizedRequestBody(asyncResp->res);
    return;
  }

  std::shared_ptr<CertificateFile> certFile =
      std::make_shared<CertificateFile>(certFileBody);

  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      asyncResp->strand_,
      [asyncResp, certFile](const boost::system::error_code& ec,
                            const std::string& objectPath) {
        if (ec) {
          BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
          messages::internalError(asyncResp->res);
          return;
        }

        sdbusplus::message::object_path path(objectPath);
        std::string certId = path.filename();
        const boost::urls::url certURL = crow::utility::urlFromPieces(
            "redfish", "v1", "AccountService", "LDAP", "Certificates", certId);
        getCertificateProperties(asyncResp, objectPath, certs::ldapServiceName,
                                 certId, certURL, "LDAP Certificate");
        BMCWEB_LOG_DEBUG << "LDAP certificate install file="
                         << certFile->getCertFilePath();
      },
      certs::ldapServiceName, certs::ldapObjectPath, certs::certInstallIntf,
      "Install", certFile->getCertFilePath());
}

inline void handleLDAPCertificateGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& id) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" << id;
  const boost::urls::url certURL = crow::utility::urlFromPieces(
      "redfish", "v1", "AccountService", "LDAP", "Certificates", id);
  std::string objPath =
      sdbusplus::message::object_path(certs::ldapObjectPath) / id;
  getCertificateProperties(asyncResp, objPath, certs::ldapServiceName, id,
                           certURL, "LDAP Certificate");
}

inline void handleLDAPCertificateDelete(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& id) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  BMCWEB_LOG_DEBUG << "Delete LDAP Certificate ID=" << id;
  std::string objPath =
      sdbusplus::message::object_path(certs::ldapObjectPath) / id;

  deleteCertificate(asyncResp, certs::ldapServiceName, objPath);
}

inline void requestRoutesLDAPCertificate(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
      .privileges(redfish::privileges::getCertificateCollection)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleLDAPCertificateCollectionGet, std::ref(app)));

  BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
      .privileges(redfish::privileges::postCertificateCollection)
      .methods(boost::beast::http::verb::post)(
          std::bind_front(handleLDAPCertificateCollectionPost, std::ref(app)));

  BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/")
      .privileges(redfish::privileges::getCertificate)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleLDAPCertificateGet, std::ref(app)));

  BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/")
      .privileges(redfish::privileges::deleteCertificate)
      .methods(boost::beast::http::verb::delete_)(
          std::bind_front(handleLDAPCertificateDelete, std::ref(app)));
}  // requestRoutesLDAPCertificate

inline void handleTrustStoreCertificateCollectionGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  asyncResp->res.jsonValue["@odata.id"] =
      "/redfish/v1/Managers/bmc/Truststore/Certificates/";
  asyncResp->res.jsonValue["@odata.type"] =
      "#CertificateCollection.CertificateCollection";
  asyncResp->res.jsonValue["Name"] = "TrustStore Certificates Collection";
  asyncResp->res.jsonValue["Description"] =
      "A Collection of TrustStore certificate instances";

  getCertificateList(asyncResp, certs::authorityObjectPath,
                     "/Members"_json_pointer,
                     "/Members@odata.count"_json_pointer);
}

inline void handleTrustStoreCertificateCollectionPost(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }
  std::string certFileBody = getCertificateFromReqBody(asyncResp, req);

  if (certFileBody.empty()) {
    BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
    messages::unrecognizedRequestBody(asyncResp->res);
    return;
  }

  std::shared_ptr<CertificateFile> certFile =
      std::make_shared<CertificateFile>(certFileBody);
  managedStore::GetManagedObjectStore()->PostDbusCallToIoContextThreadSafe(
      asyncResp->strand_,
      [asyncResp, certFile](const boost::system::error_code& ec,
                            const std::string& objectPath) {
        if (ec) {
          BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
          messages::internalError(asyncResp->res);
          return;
        }

        sdbusplus::message::object_path path(objectPath);
        std::string certId = path.filename();
        const boost::urls::url certURL =
            crow::utility::urlFromPieces("redfish", "v1", "Managers", "bmc",
                                         "Truststore", "Certificates", certId);
        getCertificateProperties(asyncResp, objectPath,
                                 certs::authorityServiceName, certId, certURL,
                                 "TrustStore Certificate");
        BMCWEB_LOG_DEBUG << "TrustStore certificate install file="
                         << certFile->getCertFilePath();
      },
      certs::authorityServiceName, certs::authorityObjectPath,
      certs::certInstallIntf, "Install", certFile->getCertFilePath());
}

inline void handleTrustStoreCertificateGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& id) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  BMCWEB_LOG_DEBUG << "Truststore Certificate ID=" << id;
  const boost::urls::url certURL = crow::utility::urlFromPieces(
      "redfish", "v1", "Managers", "bmc", "Truststore", "Certificates", id);
  std::string objPath =
      sdbusplus::message::object_path(certs::authorityObjectPath) / id;
  getCertificateProperties(asyncResp, objPath, certs::authorityServiceName, id,
                           certURL, "TrustStore Certificate");
}

inline void handleTrustStoreCertificateDelete(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& id) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  BMCWEB_LOG_DEBUG << "Delete TrustStore Certificate ID=" << id;
  std::string objPath =
      sdbusplus::message::object_path(certs::authorityObjectPath) / id;

  deleteCertificate(asyncResp, certs::authorityServiceName, objPath);
}

inline void requestRoutesTrustStoreCertificate(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
      .privileges(redfish::privileges::getCertificate)
      .methods(boost::beast::http::verb::get)(std::bind_front(
          handleTrustStoreCertificateCollectionGet, std::ref(app)));

  BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
      .privileges(redfish::privileges::postCertificateCollection)
      .methods(boost::beast::http::verb::post)(std::bind_front(
          handleTrustStoreCertificateCollectionPost, std::ref(app)));

  BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
      .privileges(redfish::privileges::getCertificate)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleTrustStoreCertificateGet, std::ref(app)));

  BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
      .privileges(redfish::privileges::deleteCertificate)
      .methods(boost::beast::http::verb::delete_)(
          std::bind_front(handleTrustStoreCertificateDelete, std::ref(app)));
}  // requestRoutesTrustStoreCertificate

/**
 * Collection of Chassis Certificates
 */
inline void handleChassisCertificateCollectionGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  boost::urls::url url = crow::utility::urlFromPieces(
      "redfish", "v1", "Chassis", chassisId, "Certificates");

  asyncResp->res.jsonValue["@odata.id"] = url.buffer();
  asyncResp->res.jsonValue["@odata.type"] =
      "#CertificateCollection.CertificateCollection";
  asyncResp->res.jsonValue["Name"] = "Chassis Certificates Collection";
  asyncResp->res.jsonValue["Description"] =
      "A Collection of Chassis Certificate instances";

  constexpr std::array<std::string_view, 1> certInterfaces = {
      "xyz.openbmc_project.Certs.Certificate"};
  std::string certPath =
      sdbusplus::message::object_path(certs::chassisObjectPath) / chassisId;

  collection_util::getCollectionMembers(asyncResp, url, certInterfaces,
                                        certPath.c_str());
}

inline void handleChassisCertificateGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId, const std::string& certId) {
  if (!redfish::setUpRedfishRoute(app, req, asyncResp)) {
    return;
  }

  if (chassisId.empty() || certId.empty()) {
    messages::internalError(asyncResp->res);
    return;
  }

  // GetSubTree on interfaces which provide info about certificate.
  constexpr std::array<std::string_view, 1> interfaces = {
      "xyz.openbmc_project.Certs.Certificate"};
  std::string certCollectionPath =
      sdbusplus::message::object_path(certs::chassisObjectPath) / chassisId;

  managedStore::ManagedObjectStoreContext context(asyncResp);
  dbus_utils::getSubTree(
      certCollectionPath, 0, interfaces, context,
      [asyncResp, chassisId, certId](
          const boost::system::error_code& ec,
          const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec) {
          BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
          messages::internalError(asyncResp->res);
          return;
        }

        const boost::urls::url certURL = crow::utility::urlFromPieces(
            "redfish", "v1", "Chassis", chassisId, "Certificates", certId);
        sdbusplus::message::object_path certPath =
            std::string(certs::chassisObjectPath) + "/" + chassisId + "/" +
            certId;

        for (const auto& [objectPath, serviceMap] : subtree) {
          // Ignore any objects which don't match certPath
          if (!objectPath.starts_with(certPath.str)) {
            continue;
          }

          // Should only match one service and one cert object
          for (const auto& [serviceName, interfaceList] : serviceMap) {
            getCertificateProperties(asyncResp, certPath, serviceName, certId,
                                     certURL, "Chassis Certificate");
          }
        }
      });
}

inline void requestRoutesChassisCertificate(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Certificates/")
      .privileges(redfish::privileges::getCertificateCollection)
      .methods(boost::beast::http::verb::get)(std::bind_front(
          handleChassisCertificateCollectionGet, std::ref(app)));

  BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/Certificates/<str>/")
      .privileges(redfish::privileges::getCertificate)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleChassisCertificateGet, std::ref(app)));
}  // requestRoutesChassisCertificate

}  // namespace redfish

#endif  // THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_CERTIFICATE_SERVICE_H_
