xref: /openbmc/bmcweb/features/redfish/lib/certificate_service.hpp (revision 4f48d5f67f293e50340e7f4bf866435e03a6fc62)
15968caeeSMarri Devender Rao #pragma once
25968caeeSMarri Devender Rao 
37e860f15SJohn Edward Broadbent #include <app.hpp>
4e6604b11SIwona Klimaszewska #include <boost/convert.hpp>
5e6604b11SIwona Klimaszewska #include <boost/convert/strtol.hpp>
6ed398213SEd Tanous #include <registries/privilege_registry.hpp>
71214b7e7SGunnar Mills 
85968caeeSMarri Devender Rao #include <variant>
95968caeeSMarri Devender Rao namespace redfish
105968caeeSMarri Devender Rao {
115968caeeSMarri Devender Rao namespace certs
125968caeeSMarri Devender Rao {
135968caeeSMarri Devender Rao constexpr char const* httpsObjectPath =
145968caeeSMarri Devender Rao     "/xyz/openbmc_project/certs/server/https";
155968caeeSMarri Devender Rao constexpr char const* certInstallIntf = "xyz.openbmc_project.Certs.Install";
165968caeeSMarri Devender Rao constexpr char const* certReplaceIntf = "xyz.openbmc_project.Certs.Replace";
1707a60299SZbigniew Kurzynski constexpr char const* objDeleteIntf = "xyz.openbmc_project.Object.Delete";
185968caeeSMarri Devender Rao constexpr char const* certPropIntf = "xyz.openbmc_project.Certs.Certificate";
195968caeeSMarri Devender Rao constexpr char const* dbusPropIntf = "org.freedesktop.DBus.Properties";
205968caeeSMarri Devender Rao constexpr char const* dbusObjManagerIntf = "org.freedesktop.DBus.ObjectManager";
2137cce918SMarri Devender Rao constexpr char const* ldapObjectPath = "/xyz/openbmc_project/certs/client/ldap";
2237cce918SMarri Devender Rao constexpr char const* httpsServiceName =
2337cce918SMarri Devender Rao     "xyz.openbmc_project.Certs.Manager.Server.Https";
2437cce918SMarri Devender Rao constexpr char const* ldapServiceName =
2537cce918SMarri Devender Rao     "xyz.openbmc_project.Certs.Manager.Client.Ldap";
26cfcd5f6bSMarri Devender Rao constexpr char const* authorityServiceName =
27cfcd5f6bSMarri Devender Rao     "xyz.openbmc_project.Certs.Manager.Authority.Ldap";
28cfcd5f6bSMarri Devender Rao constexpr char const* authorityObjectPath =
29cfcd5f6bSMarri Devender Rao     "/xyz/openbmc_project/certs/authority/ldap";
305968caeeSMarri Devender Rao } // namespace certs
315968caeeSMarri Devender Rao 
325968caeeSMarri Devender Rao /**
335968caeeSMarri Devender Rao  * The Certificate schema defines a Certificate Service which represents the
345968caeeSMarri Devender Rao  * actions available to manage certificates and links to where certificates
355968caeeSMarri Devender Rao  * are installed.
365968caeeSMarri Devender Rao  */
377e860f15SJohn Edward Broadbent 
385968caeeSMarri Devender Rao // TODO: Issue#61 No entries are available for Certificate
394e0453b1SGunnar Mills // service at https://www.dmtf.org/standards/redfish
405968caeeSMarri Devender Rao // "redfish standard registries". Need to modify after DMTF
415968caeeSMarri Devender Rao // publish Privilege details for certificate service
425968caeeSMarri Devender Rao 
437e860f15SJohn Edward Broadbent inline void requestRoutesCertificateService(App& app)
445968caeeSMarri Devender Rao {
457e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/")
46ed398213SEd Tanous         .privileges(redfish::privileges::getCertificateService)
4772048780SAbhishek Patel         .methods(
4872048780SAbhishek Patel             boost::beast::http::verb::
4972048780SAbhishek Patel                 get)([](const crow::Request& req,
507e860f15SJohn Edward Broadbent                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
518d1b46d7Szhanghch05             asyncResp->res.jsonValue = {
527e860f15SJohn Edward Broadbent                 {"@odata.type",
537e860f15SJohn Edward Broadbent                  "#CertificateService.v1_0_0.CertificateService"},
545968caeeSMarri Devender Rao                 {"@odata.id", "/redfish/v1/CertificateService"},
555968caeeSMarri Devender Rao                 {"Id", "CertificateService"},
565968caeeSMarri Devender Rao                 {"Name", "Certificate Service"},
5772048780SAbhishek Patel                 {"Description", "Actions available to manage certificates"}};
5872048780SAbhishek Patel             // /redfish/v1/CertificateService/CertificateLocations is something
5972048780SAbhishek Patel             // only ConfigureManager can access then only display when the user
6072048780SAbhishek Patel             // has permissions ConfigureManager
6172048780SAbhishek Patel             Privileges effectiveUserPrivileges =
6272048780SAbhishek Patel                 redfish::getUserPrivileges(req.userRole);
6372048780SAbhishek Patel             if (isOperationAllowedWithPrivileges({{"ConfigureManager"}},
6472048780SAbhishek Patel                                                  effectiveUserPrivileges))
6572048780SAbhishek Patel             {
668d1b46d7Szhanghch05                 asyncResp->res.jsonValue["CertificateLocations"] = {
675968caeeSMarri Devender Rao                     {"@odata.id",
685968caeeSMarri Devender Rao                      "/redfish/v1/CertificateService/CertificateLocations"}};
6972048780SAbhishek Patel             }
7072048780SAbhishek Patel             asyncResp->res.jsonValue["Actions"]
7172048780SAbhishek Patel                                     ["#CertificateService.ReplaceCertificate"] =
7272048780SAbhishek Patel                 {{"target", "/redfish/v1/CertificateService/Actions/"
735968caeeSMarri Devender Rao                             "CertificateService.ReplaceCertificate"},
745968caeeSMarri Devender Rao                  {"CertificateType@Redfish.AllowableValues", {"PEM"}}};
757e860f15SJohn Edward Broadbent             asyncResp->res
767e860f15SJohn Edward Broadbent                 .jsonValue["Actions"]["#CertificateService.GenerateCSR"] = {
777e860f15SJohn Edward Broadbent                 {"target", "/redfish/v1/CertificateService/Actions/"
7830215816SMarri Devender Rao                            "CertificateService.GenerateCSR"}};
797e860f15SJohn Edward Broadbent         });
807e860f15SJohn Edward Broadbent } // requestRoutesCertificateService
8137cce918SMarri Devender Rao 
825968caeeSMarri Devender Rao /**
835968caeeSMarri Devender Rao  * @brief Find the ID specified in the URL
845968caeeSMarri Devender Rao  * Finds the numbers specified after the last "/" in the URL and returns.
855968caeeSMarri Devender Rao  * @param[in] path URL
865968caeeSMarri Devender Rao  * @return -1 on failure and number on success
875968caeeSMarri Devender Rao  */
8823a21a1cSEd Tanous inline long getIDFromURL(const std::string_view url)
895968caeeSMarri Devender Rao {
90f23b7296SEd Tanous     std::size_t found = url.rfind('/');
915968caeeSMarri Devender Rao     if (found == std::string::npos)
925968caeeSMarri Devender Rao     {
935968caeeSMarri Devender Rao         return -1;
945968caeeSMarri Devender Rao     }
95e6604b11SIwona Klimaszewska 
965968caeeSMarri Devender Rao     if ((found + 1) < url.length())
975968caeeSMarri Devender Rao     {
985968caeeSMarri Devender Rao         std::string_view str = url.substr(found + 1);
99e6604b11SIwona Klimaszewska 
100e6604b11SIwona Klimaszewska         return boost::convert<long>(str, boost::cnv::strtol()).value_or(-1);
1015968caeeSMarri Devender Rao     }
102e6604b11SIwona Klimaszewska 
1035968caeeSMarri Devender Rao     return -1;
1045968caeeSMarri Devender Rao }
1055968caeeSMarri Devender Rao 
1068d1b46d7Szhanghch05 inline std::string getCertificateFromReqBody(
1078d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
10858eb238fSKowalski, Kamil     const crow::Request& req)
10958eb238fSKowalski, Kamil {
11058eb238fSKowalski, Kamil     nlohmann::json reqJson = nlohmann::json::parse(req.body, nullptr, false);
11158eb238fSKowalski, Kamil 
11258eb238fSKowalski, Kamil     if (reqJson.is_discarded())
11358eb238fSKowalski, Kamil     {
11458eb238fSKowalski, Kamil         // We did not receive JSON request, proceed as it is RAW data
11558eb238fSKowalski, Kamil         return req.body;
11658eb238fSKowalski, Kamil     }
11758eb238fSKowalski, Kamil 
11858eb238fSKowalski, Kamil     std::string certificate;
11958eb238fSKowalski, Kamil     std::optional<std::string> certificateType = "PEM";
12058eb238fSKowalski, Kamil 
12158eb238fSKowalski, Kamil     if (!json_util::readJson(reqJson, asyncResp->res, "CertificateString",
12258eb238fSKowalski, Kamil                              certificate, "CertificateType", certificateType))
12358eb238fSKowalski, Kamil     {
12458eb238fSKowalski, Kamil         BMCWEB_LOG_ERROR << "Required parameters are missing";
12558eb238fSKowalski, Kamil         messages::internalError(asyncResp->res);
12658eb238fSKowalski, Kamil         return std::string();
12758eb238fSKowalski, Kamil     }
12858eb238fSKowalski, Kamil 
12958eb238fSKowalski, Kamil     if (*certificateType != "PEM")
13058eb238fSKowalski, Kamil     {
13158eb238fSKowalski, Kamil         messages::propertyValueNotInList(asyncResp->res, *certificateType,
13258eb238fSKowalski, Kamil                                          "CertificateType");
13358eb238fSKowalski, Kamil         return std::string();
13458eb238fSKowalski, Kamil     }
13558eb238fSKowalski, Kamil 
13658eb238fSKowalski, Kamil     return certificate;
13758eb238fSKowalski, Kamil }
13858eb238fSKowalski, Kamil 
1395968caeeSMarri Devender Rao /**
1405968caeeSMarri Devender Rao  * Class to create a temporary certificate file for uploading to system
1415968caeeSMarri Devender Rao  */
1425968caeeSMarri Devender Rao class CertificateFile
1435968caeeSMarri Devender Rao {
1445968caeeSMarri Devender Rao   public:
1455968caeeSMarri Devender Rao     CertificateFile() = delete;
1465968caeeSMarri Devender Rao     CertificateFile(const CertificateFile&) = delete;
1475968caeeSMarri Devender Rao     CertificateFile& operator=(const CertificateFile&) = delete;
1485968caeeSMarri Devender Rao     CertificateFile(CertificateFile&&) = delete;
1495968caeeSMarri Devender Rao     CertificateFile& operator=(CertificateFile&&) = delete;
1505968caeeSMarri Devender Rao     CertificateFile(const std::string& certString)
1515968caeeSMarri Devender Rao     {
15272d52d25SEd Tanous         std::array<char, 18> dirTemplate = {'/', 't', 'm', 'p', '/', 'C',
1535207438cSEd Tanous                                             'e', 'r', 't', 's', '.', 'X',
1545207438cSEd Tanous                                             'X', 'X', 'X', 'X', 'X', '\0'};
1555207438cSEd Tanous         char* tempDirectory = mkdtemp(dirTemplate.data());
1565968caeeSMarri Devender Rao         if (tempDirectory)
1575968caeeSMarri Devender Rao         {
1585968caeeSMarri Devender Rao             certDirectory = tempDirectory;
1595968caeeSMarri Devender Rao             certificateFile = certDirectory / "cert.pem";
1605968caeeSMarri Devender Rao             std::ofstream out(certificateFile, std::ofstream::out |
1615968caeeSMarri Devender Rao                                                    std::ofstream::binary |
1625968caeeSMarri Devender Rao                                                    std::ofstream::trunc);
1635968caeeSMarri Devender Rao             out << certString;
1645968caeeSMarri Devender Rao             out.close();
1655968caeeSMarri Devender Rao             BMCWEB_LOG_DEBUG << "Creating certificate file" << certificateFile;
1665968caeeSMarri Devender Rao         }
1675968caeeSMarri Devender Rao     }
1685968caeeSMarri Devender Rao     ~CertificateFile()
1695968caeeSMarri Devender Rao     {
1705968caeeSMarri Devender Rao         if (std::filesystem::exists(certDirectory))
1715968caeeSMarri Devender Rao         {
1725968caeeSMarri Devender Rao             BMCWEB_LOG_DEBUG << "Removing certificate file" << certificateFile;
17323a21a1cSEd Tanous             std::error_code ec;
17423a21a1cSEd Tanous             std::filesystem::remove_all(certDirectory, ec);
17523a21a1cSEd Tanous             if (ec)
1765968caeeSMarri Devender Rao             {
1775968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "Failed to remove temp directory"
1785968caeeSMarri Devender Rao                                  << certDirectory;
1795968caeeSMarri Devender Rao             }
1805968caeeSMarri Devender Rao         }
1815968caeeSMarri Devender Rao     }
1825968caeeSMarri Devender Rao     std::string getCertFilePath()
1835968caeeSMarri Devender Rao     {
1845968caeeSMarri Devender Rao         return certificateFile;
1855968caeeSMarri Devender Rao     }
1865968caeeSMarri Devender Rao 
1875968caeeSMarri Devender Rao   private:
1885968caeeSMarri Devender Rao     std::filesystem::path certificateFile;
1895968caeeSMarri Devender Rao     std::filesystem::path certDirectory;
1905968caeeSMarri Devender Rao };
1915968caeeSMarri Devender Rao 
19230215816SMarri Devender Rao static std::unique_ptr<sdbusplus::bus::match::match> csrMatcher;
19330215816SMarri Devender Rao /**
19430215816SMarri Devender Rao  * @brief Read data from CSR D-bus object and set to response
19530215816SMarri Devender Rao  *
19630215816SMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
19730215816SMarri Devender Rao  * @param[in] certURI Link to certifiate collection URI
19830215816SMarri Devender Rao  * @param[in] service D-Bus service name
19930215816SMarri Devender Rao  * @param[in] certObjPath certificate D-Bus object path
20030215816SMarri Devender Rao  * @param[in] csrObjPath CSR D-Bus object path
20130215816SMarri Devender Rao  * @return None
20230215816SMarri Devender Rao  */
2038d1b46d7Szhanghch05 static void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
20430215816SMarri Devender Rao                    const std::string& certURI, const std::string& service,
20530215816SMarri Devender Rao                    const std::string& certObjPath,
20630215816SMarri Devender Rao                    const std::string& csrObjPath)
20730215816SMarri Devender Rao {
20830215816SMarri Devender Rao     BMCWEB_LOG_DEBUG << "getCSR CertObjectPath" << certObjPath
20930215816SMarri Devender Rao                      << " CSRObjectPath=" << csrObjPath
21030215816SMarri Devender Rao                      << " service=" << service;
21130215816SMarri Devender Rao     crow::connections::systemBus->async_method_call(
21230215816SMarri Devender Rao         [asyncResp, certURI](const boost::system::error_code ec,
21330215816SMarri Devender Rao                              const std::string& csr) {
21430215816SMarri Devender Rao             if (ec)
21530215816SMarri Devender Rao             {
21630215816SMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
21730215816SMarri Devender Rao                 messages::internalError(asyncResp->res);
21830215816SMarri Devender Rao                 return;
21930215816SMarri Devender Rao             }
22030215816SMarri Devender Rao             if (csr.empty())
22130215816SMarri Devender Rao             {
22230215816SMarri Devender Rao                 BMCWEB_LOG_ERROR << "CSR read is empty";
22330215816SMarri Devender Rao                 messages::internalError(asyncResp->res);
22430215816SMarri Devender Rao                 return;
22530215816SMarri Devender Rao             }
22630215816SMarri Devender Rao             asyncResp->res.jsonValue["CSRString"] = csr;
22730215816SMarri Devender Rao             asyncResp->res.jsonValue["CertificateCollection"] = {
22830215816SMarri Devender Rao                 {"@odata.id", certURI}};
22930215816SMarri Devender Rao         },
23030215816SMarri Devender Rao         service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR");
23130215816SMarri Devender Rao }
23230215816SMarri Devender Rao 
23330215816SMarri Devender Rao /**
23430215816SMarri Devender Rao  * Action to Generate CSR
23530215816SMarri Devender Rao  */
2367e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionGenerateCSR(App& app)
23730215816SMarri Devender Rao {
2387e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/Actions/"
23930215816SMarri Devender Rao                       "CertificateService.GenerateCSR/")
240ed398213SEd Tanous         // Incorrect Privilege;  Should be ConfigureManager
241ed398213SEd Tanous         //.privileges(redfish::privileges::postCertificateService)
242432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
2437e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
2447e860f15SJohn Edward Broadbent             [](const crow::Request& req,
2457e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2462c70f800SEd Tanous                 static const int rsaKeyBitLength = 2048;
2478d1b46d7Szhanghch05 
24830215816SMarri Devender Rao                 // Required parameters
24930215816SMarri Devender Rao                 std::string city;
25030215816SMarri Devender Rao                 std::string commonName;
25130215816SMarri Devender Rao                 std::string country;
25230215816SMarri Devender Rao                 std::string organization;
25330215816SMarri Devender Rao                 std::string organizationalUnit;
25430215816SMarri Devender Rao                 std::string state;
25530215816SMarri Devender Rao                 nlohmann::json certificateCollection;
25630215816SMarri Devender Rao 
25730215816SMarri Devender Rao                 // Optional parameters
25830215816SMarri Devender Rao                 std::optional<std::vector<std::string>> optAlternativeNames =
25930215816SMarri Devender Rao                     std::vector<std::string>();
26030215816SMarri Devender Rao                 std::optional<std::string> optContactPerson = "";
26130215816SMarri Devender Rao                 std::optional<std::string> optChallengePassword = "";
26230215816SMarri Devender Rao                 std::optional<std::string> optEmail = "";
26330215816SMarri Devender Rao                 std::optional<std::string> optGivenName = "";
26430215816SMarri Devender Rao                 std::optional<std::string> optInitials = "";
2652c70f800SEd Tanous                 std::optional<int64_t> optKeyBitLength = rsaKeyBitLength;
266aaf3206fSVernon Mauery                 std::optional<std::string> optKeyCurveId = "secp384r1";
26730215816SMarri Devender Rao                 std::optional<std::string> optKeyPairAlgorithm = "EC";
26830215816SMarri Devender Rao                 std::optional<std::vector<std::string>> optKeyUsage =
26930215816SMarri Devender Rao                     std::vector<std::string>();
27030215816SMarri Devender Rao                 std::optional<std::string> optSurname = "";
27130215816SMarri Devender Rao                 std::optional<std::string> optUnstructuredName = "";
27230215816SMarri Devender Rao                 if (!json_util::readJson(
2737e860f15SJohn Edward Broadbent                         req, asyncResp->res, "City", city, "CommonName",
2747e860f15SJohn Edward Broadbent                         commonName, "ContactPerson", optContactPerson,
2757e860f15SJohn Edward Broadbent                         "Country", country, "Organization", organization,
2767e860f15SJohn Edward Broadbent                         "OrganizationalUnit", organizationalUnit, "State",
2777e860f15SJohn Edward Broadbent                         state, "CertificateCollection", certificateCollection,
2787e860f15SJohn Edward Broadbent                         "AlternativeNames", optAlternativeNames,
2797e860f15SJohn Edward Broadbent                         "ChallengePassword", optChallengePassword, "Email",
2807e860f15SJohn Edward Broadbent                         optEmail, "GivenName", optGivenName, "Initials",
2817e860f15SJohn Edward Broadbent                         optInitials, "KeyBitLength", optKeyBitLength,
2827e860f15SJohn Edward Broadbent                         "KeyCurveId", optKeyCurveId, "KeyPairAlgorithm",
2837e860f15SJohn Edward Broadbent                         optKeyPairAlgorithm, "KeyUsage", optKeyUsage, "Surname",
2847e860f15SJohn Edward Broadbent                         optSurname, "UnstructuredName", optUnstructuredName))
28530215816SMarri Devender Rao                 {
28630215816SMarri Devender Rao                     return;
28730215816SMarri Devender Rao                 }
28830215816SMarri Devender Rao 
28930215816SMarri Devender Rao                 // bmcweb has no way to store or decode a private key challenge
2907e860f15SJohn Edward Broadbent                 // password, which will likely cause bmcweb to crash on startup
2917e860f15SJohn Edward Broadbent                 // if this is not set on a post so not allowing the user to set
2927e860f15SJohn Edward Broadbent                 // value
29330215816SMarri Devender Rao                 if (*optChallengePassword != "")
29430215816SMarri Devender Rao                 {
2957e860f15SJohn Edward Broadbent                     messages::actionParameterNotSupported(
2967e860f15SJohn Edward Broadbent                         asyncResp->res, "GenerateCSR", "ChallengePassword");
29730215816SMarri Devender Rao                     return;
29830215816SMarri Devender Rao                 }
29930215816SMarri Devender Rao 
30030215816SMarri Devender Rao                 std::string certURI;
3017e860f15SJohn Edward Broadbent                 if (!redfish::json_util::readJson(certificateCollection,
3027e860f15SJohn Edward Broadbent                                                   asyncResp->res, "@odata.id",
3037e860f15SJohn Edward Broadbent                                                   certURI))
30430215816SMarri Devender Rao                 {
30530215816SMarri Devender Rao                     return;
30630215816SMarri Devender Rao                 }
30730215816SMarri Devender Rao 
30830215816SMarri Devender Rao                 std::string objectPath;
30930215816SMarri Devender Rao                 std::string service;
3107e860f15SJohn Edward Broadbent                 if (boost::starts_with(certURI,
3117e860f15SJohn Edward Broadbent                                        "/redfish/v1/Managers/bmc/"
3127e860f15SJohn Edward Broadbent                                        "NetworkProtocol/HTTPS/Certificates"))
31330215816SMarri Devender Rao                 {
31430215816SMarri Devender Rao                     objectPath = certs::httpsObjectPath;
31530215816SMarri Devender Rao                     service = certs::httpsServiceName;
31630215816SMarri Devender Rao                 }
3173b7f0149SMarri Devender Rao                 else if (boost::starts_with(
3187e860f15SJohn Edward Broadbent                              certURI,
3197e860f15SJohn Edward Broadbent                              "/redfish/v1/AccountService/LDAP/Certificates"))
3203b7f0149SMarri Devender Rao                 {
3213b7f0149SMarri Devender Rao                     objectPath = certs::ldapObjectPath;
3223b7f0149SMarri Devender Rao                     service = certs::ldapServiceName;
3233b7f0149SMarri Devender Rao                 }
32430215816SMarri Devender Rao                 else
32530215816SMarri Devender Rao                 {
32630215816SMarri Devender Rao                     messages::actionParameterNotSupported(
32730215816SMarri Devender Rao                         asyncResp->res, "CertificateCollection", "GenerateCSR");
32830215816SMarri Devender Rao                     return;
32930215816SMarri Devender Rao                 }
33030215816SMarri Devender Rao 
33130215816SMarri Devender Rao                 // supporting only EC and RSA algorithm
3327e860f15SJohn Edward Broadbent                 if (*optKeyPairAlgorithm != "EC" &&
3337e860f15SJohn Edward Broadbent                     *optKeyPairAlgorithm != "RSA")
33430215816SMarri Devender Rao                 {
33530215816SMarri Devender Rao                     messages::actionParameterNotSupported(
33630215816SMarri Devender Rao                         asyncResp->res, "KeyPairAlgorithm", "GenerateCSR");
33730215816SMarri Devender Rao                     return;
33830215816SMarri Devender Rao                 }
33930215816SMarri Devender Rao 
3407e860f15SJohn Edward Broadbent                 // supporting only 2048 key bit length for RSA algorithm due to
3417e860f15SJohn Edward Broadbent                 // time consumed in generating private key
34230215816SMarri Devender Rao                 if (*optKeyPairAlgorithm == "RSA" &&
3432c70f800SEd Tanous                     *optKeyBitLength != rsaKeyBitLength)
34430215816SMarri Devender Rao                 {
3457e860f15SJohn Edward Broadbent                     messages::propertyValueNotInList(
3467e860f15SJohn Edward Broadbent                         asyncResp->res, std::to_string(*optKeyBitLength),
34730215816SMarri Devender Rao                         "KeyBitLength");
34830215816SMarri Devender Rao                     return;
34930215816SMarri Devender Rao                 }
35030215816SMarri Devender Rao 
35130215816SMarri Devender Rao                 // validate KeyUsage supporting only 1 type based on URL
3527e860f15SJohn Edward Broadbent                 if (boost::starts_with(certURI,
3537e860f15SJohn Edward Broadbent                                        "/redfish/v1/Managers/bmc/"
3547e860f15SJohn Edward Broadbent                                        "NetworkProtocol/HTTPS/Certificates"))
35530215816SMarri Devender Rao                 {
35630215816SMarri Devender Rao                     if (optKeyUsage->size() == 0)
35730215816SMarri Devender Rao                     {
35830215816SMarri Devender Rao                         optKeyUsage->push_back("ServerAuthentication");
35930215816SMarri Devender Rao                     }
36030215816SMarri Devender Rao                     else if (optKeyUsage->size() == 1)
36130215816SMarri Devender Rao                     {
36230215816SMarri Devender Rao                         if ((*optKeyUsage)[0] != "ServerAuthentication")
36330215816SMarri Devender Rao                         {
36430215816SMarri Devender Rao                             messages::propertyValueNotInList(
36530215816SMarri Devender Rao                                 asyncResp->res, (*optKeyUsage)[0], "KeyUsage");
36630215816SMarri Devender Rao                             return;
36730215816SMarri Devender Rao                         }
36830215816SMarri Devender Rao                     }
36930215816SMarri Devender Rao                     else
37030215816SMarri Devender Rao                     {
37130215816SMarri Devender Rao                         messages::actionParameterNotSupported(
37230215816SMarri Devender Rao                             asyncResp->res, "KeyUsage", "GenerateCSR");
37330215816SMarri Devender Rao                         return;
37430215816SMarri Devender Rao                     }
37530215816SMarri Devender Rao                 }
3763b7f0149SMarri Devender Rao                 else if (boost::starts_with(
3777e860f15SJohn Edward Broadbent                              certURI,
3787e860f15SJohn Edward Broadbent                              "/redfish/v1/AccountService/LDAP/Certificates"))
3793b7f0149SMarri Devender Rao                 {
3803b7f0149SMarri Devender Rao                     if (optKeyUsage->size() == 0)
3813b7f0149SMarri Devender Rao                     {
3823b7f0149SMarri Devender Rao                         optKeyUsage->push_back("ClientAuthentication");
3833b7f0149SMarri Devender Rao                     }
3843b7f0149SMarri Devender Rao                     else if (optKeyUsage->size() == 1)
3853b7f0149SMarri Devender Rao                     {
3863b7f0149SMarri Devender Rao                         if ((*optKeyUsage)[0] != "ClientAuthentication")
3873b7f0149SMarri Devender Rao                         {
3883b7f0149SMarri Devender Rao                             messages::propertyValueNotInList(
3893b7f0149SMarri Devender Rao                                 asyncResp->res, (*optKeyUsage)[0], "KeyUsage");
3903b7f0149SMarri Devender Rao                             return;
3913b7f0149SMarri Devender Rao                         }
3923b7f0149SMarri Devender Rao                     }
3933b7f0149SMarri Devender Rao                     else
3943b7f0149SMarri Devender Rao                     {
3953b7f0149SMarri Devender Rao                         messages::actionParameterNotSupported(
3963b7f0149SMarri Devender Rao                             asyncResp->res, "KeyUsage", "GenerateCSR");
3973b7f0149SMarri Devender Rao                         return;
3983b7f0149SMarri Devender Rao                     }
3993b7f0149SMarri Devender Rao                 }
40030215816SMarri Devender Rao 
4017e860f15SJohn Edward Broadbent                 // Only allow one CSR matcher at a time so setting retry
4027e860f15SJohn Edward Broadbent                 // time-out and timer expiry to 10 seconds for now.
4032c70f800SEd Tanous                 static const int timeOut = 10;
40430215816SMarri Devender Rao                 if (csrMatcher)
40530215816SMarri Devender Rao                 {
4067e860f15SJohn Edward Broadbent                     messages::serviceTemporarilyUnavailable(
4077e860f15SJohn Edward Broadbent                         asyncResp->res, std::to_string(timeOut));
40830215816SMarri Devender Rao                     return;
40930215816SMarri Devender Rao                 }
41030215816SMarri Devender Rao 
41130215816SMarri Devender Rao                 // Make this static so it survives outside this method
41230215816SMarri Devender Rao                 static boost::asio::steady_timer timeout(*req.ioService);
4132c70f800SEd Tanous                 timeout.expires_after(std::chrono::seconds(timeOut));
4147e860f15SJohn Edward Broadbent                 timeout.async_wait([asyncResp](
4157e860f15SJohn Edward Broadbent                                        const boost::system::error_code& ec) {
41630215816SMarri Devender Rao                     csrMatcher = nullptr;
41730215816SMarri Devender Rao                     if (ec)
41830215816SMarri Devender Rao                     {
4197e860f15SJohn Edward Broadbent                         // operation_aborted is expected if timer is canceled
4207e860f15SJohn Edward Broadbent                         // before completion.
42130215816SMarri Devender Rao                         if (ec != boost::asio::error::operation_aborted)
42230215816SMarri Devender Rao                         {
42330215816SMarri Devender Rao                             BMCWEB_LOG_ERROR << "Async_wait failed " << ec;
42430215816SMarri Devender Rao                         }
42530215816SMarri Devender Rao                         return;
42630215816SMarri Devender Rao                     }
42730215816SMarri Devender Rao                     BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR";
42830215816SMarri Devender Rao                     messages::internalError(asyncResp->res);
42930215816SMarri Devender Rao                 });
43030215816SMarri Devender Rao 
43130215816SMarri Devender Rao                 // create a matcher to wait on CSR object
43230215816SMarri Devender Rao                 BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath;
4337e860f15SJohn Edward Broadbent                 std::string match(
4347e860f15SJohn Edward Broadbent                     "type='signal',"
43530215816SMarri Devender Rao                     "interface='org.freedesktop.DBus.ObjectManager',"
43630215816SMarri Devender Rao                     "path='" +
43730215816SMarri Devender Rao                     objectPath +
43830215816SMarri Devender Rao                     "',"
43930215816SMarri Devender Rao                     "member='InterfacesAdded'");
44030215816SMarri Devender Rao                 csrMatcher = std::make_unique<sdbusplus::bus::match::match>(
44130215816SMarri Devender Rao                     *crow::connections::systemBus, match,
44230215816SMarri Devender Rao                     [asyncResp, service, objectPath,
44330215816SMarri Devender Rao                      certURI](sdbusplus::message::message& m) {
444271584abSEd Tanous                         timeout.cancel();
44530215816SMarri Devender Rao                         if (m.is_method_error())
44630215816SMarri Devender Rao                         {
44730215816SMarri Devender Rao                             BMCWEB_LOG_ERROR << "Dbus method error!!!";
44830215816SMarri Devender Rao                             messages::internalError(asyncResp->res);
44930215816SMarri Devender Rao                             return;
45030215816SMarri Devender Rao                         }
45130215816SMarri Devender Rao                         std::vector<std::pair<
4527e860f15SJohn Edward Broadbent                             std::string,
4537e860f15SJohn Edward Broadbent                             std::vector<std::pair<std::string,
4547e860f15SJohn Edward Broadbent                                                   std::variant<std::string>>>>>
45530215816SMarri Devender Rao                             interfacesProperties;
45630215816SMarri Devender Rao                         sdbusplus::message::object_path csrObjectPath;
45730215816SMarri Devender Rao                         m.read(csrObjectPath, interfacesProperties);
4587e860f15SJohn Edward Broadbent                         BMCWEB_LOG_DEBUG << "CSR object added"
4597e860f15SJohn Edward Broadbent                                          << csrObjectPath.str;
46030215816SMarri Devender Rao                         for (auto& interface : interfacesProperties)
46130215816SMarri Devender Rao                         {
4627e860f15SJohn Edward Broadbent                             if (interface.first ==
4637e860f15SJohn Edward Broadbent                                 "xyz.openbmc_project.Certs.CSR")
46430215816SMarri Devender Rao                             {
46530215816SMarri Devender Rao                                 getCSR(asyncResp, certURI, service, objectPath,
46630215816SMarri Devender Rao                                        csrObjectPath.str);
46730215816SMarri Devender Rao                                 break;
46830215816SMarri Devender Rao                             }
46930215816SMarri Devender Rao                         }
47030215816SMarri Devender Rao                     });
47130215816SMarri Devender Rao                 crow::connections::systemBus->async_method_call(
472271584abSEd Tanous                     [asyncResp](const boost::system::error_code& ec,
473cb13a392SEd Tanous                                 const std::string&) {
47430215816SMarri Devender Rao                         if (ec)
47530215816SMarri Devender Rao                         {
4767e860f15SJohn Edward Broadbent                             BMCWEB_LOG_ERROR << "DBUS response error: "
4777e860f15SJohn Edward Broadbent                                              << ec.message();
47830215816SMarri Devender Rao                             messages::internalError(asyncResp->res);
47930215816SMarri Devender Rao                             return;
48030215816SMarri Devender Rao                         }
48130215816SMarri Devender Rao                     },
48230215816SMarri Devender Rao                     service, objectPath, "xyz.openbmc_project.Certs.CSR.Create",
4837e860f15SJohn Edward Broadbent                     "GenerateCSR", *optAlternativeNames, *optChallengePassword,
4847e860f15SJohn Edward Broadbent                     city, commonName, *optContactPerson, country, *optEmail,
4857e860f15SJohn Edward Broadbent                     *optGivenName, *optInitials, *optKeyBitLength,
4867e860f15SJohn Edward Broadbent                     *optKeyCurveId, *optKeyPairAlgorithm, *optKeyUsage,
4877e860f15SJohn Edward Broadbent                     organization, organizationalUnit, state, *optSurname,
4887e860f15SJohn Edward Broadbent                     *optUnstructuredName);
4897e860f15SJohn Edward Broadbent             });
4907e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionGenerateCSR
49130215816SMarri Devender Rao 
4925968caeeSMarri Devender Rao /**
4934e0453b1SGunnar Mills  * @brief Parse and update Certificate Issue/Subject property
4945968caeeSMarri Devender Rao  *
4955968caeeSMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
4965968caeeSMarri Devender Rao  * @param[in] str  Issuer/Subject value in key=value pairs
4975968caeeSMarri Devender Rao  * @param[in] type Issuer/Subject
4985968caeeSMarri Devender Rao  * @return None
4995968caeeSMarri Devender Rao  */
5005968caeeSMarri Devender Rao static void updateCertIssuerOrSubject(nlohmann::json& out,
5015968caeeSMarri Devender Rao                                       const std::string_view value)
5025968caeeSMarri Devender Rao {
5035968caeeSMarri Devender Rao     // example: O=openbmc-project.xyz,CN=localhost
5045968caeeSMarri Devender Rao     std::string_view::iterator i = value.begin();
5055968caeeSMarri Devender Rao     while (i != value.end())
5065968caeeSMarri Devender Rao     {
5075968caeeSMarri Devender Rao         std::string_view::iterator tokenBegin = i;
5085968caeeSMarri Devender Rao         while (i != value.end() && *i != '=')
5095968caeeSMarri Devender Rao         {
51017a897dfSManojkiran Eda             ++i;
5115968caeeSMarri Devender Rao         }
5125968caeeSMarri Devender Rao         if (i == value.end())
5135968caeeSMarri Devender Rao         {
5145968caeeSMarri Devender Rao             break;
5155968caeeSMarri Devender Rao         }
516271584abSEd Tanous         const std::string_view key(tokenBegin,
517271584abSEd Tanous                                    static_cast<size_t>(i - tokenBegin));
51817a897dfSManojkiran Eda         ++i;
5195968caeeSMarri Devender Rao         tokenBegin = i;
5205968caeeSMarri Devender Rao         while (i != value.end() && *i != ',')
5215968caeeSMarri Devender Rao         {
52217a897dfSManojkiran Eda             ++i;
5235968caeeSMarri Devender Rao         }
524271584abSEd Tanous         const std::string_view val(tokenBegin,
525271584abSEd Tanous                                    static_cast<size_t>(i - tokenBegin));
5265968caeeSMarri Devender Rao         if (key == "L")
5275968caeeSMarri Devender Rao         {
5285968caeeSMarri Devender Rao             out["City"] = val;
5295968caeeSMarri Devender Rao         }
5305968caeeSMarri Devender Rao         else if (key == "CN")
5315968caeeSMarri Devender Rao         {
5325968caeeSMarri Devender Rao             out["CommonName"] = val;
5335968caeeSMarri Devender Rao         }
5345968caeeSMarri Devender Rao         else if (key == "C")
5355968caeeSMarri Devender Rao         {
5365968caeeSMarri Devender Rao             out["Country"] = val;
5375968caeeSMarri Devender Rao         }
5385968caeeSMarri Devender Rao         else if (key == "O")
5395968caeeSMarri Devender Rao         {
5405968caeeSMarri Devender Rao             out["Organization"] = val;
5415968caeeSMarri Devender Rao         }
5425968caeeSMarri Devender Rao         else if (key == "OU")
5435968caeeSMarri Devender Rao         {
5445968caeeSMarri Devender Rao             out["OrganizationalUnit"] = val;
5455968caeeSMarri Devender Rao         }
5465968caeeSMarri Devender Rao         else if (key == "ST")
5475968caeeSMarri Devender Rao         {
5485968caeeSMarri Devender Rao             out["State"] = val;
5495968caeeSMarri Devender Rao         }
5505968caeeSMarri Devender Rao         // skip comma character
5515968caeeSMarri Devender Rao         if (i != value.end())
5525968caeeSMarri Devender Rao         {
55317a897dfSManojkiran Eda             ++i;
5545968caeeSMarri Devender Rao         }
5555968caeeSMarri Devender Rao     }
5565968caeeSMarri Devender Rao }
5575968caeeSMarri Devender Rao 
5585968caeeSMarri Devender Rao /**
5595968caeeSMarri Devender Rao  * @brief Retrieve the certificates properties and append to the response
5605968caeeSMarri Devender Rao  * message
5615968caeeSMarri Devender Rao  *
5625968caeeSMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
5635968caeeSMarri Devender Rao  * @param[in] objectPath  Path of the D-Bus service object
5645968caeeSMarri Devender Rao  * @param[in] certId  Id of the certificate
5655968caeeSMarri Devender Rao  * @param[in] certURL  URL of the certificate object
5665968caeeSMarri Devender Rao  * @param[in] name  name of the certificate
5675968caeeSMarri Devender Rao  * @return None
5685968caeeSMarri Devender Rao  */
5695968caeeSMarri Devender Rao static void getCertificateProperties(
5708d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
5718d1b46d7Szhanghch05     const std::string& objectPath, const std::string& service, long certId,
5728d1b46d7Szhanghch05     const std::string& certURL, const std::string& name)
5735968caeeSMarri Devender Rao {
5745968caeeSMarri Devender Rao     using PropertyType =
5755968caeeSMarri Devender Rao         std::variant<std::string, uint64_t, std::vector<std::string>>;
5765968caeeSMarri Devender Rao     using PropertiesMap = boost::container::flat_map<std::string, PropertyType>;
5775968caeeSMarri Devender Rao     BMCWEB_LOG_DEBUG << "getCertificateProperties Path=" << objectPath
5785968caeeSMarri Devender Rao                      << " certId=" << certId << " certURl=" << certURL;
5795968caeeSMarri Devender Rao     crow::connections::systemBus->async_method_call(
58037cce918SMarri Devender Rao         [asyncResp, certURL, certId, name](const boost::system::error_code ec,
5815968caeeSMarri Devender Rao                                            const PropertiesMap& properties) {
5825968caeeSMarri Devender Rao             if (ec)
5835968caeeSMarri Devender Rao             {
5845968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
5858aae75adSMarri Devender Rao                 messages::resourceNotFound(asyncResp->res, name,
5868aae75adSMarri Devender Rao                                            std::to_string(certId));
5875968caeeSMarri Devender Rao                 return;
5885968caeeSMarri Devender Rao             }
5895968caeeSMarri Devender Rao             asyncResp->res.jsonValue = {
5905968caeeSMarri Devender Rao                 {"@odata.id", certURL},
5915968caeeSMarri Devender Rao                 {"@odata.type", "#Certificate.v1_0_0.Certificate"},
5925968caeeSMarri Devender Rao                 {"Id", std::to_string(certId)},
5935968caeeSMarri Devender Rao                 {"Name", name},
5945968caeeSMarri Devender Rao                 {"Description", name}};
5955968caeeSMarri Devender Rao             for (const auto& property : properties)
5965968caeeSMarri Devender Rao             {
5975968caeeSMarri Devender Rao                 if (property.first == "CertificateString")
5985968caeeSMarri Devender Rao                 {
5995968caeeSMarri Devender Rao                     asyncResp->res.jsonValue["CertificateString"] = "";
6005968caeeSMarri Devender Rao                     const std::string* value =
6015968caeeSMarri Devender Rao                         std::get_if<std::string>(&property.second);
6025968caeeSMarri Devender Rao                     if (value)
6035968caeeSMarri Devender Rao                     {
60437cce918SMarri Devender Rao                         asyncResp->res.jsonValue["CertificateString"] = *value;
6055968caeeSMarri Devender Rao                     }
6065968caeeSMarri Devender Rao                 }
6075968caeeSMarri Devender Rao                 else if (property.first == "KeyUsage")
6085968caeeSMarri Devender Rao                 {
6095968caeeSMarri Devender Rao                     nlohmann::json& keyUsage =
6105968caeeSMarri Devender Rao                         asyncResp->res.jsonValue["KeyUsage"];
6115968caeeSMarri Devender Rao                     keyUsage = nlohmann::json::array();
6125968caeeSMarri Devender Rao                     const std::vector<std::string>* value =
61337cce918SMarri Devender Rao                         std::get_if<std::vector<std::string>>(&property.second);
6145968caeeSMarri Devender Rao                     if (value)
6155968caeeSMarri Devender Rao                     {
6165968caeeSMarri Devender Rao                         for (const std::string& usage : *value)
6175968caeeSMarri Devender Rao                         {
6185968caeeSMarri Devender Rao                             keyUsage.push_back(usage);
6195968caeeSMarri Devender Rao                         }
6205968caeeSMarri Devender Rao                     }
6215968caeeSMarri Devender Rao                 }
6225968caeeSMarri Devender Rao                 else if (property.first == "Issuer")
6235968caeeSMarri Devender Rao                 {
6245968caeeSMarri Devender Rao                     const std::string* value =
6255968caeeSMarri Devender Rao                         std::get_if<std::string>(&property.second);
6265968caeeSMarri Devender Rao                     if (value)
6275968caeeSMarri Devender Rao                     {
6285968caeeSMarri Devender Rao                         updateCertIssuerOrSubject(
6295968caeeSMarri Devender Rao                             asyncResp->res.jsonValue["Issuer"], *value);
6305968caeeSMarri Devender Rao                     }
6315968caeeSMarri Devender Rao                 }
6325968caeeSMarri Devender Rao                 else if (property.first == "Subject")
6335968caeeSMarri Devender Rao                 {
6345968caeeSMarri Devender Rao                     const std::string* value =
6355968caeeSMarri Devender Rao                         std::get_if<std::string>(&property.second);
6365968caeeSMarri Devender Rao                     if (value)
6375968caeeSMarri Devender Rao                     {
6385968caeeSMarri Devender Rao                         updateCertIssuerOrSubject(
63937cce918SMarri Devender Rao                             asyncResp->res.jsonValue["Subject"], *value);
6405968caeeSMarri Devender Rao                     }
6415968caeeSMarri Devender Rao                 }
6425968caeeSMarri Devender Rao                 else if (property.first == "ValidNotAfter")
6435968caeeSMarri Devender Rao                 {
6445968caeeSMarri Devender Rao                     const uint64_t* value =
6455968caeeSMarri Devender Rao                         std::get_if<uint64_t>(&property.second);
6465968caeeSMarri Devender Rao                     if (value)
6475968caeeSMarri Devender Rao                     {
64837cce918SMarri Devender Rao                         std::time_t time = static_cast<std::time_t>(*value);
6495968caeeSMarri Devender Rao                         asyncResp->res.jsonValue["ValidNotAfter"] =
6505968caeeSMarri Devender Rao                             crow::utility::getDateTime(time);
6515968caeeSMarri Devender Rao                     }
6525968caeeSMarri Devender Rao                 }
6535968caeeSMarri Devender Rao                 else if (property.first == "ValidNotBefore")
6545968caeeSMarri Devender Rao                 {
6555968caeeSMarri Devender Rao                     const uint64_t* value =
6565968caeeSMarri Devender Rao                         std::get_if<uint64_t>(&property.second);
6575968caeeSMarri Devender Rao                     if (value)
6585968caeeSMarri Devender Rao                     {
65937cce918SMarri Devender Rao                         std::time_t time = static_cast<std::time_t>(*value);
6605968caeeSMarri Devender Rao                         asyncResp->res.jsonValue["ValidNotBefore"] =
6615968caeeSMarri Devender Rao                             crow::utility::getDateTime(time);
6625968caeeSMarri Devender Rao                     }
6635968caeeSMarri Devender Rao                 }
6645968caeeSMarri Devender Rao             }
6655968caeeSMarri Devender Rao             asyncResp->res.addHeader("Location", certURL);
6665968caeeSMarri Devender Rao         },
6675968caeeSMarri Devender Rao         service, objectPath, certs::dbusPropIntf, "GetAll",
6685968caeeSMarri Devender Rao         certs::certPropIntf);
6695968caeeSMarri Devender Rao }
6705968caeeSMarri Devender Rao 
6715968caeeSMarri Devender Rao using GetObjectType =
6725968caeeSMarri Devender Rao     std::vector<std::pair<std::string, std::vector<std::string>>>;
6735968caeeSMarri Devender Rao 
6745968caeeSMarri Devender Rao /**
6755968caeeSMarri Devender Rao  * Action to replace an existing certificate
6765968caeeSMarri Devender Rao  */
6777e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionsReplaceCertificate(App& app)
6785968caeeSMarri Devender Rao {
6797e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/Actions/"
6805968caeeSMarri Devender Rao                       "CertificateService.ReplaceCertificate/")
681ed398213SEd Tanous         .privileges(redfish::privileges::postCertificateService)
6827e860f15SJohn Edward Broadbent         .methods(
6837e860f15SJohn Edward Broadbent             boost::beast::http::verb::
6847e860f15SJohn Edward Broadbent                 post)([](const crow::Request& req,
6857e860f15SJohn Edward Broadbent                          const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
6865968caeeSMarri Devender Rao             std::string certificate;
6875968caeeSMarri Devender Rao             nlohmann::json certificateUri;
6885968caeeSMarri Devender Rao             std::optional<std::string> certificateType = "PEM";
6898d1b46d7Szhanghch05 
6905968caeeSMarri Devender Rao             if (!json_util::readJson(req, asyncResp->res, "CertificateString",
6917e860f15SJohn Edward Broadbent                                      certificate, "CertificateUri",
6927e860f15SJohn Edward Broadbent                                      certificateUri, "CertificateType",
6937e860f15SJohn Edward Broadbent                                      certificateType))
6945968caeeSMarri Devender Rao             {
6955968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "Required parameters are missing";
6965968caeeSMarri Devender Rao                 messages::internalError(asyncResp->res);
6975968caeeSMarri Devender Rao                 return;
6985968caeeSMarri Devender Rao             }
6995968caeeSMarri Devender Rao 
7005968caeeSMarri Devender Rao             if (!certificateType)
7015968caeeSMarri Devender Rao             {
7025968caeeSMarri Devender Rao                 // should never happen, but it never hurts to be paranoid.
7035968caeeSMarri Devender Rao                 return;
7045968caeeSMarri Devender Rao             }
7055968caeeSMarri Devender Rao             if (certificateType != "PEM")
7065968caeeSMarri Devender Rao             {
7075968caeeSMarri Devender Rao                 messages::actionParameterNotSupported(
7085968caeeSMarri Devender Rao                     asyncResp->res, "CertificateType", "ReplaceCertificate");
7095968caeeSMarri Devender Rao                 return;
7105968caeeSMarri Devender Rao             }
7115968caeeSMarri Devender Rao 
7125968caeeSMarri Devender Rao             std::string certURI;
7135968caeeSMarri Devender Rao             if (!redfish::json_util::readJson(certificateUri, asyncResp->res,
7145968caeeSMarri Devender Rao                                               "@odata.id", certURI))
7155968caeeSMarri Devender Rao             {
7165968caeeSMarri Devender Rao                 messages::actionParameterMissing(
7175968caeeSMarri Devender Rao                     asyncResp->res, "ReplaceCertificate", "CertificateUri");
7185968caeeSMarri Devender Rao                 return;
7195968caeeSMarri Devender Rao             }
7205968caeeSMarri Devender Rao 
7215968caeeSMarri Devender Rao             BMCWEB_LOG_INFO << "Certificate URI to replace" << certURI;
7225968caeeSMarri Devender Rao             long id = getIDFromURL(certURI);
7235968caeeSMarri Devender Rao             if (id < 0)
7245968caeeSMarri Devender Rao             {
7257e860f15SJohn Edward Broadbent                 messages::actionParameterValueFormatError(
7267e860f15SJohn Edward Broadbent                     asyncResp->res, certURI, "CertificateUri",
7275968caeeSMarri Devender Rao                     "ReplaceCertificate");
7285968caeeSMarri Devender Rao                 return;
7295968caeeSMarri Devender Rao             }
7305968caeeSMarri Devender Rao             std::string objectPath;
7315968caeeSMarri Devender Rao             std::string name;
73237cce918SMarri Devender Rao             std::string service;
7337e860f15SJohn Edward Broadbent             if (boost::starts_with(certURI,
7347e860f15SJohn Edward Broadbent                                    "/redfish/v1/Managers/bmc/NetworkProtocol/"
7357e860f15SJohn Edward Broadbent                                    "HTTPS/Certificates/"))
7365968caeeSMarri Devender Rao             {
7377e860f15SJohn Edward Broadbent                 objectPath = std::string(certs::httpsObjectPath) + "/" +
7387e860f15SJohn Edward Broadbent                              std::to_string(id);
7395968caeeSMarri Devender Rao                 name = "HTTPS certificate";
74037cce918SMarri Devender Rao                 service = certs::httpsServiceName;
74137cce918SMarri Devender Rao             }
74237cce918SMarri Devender Rao             else if (boost::starts_with(
7437e860f15SJohn Edward Broadbent                          certURI,
7447e860f15SJohn Edward Broadbent                          "/redfish/v1/AccountService/LDAP/Certificates/"))
74537cce918SMarri Devender Rao             {
7467e860f15SJohn Edward Broadbent                 objectPath = std::string(certs::ldapObjectPath) + "/" +
7477e860f15SJohn Edward Broadbent                              std::to_string(id);
74837cce918SMarri Devender Rao                 name = "LDAP certificate";
74937cce918SMarri Devender Rao                 service = certs::ldapServiceName;
7505968caeeSMarri Devender Rao             }
751cfcd5f6bSMarri Devender Rao             else if (boost::starts_with(
752cfcd5f6bSMarri Devender Rao                          certURI,
753cfcd5f6bSMarri Devender Rao                          "/redfish/v1/Managers/bmc/Truststore/Certificates/"))
754cfcd5f6bSMarri Devender Rao             {
755cfcd5f6bSMarri Devender Rao                 objectPath = std::string(certs::authorityObjectPath) + "/" +
756cfcd5f6bSMarri Devender Rao                              std::to_string(id);
757cfcd5f6bSMarri Devender Rao                 name = "TrustStore certificate";
758cfcd5f6bSMarri Devender Rao                 service = certs::authorityServiceName;
759cfcd5f6bSMarri Devender Rao             }
7605968caeeSMarri Devender Rao             else
7615968caeeSMarri Devender Rao             {
7625968caeeSMarri Devender Rao                 messages::actionParameterNotSupported(
7635968caeeSMarri Devender Rao                     asyncResp->res, "CertificateUri", "ReplaceCertificate");
7645968caeeSMarri Devender Rao                 return;
7655968caeeSMarri Devender Rao             }
7665968caeeSMarri Devender Rao 
7675968caeeSMarri Devender Rao             std::shared_ptr<CertificateFile> certFile =
7685968caeeSMarri Devender Rao                 std::make_shared<CertificateFile>(certificate);
7695968caeeSMarri Devender Rao             crow::connections::systemBus->async_method_call(
77037cce918SMarri Devender Rao                 [asyncResp, certFile, objectPath, service, certURI, id,
7715968caeeSMarri Devender Rao                  name](const boost::system::error_code ec) {
7725968caeeSMarri Devender Rao                     if (ec)
7735968caeeSMarri Devender Rao                     {
7745968caeeSMarri Devender Rao                         BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
7758aae75adSMarri Devender Rao                         messages::resourceNotFound(asyncResp->res, name,
7768aae75adSMarri Devender Rao                                                    std::to_string(id));
7775968caeeSMarri Devender Rao                         return;
7785968caeeSMarri Devender Rao                     }
77937cce918SMarri Devender Rao                     getCertificateProperties(asyncResp, objectPath, service, id,
7805968caeeSMarri Devender Rao                                              certURI, name);
7815968caeeSMarri Devender Rao                     BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
7825968caeeSMarri Devender Rao                                      << certFile->getCertFilePath();
7835968caeeSMarri Devender Rao                 },
7845968caeeSMarri Devender Rao                 service, objectPath, certs::certReplaceIntf, "Replace",
7855968caeeSMarri Devender Rao                 certFile->getCertFilePath());
7867e860f15SJohn Edward Broadbent         });
7877e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionsReplaceCertificate
7885968caeeSMarri Devender Rao 
7895968caeeSMarri Devender Rao /**
7905968caeeSMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
7915968caeeSMarri Devender Rao  * of a component, account or service.
7925968caeeSMarri Devender Rao  */
7935968caeeSMarri Devender Rao 
7947e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificate(App& app)
7955968caeeSMarri Devender Rao {
7967e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
7977e860f15SJohn Edward Broadbent         app,
7987e860f15SJohn Edward Broadbent         "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/<str>/")
799ed398213SEd Tanous         .privileges(redfish::privileges::getCertificate)
8007e860f15SJohn Edward Broadbent         .methods(
8017e860f15SJohn Edward Broadbent             boost::beast::http::verb::
8027e860f15SJohn Edward Broadbent                 get)([](const crow::Request& req,
8037e860f15SJohn Edward Broadbent                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
8047e860f15SJohn Edward Broadbent                         const std::string& param) -> void {
8057e860f15SJohn Edward Broadbent             if (param.empty())
8065968caeeSMarri Devender Rao             {
8075968caeeSMarri Devender Rao                 messages::internalError(asyncResp->res);
8085968caeeSMarri Devender Rao                 return;
8095968caeeSMarri Devender Rao             }
8105968caeeSMarri Devender Rao             long id = getIDFromURL(req.url);
8115968caeeSMarri Devender Rao 
8127e860f15SJohn Edward Broadbent             BMCWEB_LOG_DEBUG << "HTTPSCertificate::doGet ID="
8137e860f15SJohn Edward Broadbent                              << std::to_string(id);
8145968caeeSMarri Devender Rao             std::string certURL =
8155968caeeSMarri Devender Rao                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" +
8165968caeeSMarri Devender Rao                 std::to_string(id);
8175968caeeSMarri Devender Rao             std::string objectPath = certs::httpsObjectPath;
8185968caeeSMarri Devender Rao             objectPath += "/";
8195968caeeSMarri Devender Rao             objectPath += std::to_string(id);
8207e860f15SJohn Edward Broadbent             getCertificateProperties(asyncResp, objectPath,
8217e860f15SJohn Edward Broadbent                                      certs::httpsServiceName, id, certURL,
8227e860f15SJohn Edward Broadbent                                      "HTTPS Certificate");
8237e860f15SJohn Edward Broadbent         });
8245968caeeSMarri Devender Rao }
8255968caeeSMarri Devender Rao 
8265968caeeSMarri Devender Rao /**
8275968caeeSMarri Devender Rao  * Collection of HTTPS certificates
8285968caeeSMarri Devender Rao  */
8297e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificateCollection(App& app)
8305968caeeSMarri Devender Rao {
8317e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
8325968caeeSMarri Devender Rao                  "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
833ed398213SEd Tanous         .privileges(redfish::privileges::getCertificateCollection)
8347e860f15SJohn Edward Broadbent         .methods(
8357e860f15SJohn Edward Broadbent             boost::beast::http::verb::
8367e860f15SJohn Edward Broadbent                 get)([](const crow::Request&,
8377e860f15SJohn Edward Broadbent                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
8388d1b46d7Szhanghch05             asyncResp->res.jsonValue = {
8395968caeeSMarri Devender Rao                 {"@odata.id",
8405968caeeSMarri Devender Rao                  "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"},
8415968caeeSMarri Devender Rao                 {"@odata.type", "#CertificateCollection.CertificateCollection"},
8425968caeeSMarri Devender Rao                 {"Name", "HTTPS Certificates Collection"},
8435968caeeSMarri Devender Rao                 {"Description", "A Collection of HTTPS certificate instances"}};
8448d1b46d7Szhanghch05 
8455968caeeSMarri Devender Rao             crow::connections::systemBus->async_method_call(
8465968caeeSMarri Devender Rao                 [asyncResp](const boost::system::error_code ec,
8475968caeeSMarri Devender Rao                             const ManagedObjectType& certs) {
8485968caeeSMarri Devender Rao                     if (ec)
8495968caeeSMarri Devender Rao                     {
8505968caeeSMarri Devender Rao                         BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
8515968caeeSMarri Devender Rao                         messages::internalError(asyncResp->res);
8525968caeeSMarri Devender Rao                         return;
8535968caeeSMarri Devender Rao                     }
8547e860f15SJohn Edward Broadbent                     nlohmann::json& members =
8557e860f15SJohn Edward Broadbent                         asyncResp->res.jsonValue["Members"];
8565968caeeSMarri Devender Rao                     members = nlohmann::json::array();
8575968caeeSMarri Devender Rao                     for (const auto& cert : certs)
8585968caeeSMarri Devender Rao                     {
8595968caeeSMarri Devender Rao                         long id = getIDFromURL(cert.first.str);
86037cce918SMarri Devender Rao                         if (id >= 0)
8615968caeeSMarri Devender Rao                         {
8625968caeeSMarri Devender Rao                             members.push_back(
8635968caeeSMarri Devender Rao                                 {{"@odata.id",
8645968caeeSMarri Devender Rao                                   "/redfish/v1/Managers/bmc/"
8655968caeeSMarri Devender Rao                                   "NetworkProtocol/HTTPS/Certificates/" +
8665968caeeSMarri Devender Rao                                       std::to_string(id)}});
8675968caeeSMarri Devender Rao                         }
8685968caeeSMarri Devender Rao                     }
8695968caeeSMarri Devender Rao                     asyncResp->res.jsonValue["Members@odata.count"] =
8705968caeeSMarri Devender Rao                         members.size();
8715968caeeSMarri Devender Rao                 },
87237cce918SMarri Devender Rao                 certs::httpsServiceName, certs::httpsObjectPath,
87337cce918SMarri Devender Rao                 certs::dbusObjManagerIntf, "GetManagedObjects");
8747e860f15SJohn Edward Broadbent         });
8755968caeeSMarri Devender Rao 
8767e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
8777e860f15SJohn Edward Broadbent                  "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
878ed398213SEd Tanous         .privileges(redfish::privileges::postCertificateCollection)
8797e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
8807e860f15SJohn Edward Broadbent             [](const crow::Request& req,
8817e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
8825968caeeSMarri Devender Rao                 BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost";
8838d1b46d7Szhanghch05 
8847e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue = {
8857e860f15SJohn Edward Broadbent                     {"Name", "HTTPS Certificate"},
8865968caeeSMarri Devender Rao                     {"Description", "HTTPS Certificate"}};
8875968caeeSMarri Devender Rao 
8887e860f15SJohn Edward Broadbent                 std::string certFileBody =
8897e860f15SJohn Edward Broadbent                     getCertificateFromReqBody(asyncResp, req);
89058eb238fSKowalski, Kamil 
89158eb238fSKowalski, Kamil                 if (certFileBody.empty())
89258eb238fSKowalski, Kamil                 {
8937e860f15SJohn Edward Broadbent                     BMCWEB_LOG_ERROR
8947e860f15SJohn Edward Broadbent                         << "Cannot get certificate from request body.";
895a08752f5SZbigniew Kurzynski                     messages::unrecognizedRequestBody(asyncResp->res);
89658eb238fSKowalski, Kamil                     return;
89758eb238fSKowalski, Kamil                 }
89858eb238fSKowalski, Kamil 
8995968caeeSMarri Devender Rao                 std::shared_ptr<CertificateFile> certFile =
90058eb238fSKowalski, Kamil                     std::make_shared<CertificateFile>(certFileBody);
9015968caeeSMarri Devender Rao 
9025968caeeSMarri Devender Rao                 crow::connections::systemBus->async_method_call(
903656ec7e3SZbigniew Kurzynski                     [asyncResp, certFile](const boost::system::error_code ec,
904656ec7e3SZbigniew Kurzynski                                           const std::string& objectPath) {
9055968caeeSMarri Devender Rao                         if (ec)
9065968caeeSMarri Devender Rao                         {
9075968caeeSMarri Devender Rao                             BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
9085968caeeSMarri Devender Rao                             messages::internalError(asyncResp->res);
9095968caeeSMarri Devender Rao                             return;
9105968caeeSMarri Devender Rao                         }
911656ec7e3SZbigniew Kurzynski                         long certId = getIDFromURL(objectPath);
912656ec7e3SZbigniew Kurzynski                         if (certId < 0)
913656ec7e3SZbigniew Kurzynski                         {
914656ec7e3SZbigniew Kurzynski                             BMCWEB_LOG_ERROR << "Invalid objectPath value"
915656ec7e3SZbigniew Kurzynski                                              << objectPath;
916656ec7e3SZbigniew Kurzynski                             messages::internalError(asyncResp->res);
917656ec7e3SZbigniew Kurzynski                             return;
918656ec7e3SZbigniew Kurzynski                         }
9195968caeeSMarri Devender Rao                         std::string certURL =
9205968caeeSMarri Devender Rao                             "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/"
9215968caeeSMarri Devender Rao                             "Certificates/" +
9225968caeeSMarri Devender Rao                             std::to_string(certId);
9237e860f15SJohn Edward Broadbent                         getCertificateProperties(
9247e860f15SJohn Edward Broadbent                             asyncResp, objectPath, certs::httpsServiceName,
9257e860f15SJohn Edward Broadbent                             certId, certURL, "HTTPS Certificate");
9265968caeeSMarri Devender Rao                         BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
9275968caeeSMarri Devender Rao                                          << certFile->getCertFilePath();
9285968caeeSMarri Devender Rao                     },
92937cce918SMarri Devender Rao                     certs::httpsServiceName, certs::httpsObjectPath,
9307e860f15SJohn Edward Broadbent                     certs::certInstallIntf, "Install",
9317e860f15SJohn Edward Broadbent                     certFile->getCertFilePath());
9327e860f15SJohn Edward Broadbent             });
9337e860f15SJohn Edward Broadbent } // requestRoutesHTTPSCertificateCollection
9345968caeeSMarri Devender Rao 
9355968caeeSMarri Devender Rao /**
93637cce918SMarri Devender Rao  * @brief Retrieve the certificates installed list and append to the
93737cce918SMarri Devender Rao  * response
93837cce918SMarri Devender Rao  *
93937cce918SMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
94037cce918SMarri Devender Rao  * @param[in] certURL  Path of the certificate object
94137cce918SMarri Devender Rao  * @param[in] path  Path of the D-Bus service object
94237cce918SMarri Devender Rao  * @return None
94337cce918SMarri Devender Rao  */
944*4f48d5f6SEd Tanous inline void
945*4f48d5f6SEd Tanous     getCertificateLocations(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
9468d1b46d7Szhanghch05                             const std::string& certURL, const std::string& path,
94737cce918SMarri Devender Rao                             const std::string& service)
94837cce918SMarri Devender Rao {
94937cce918SMarri Devender Rao     BMCWEB_LOG_DEBUG << "getCertificateLocations URI=" << certURL
95037cce918SMarri Devender Rao                      << " Path=" << path << " service= " << service;
95137cce918SMarri Devender Rao     crow::connections::systemBus->async_method_call(
95237cce918SMarri Devender Rao         [asyncResp, certURL](const boost::system::error_code ec,
95337cce918SMarri Devender Rao                              const ManagedObjectType& certs) {
95437cce918SMarri Devender Rao             if (ec)
95537cce918SMarri Devender Rao             {
9569c8e039eSJonathan Doman                 BMCWEB_LOG_WARNING
9579c8e039eSJonathan Doman                     << "Certificate collection query failed: " << ec
9589c8e039eSJonathan Doman                     << ", skipping " << certURL;
95937cce918SMarri Devender Rao                 return;
96037cce918SMarri Devender Rao             }
96137cce918SMarri Devender Rao             nlohmann::json& links =
96237cce918SMarri Devender Rao                 asyncResp->res.jsonValue["Links"]["Certificates"];
96337cce918SMarri Devender Rao             for (auto& cert : certs)
96437cce918SMarri Devender Rao             {
96537cce918SMarri Devender Rao                 long id = getIDFromURL(cert.first.str);
96637cce918SMarri Devender Rao                 if (id >= 0)
96737cce918SMarri Devender Rao                 {
96837cce918SMarri Devender Rao                     links.push_back(
96937cce918SMarri Devender Rao                         {{"@odata.id", certURL + std::to_string(id)}});
97037cce918SMarri Devender Rao                 }
97137cce918SMarri Devender Rao             }
97237cce918SMarri Devender Rao             asyncResp->res.jsonValue["Links"]["Certificates@odata.count"] =
97337cce918SMarri Devender Rao                 links.size();
97437cce918SMarri Devender Rao         },
97537cce918SMarri Devender Rao         service, path, certs::dbusObjManagerIntf, "GetManagedObjects");
9765968caeeSMarri Devender Rao }
9777e860f15SJohn Edward Broadbent 
9787e860f15SJohn Edward Broadbent /**
9797e860f15SJohn Edward Broadbent  * The certificate location schema defines a resource that an administrator
9807e860f15SJohn Edward Broadbent  * can use in order to locate all certificates installed on a given service.
9817e860f15SJohn Edward Broadbent  */
9827e860f15SJohn Edward Broadbent inline void requestRoutesCertificateLocations(App& app)
9837e860f15SJohn Edward Broadbent {
9847e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/")
985ed398213SEd Tanous         .privileges(redfish::privileges::getCertificateLocations)
9867e860f15SJohn Edward Broadbent         .methods(
9877e860f15SJohn Edward Broadbent             boost::beast::http::verb::
9887e860f15SJohn Edward Broadbent                 get)([](const crow::Request&,
9897e860f15SJohn Edward Broadbent                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
9907e860f15SJohn Edward Broadbent             asyncResp->res.jsonValue = {
9917e860f15SJohn Edward Broadbent                 {"@odata.id",
9927e860f15SJohn Edward Broadbent                  "/redfish/v1/CertificateService/CertificateLocations"},
9937e860f15SJohn Edward Broadbent                 {"@odata.type",
9947e860f15SJohn Edward Broadbent                  "#CertificateLocations.v1_0_0.CertificateLocations"},
9957e860f15SJohn Edward Broadbent                 {"Name", "Certificate Locations"},
9967e860f15SJohn Edward Broadbent                 {"Id", "CertificateLocations"},
9977e860f15SJohn Edward Broadbent                 {"Description",
9987e860f15SJohn Edward Broadbent                  "Defines a resource that an administrator can use in order to "
9997e860f15SJohn Edward Broadbent                  "locate all certificates installed on a given service"}};
10007e860f15SJohn Edward Broadbent 
10017e860f15SJohn Edward Broadbent             nlohmann::json& links =
10027e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["Links"]["Certificates"];
10037e860f15SJohn Edward Broadbent             links = nlohmann::json::array();
10047e860f15SJohn Edward Broadbent             getCertificateLocations(
10057e860f15SJohn Edward Broadbent                 asyncResp,
10067e860f15SJohn Edward Broadbent                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/",
10077e860f15SJohn Edward Broadbent                 certs::httpsObjectPath, certs::httpsServiceName);
10087e860f15SJohn Edward Broadbent             getCertificateLocations(
10097e860f15SJohn Edward Broadbent                 asyncResp, "/redfish/v1/AccountService/LDAP/Certificates/",
10107e860f15SJohn Edward Broadbent                 certs::ldapObjectPath, certs::ldapServiceName);
10117e860f15SJohn Edward Broadbent             getCertificateLocations(
10127e860f15SJohn Edward Broadbent                 asyncResp, "/redfish/v1/Managers/bmc/Truststore/Certificates/",
10137e860f15SJohn Edward Broadbent                 certs::authorityObjectPath, certs::authorityServiceName);
10147e860f15SJohn Edward Broadbent         });
10157e860f15SJohn Edward Broadbent }
10167e860f15SJohn Edward Broadbent // requestRoutesCertificateLocations
101737cce918SMarri Devender Rao 
101837cce918SMarri Devender Rao /**
101937cce918SMarri Devender Rao  * Collection of LDAP certificates
102037cce918SMarri Devender Rao  */
10217e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificateCollection(App& app)
102237cce918SMarri Devender Rao {
10237e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
1024ed398213SEd Tanous         .privileges(redfish::privileges::getCertificateCollection)
10257e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
10267e860f15SJohn Edward Broadbent             [](const crow::Request&,
10277e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
10288d1b46d7Szhanghch05                 asyncResp->res.jsonValue = {
10297e860f15SJohn Edward Broadbent                     {"@odata.id",
10307e860f15SJohn Edward Broadbent                      "/redfish/v1/AccountService/LDAP/Certificates"},
10317e860f15SJohn Edward Broadbent                     {"@odata.type",
10327e860f15SJohn Edward Broadbent                      "#CertificateCollection.CertificateCollection"},
103337cce918SMarri Devender Rao                     {"Name", "LDAP Certificates Collection"},
10347e860f15SJohn Edward Broadbent                     {"Description",
10357e860f15SJohn Edward Broadbent                      "A Collection of LDAP certificate instances"}};
10368d1b46d7Szhanghch05 
103737cce918SMarri Devender Rao                 crow::connections::systemBus->async_method_call(
103837cce918SMarri Devender Rao                     [asyncResp](const boost::system::error_code ec,
103937cce918SMarri Devender Rao                                 const ManagedObjectType& certs) {
10407e860f15SJohn Edward Broadbent                         nlohmann::json& members =
10417e860f15SJohn Edward Broadbent                             asyncResp->res.jsonValue["Members"];
10429c8e039eSJonathan Doman                         nlohmann::json& count =
10439c8e039eSJonathan Doman                             asyncResp->res.jsonValue["Members@odata.count"];
10449c8e039eSJonathan Doman                         members = nlohmann::json::array();
10459c8e039eSJonathan Doman                         count = 0;
104637cce918SMarri Devender Rao                         if (ec)
104737cce918SMarri Devender Rao                         {
10487e860f15SJohn Edward Broadbent                             BMCWEB_LOG_WARNING
10497e860f15SJohn Edward Broadbent                                 << "LDAP certificate query failed: " << ec;
105037cce918SMarri Devender Rao                             return;
105137cce918SMarri Devender Rao                         }
105237cce918SMarri Devender Rao                         for (const auto& cert : certs)
105337cce918SMarri Devender Rao                         {
105437cce918SMarri Devender Rao                             long id = getIDFromURL(cert.first.str);
105537cce918SMarri Devender Rao                             if (id >= 0)
105637cce918SMarri Devender Rao                             {
105737cce918SMarri Devender Rao                                 members.push_back(
105837cce918SMarri Devender Rao                                     {{"@odata.id", "/redfish/v1/AccountService/"
105937cce918SMarri Devender Rao                                                    "LDAP/Certificates/" +
106037cce918SMarri Devender Rao                                                        std::to_string(id)}});
106137cce918SMarri Devender Rao                             }
106237cce918SMarri Devender Rao                         }
10639c8e039eSJonathan Doman                         count = members.size();
106437cce918SMarri Devender Rao                     },
106537cce918SMarri Devender Rao                     certs::ldapServiceName, certs::ldapObjectPath,
106637cce918SMarri Devender Rao                     certs::dbusObjManagerIntf, "GetManagedObjects");
10677e860f15SJohn Edward Broadbent             });
106837cce918SMarri Devender Rao 
10697e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
1070ed398213SEd Tanous         .privileges(redfish::privileges::postCertificateCollection)
10717e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
10727e860f15SJohn Edward Broadbent             [](const crow::Request& req,
10737e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
10747e860f15SJohn Edward Broadbent                 std::string certFileBody =
10757e860f15SJohn Edward Broadbent                     getCertificateFromReqBody(asyncResp, req);
107658eb238fSKowalski, Kamil 
107758eb238fSKowalski, Kamil                 if (certFileBody.empty())
107858eb238fSKowalski, Kamil                 {
10797e860f15SJohn Edward Broadbent                     BMCWEB_LOG_ERROR
10807e860f15SJohn Edward Broadbent                         << "Cannot get certificate from request body.";
1081a08752f5SZbigniew Kurzynski                     messages::unrecognizedRequestBody(asyncResp->res);
108258eb238fSKowalski, Kamil                     return;
108358eb238fSKowalski, Kamil                 }
108458eb238fSKowalski, Kamil 
108558eb238fSKowalski, Kamil                 std::shared_ptr<CertificateFile> certFile =
108658eb238fSKowalski, Kamil                     std::make_shared<CertificateFile>(certFileBody);
108758eb238fSKowalski, Kamil 
108837cce918SMarri Devender Rao                 crow::connections::systemBus->async_method_call(
1089656ec7e3SZbigniew Kurzynski                     [asyncResp, certFile](const boost::system::error_code ec,
1090656ec7e3SZbigniew Kurzynski                                           const std::string& objectPath) {
109137cce918SMarri Devender Rao                         if (ec)
109237cce918SMarri Devender Rao                         {
109337cce918SMarri Devender Rao                             BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
109437cce918SMarri Devender Rao                             messages::internalError(asyncResp->res);
109537cce918SMarri Devender Rao                             return;
109637cce918SMarri Devender Rao                         }
1097656ec7e3SZbigniew Kurzynski                         long certId = getIDFromURL(objectPath);
1098656ec7e3SZbigniew Kurzynski                         if (certId < 0)
1099656ec7e3SZbigniew Kurzynski                         {
1100656ec7e3SZbigniew Kurzynski                             BMCWEB_LOG_ERROR << "Invalid objectPath value"
1101656ec7e3SZbigniew Kurzynski                                              << objectPath;
1102656ec7e3SZbigniew Kurzynski                             messages::internalError(asyncResp->res);
1103656ec7e3SZbigniew Kurzynski                             return;
1104656ec7e3SZbigniew Kurzynski                         }
110537cce918SMarri Devender Rao                         std::string certURL =
110637cce918SMarri Devender Rao                             "/redfish/v1/AccountService/LDAP/Certificates/" +
110737cce918SMarri Devender Rao                             std::to_string(certId);
110837cce918SMarri Devender Rao                         getCertificateProperties(asyncResp, objectPath,
110937cce918SMarri Devender Rao                                                  certs::ldapServiceName, certId,
111037cce918SMarri Devender Rao                                                  certURL, "LDAP Certificate");
111137cce918SMarri Devender Rao                         BMCWEB_LOG_DEBUG << "LDAP certificate install file="
111237cce918SMarri Devender Rao                                          << certFile->getCertFilePath();
111337cce918SMarri Devender Rao                     },
111437cce918SMarri Devender Rao                     certs::ldapServiceName, certs::ldapObjectPath,
11157e860f15SJohn Edward Broadbent                     certs::certInstallIntf, "Install",
11167e860f15SJohn Edward Broadbent                     certFile->getCertFilePath());
11177e860f15SJohn Edward Broadbent             });
11187e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificateCollection
111937cce918SMarri Devender Rao 
112037cce918SMarri Devender Rao /**
112137cce918SMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
112237cce918SMarri Devender Rao  * of a component, account or service.
112337cce918SMarri Devender Rao  */
11247e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificate(App& app)
112537cce918SMarri Devender Rao {
11267e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/")
1127ed398213SEd Tanous         .privileges(redfish::privileges::getCertificate)
11287e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
11297e860f15SJohn Edward Broadbent             [](const crow::Request& req,
11307e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
11317e860f15SJohn Edward Broadbent                const std::string&) {
113237cce918SMarri Devender Rao                 long id = getIDFromURL(req.url);
113337cce918SMarri Devender Rao                 if (id < 0)
113437cce918SMarri Devender Rao                 {
113537cce918SMarri Devender Rao                     BMCWEB_LOG_ERROR << "Invalid url value" << req.url;
113637cce918SMarri Devender Rao                     messages::internalError(asyncResp->res);
113737cce918SMarri Devender Rao                     return;
113837cce918SMarri Devender Rao                 }
11397e860f15SJohn Edward Broadbent                 BMCWEB_LOG_DEBUG << "LDAP Certificate ID="
11407e860f15SJohn Edward Broadbent                                  << std::to_string(id);
11417e860f15SJohn Edward Broadbent                 std::string certURL =
11427e860f15SJohn Edward Broadbent                     "/redfish/v1/AccountService/LDAP/Certificates/" +
114337cce918SMarri Devender Rao                     std::to_string(id);
114437cce918SMarri Devender Rao                 std::string objectPath = certs::ldapObjectPath;
114537cce918SMarri Devender Rao                 objectPath += "/";
114637cce918SMarri Devender Rao                 objectPath += std::to_string(id);
11477e860f15SJohn Edward Broadbent                 getCertificateProperties(asyncResp, objectPath,
11487e860f15SJohn Edward Broadbent                                          certs::ldapServiceName, id, certURL,
11497e860f15SJohn Edward Broadbent                                          "LDAP Certificate");
11507e860f15SJohn Edward Broadbent             });
11517e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificate
1152cfcd5f6bSMarri Devender Rao /**
1153cfcd5f6bSMarri Devender Rao  * Collection of TrustStoreCertificate certificates
1154cfcd5f6bSMarri Devender Rao  */
11557e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificateCollection(App& app)
1156cfcd5f6bSMarri Devender Rao {
11577e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
1158ed398213SEd Tanous         .privileges(redfish::privileges::getCertificate)
11597e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
11607e860f15SJohn Edward Broadbent             [](const crow::Request&,
11617e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
11628d1b46d7Szhanghch05                 asyncResp->res.jsonValue = {
11637e860f15SJohn Edward Broadbent                     {"@odata.id",
11647e860f15SJohn Edward Broadbent                      "/redfish/v1/Managers/bmc/Truststore/Certificates/"},
11657e860f15SJohn Edward Broadbent                     {"@odata.type",
11667e860f15SJohn Edward Broadbent                      "#CertificateCollection.CertificateCollection"},
1167cfcd5f6bSMarri Devender Rao                     {"Name", "TrustStore Certificates Collection"},
1168cfcd5f6bSMarri Devender Rao                     {"Description",
1169cfcd5f6bSMarri Devender Rao                      "A Collection of TrustStore certificate instances"}};
11708d1b46d7Szhanghch05 
1171cfcd5f6bSMarri Devender Rao                 crow::connections::systemBus->async_method_call(
1172cfcd5f6bSMarri Devender Rao                     [asyncResp](const boost::system::error_code ec,
1173cfcd5f6bSMarri Devender Rao                                 const ManagedObjectType& certs) {
1174cfcd5f6bSMarri Devender Rao                         if (ec)
1175cfcd5f6bSMarri Devender Rao                         {
1176cfcd5f6bSMarri Devender Rao                             BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
1177cfcd5f6bSMarri Devender Rao                             messages::internalError(asyncResp->res);
1178cfcd5f6bSMarri Devender Rao                             return;
1179cfcd5f6bSMarri Devender Rao                         }
11807e860f15SJohn Edward Broadbent                         nlohmann::json& members =
11817e860f15SJohn Edward Broadbent                             asyncResp->res.jsonValue["Members"];
1182cfcd5f6bSMarri Devender Rao                         members = nlohmann::json::array();
1183cfcd5f6bSMarri Devender Rao                         for (const auto& cert : certs)
1184cfcd5f6bSMarri Devender Rao                         {
1185cfcd5f6bSMarri Devender Rao                             long id = getIDFromURL(cert.first.str);
1186cfcd5f6bSMarri Devender Rao                             if (id >= 0)
1187cfcd5f6bSMarri Devender Rao                             {
1188cfcd5f6bSMarri Devender Rao                                 members.push_back(
1189cfcd5f6bSMarri Devender Rao                                     {{"@odata.id", "/redfish/v1/Managers/bmc/"
1190cfcd5f6bSMarri Devender Rao                                                    "Truststore/Certificates/" +
1191cfcd5f6bSMarri Devender Rao                                                        std::to_string(id)}});
1192cfcd5f6bSMarri Devender Rao                             }
1193cfcd5f6bSMarri Devender Rao                         }
1194cfcd5f6bSMarri Devender Rao                         asyncResp->res.jsonValue["Members@odata.count"] =
1195cfcd5f6bSMarri Devender Rao                             members.size();
1196cfcd5f6bSMarri Devender Rao                     },
1197cfcd5f6bSMarri Devender Rao                     certs::authorityServiceName, certs::authorityObjectPath,
1198cfcd5f6bSMarri Devender Rao                     certs::dbusObjManagerIntf, "GetManagedObjects");
11997e860f15SJohn Edward Broadbent             });
1200cfcd5f6bSMarri Devender Rao 
12017e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
1202ed398213SEd Tanous         .privileges(redfish::privileges::postCertificateCollection)
12037e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
12047e860f15SJohn Edward Broadbent             [](const crow::Request& req,
12057e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
12067e860f15SJohn Edward Broadbent                 std::string certFileBody =
12077e860f15SJohn Edward Broadbent                     getCertificateFromReqBody(asyncResp, req);
1208a08752f5SZbigniew Kurzynski 
1209a08752f5SZbigniew Kurzynski                 if (certFileBody.empty())
1210a08752f5SZbigniew Kurzynski                 {
12117e860f15SJohn Edward Broadbent                     BMCWEB_LOG_ERROR
12127e860f15SJohn Edward Broadbent                         << "Cannot get certificate from request body.";
1213a08752f5SZbigniew Kurzynski                     messages::unrecognizedRequestBody(asyncResp->res);
1214a08752f5SZbigniew Kurzynski                     return;
1215a08752f5SZbigniew Kurzynski                 }
1216a08752f5SZbigniew Kurzynski 
1217a08752f5SZbigniew Kurzynski                 std::shared_ptr<CertificateFile> certFile =
1218a08752f5SZbigniew Kurzynski                     std::make_shared<CertificateFile>(certFileBody);
1219cfcd5f6bSMarri Devender Rao                 crow::connections::systemBus->async_method_call(
1220656ec7e3SZbigniew Kurzynski                     [asyncResp, certFile](const boost::system::error_code ec,
1221656ec7e3SZbigniew Kurzynski                                           const std::string& objectPath) {
1222cfcd5f6bSMarri Devender Rao                         if (ec)
1223cfcd5f6bSMarri Devender Rao                         {
1224cfcd5f6bSMarri Devender Rao                             BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
1225cfcd5f6bSMarri Devender Rao                             messages::internalError(asyncResp->res);
1226cfcd5f6bSMarri Devender Rao                             return;
1227cfcd5f6bSMarri Devender Rao                         }
1228656ec7e3SZbigniew Kurzynski                         long certId = getIDFromURL(objectPath);
1229656ec7e3SZbigniew Kurzynski                         if (certId < 0)
1230656ec7e3SZbigniew Kurzynski                         {
1231656ec7e3SZbigniew Kurzynski                             BMCWEB_LOG_ERROR << "Invalid objectPath value"
1232656ec7e3SZbigniew Kurzynski                                              << objectPath;
1233656ec7e3SZbigniew Kurzynski                             messages::internalError(asyncResp->res);
1234656ec7e3SZbigniew Kurzynski                             return;
1235656ec7e3SZbigniew Kurzynski                         }
1236cfcd5f6bSMarri Devender Rao                         std::string certURL = "/redfish/v1/Managers/bmc/"
1237cfcd5f6bSMarri Devender Rao                                               "Truststore/Certificates/" +
1238cfcd5f6bSMarri Devender Rao                                               std::to_string(certId);
1239656ec7e3SZbigniew Kurzynski 
12407e860f15SJohn Edward Broadbent                         getCertificateProperties(
12417e860f15SJohn Edward Broadbent                             asyncResp, objectPath, certs::authorityServiceName,
12427e860f15SJohn Edward Broadbent                             certId, certURL, "TrustStore Certificate");
12437e860f15SJohn Edward Broadbent                         BMCWEB_LOG_DEBUG
12447e860f15SJohn Edward Broadbent                             << "TrustStore certificate install file="
1245cfcd5f6bSMarri Devender Rao                             << certFile->getCertFilePath();
1246cfcd5f6bSMarri Devender Rao                     },
1247cfcd5f6bSMarri Devender Rao                     certs::authorityServiceName, certs::authorityObjectPath,
12487e860f15SJohn Edward Broadbent                     certs::certInstallIntf, "Install",
12497e860f15SJohn Edward Broadbent                     certFile->getCertFilePath());
12507e860f15SJohn Edward Broadbent             });
12517e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificateCollection
1252cfcd5f6bSMarri Devender Rao 
1253cfcd5f6bSMarri Devender Rao /**
1254cfcd5f6bSMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
1255cfcd5f6bSMarri Devender Rao  * of a component, account or service.
1256cfcd5f6bSMarri Devender Rao  */
12577e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificate(App& app)
1258cfcd5f6bSMarri Devender Rao {
12597e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
1260ed398213SEd Tanous         .privileges(redfish::privileges::getCertificate)
12617e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
12627e860f15SJohn Edward Broadbent             [](const crow::Request& req,
12637e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
12647e860f15SJohn Edward Broadbent                const std::string&) {
1265cfcd5f6bSMarri Devender Rao                 long id = getIDFromURL(req.url);
1266cfcd5f6bSMarri Devender Rao                 if (id < 0)
1267cfcd5f6bSMarri Devender Rao                 {
1268cfcd5f6bSMarri Devender Rao                     BMCWEB_LOG_ERROR << "Invalid url value" << req.url;
1269cfcd5f6bSMarri Devender Rao                     messages::internalError(asyncResp->res);
1270cfcd5f6bSMarri Devender Rao                     return;
1271cfcd5f6bSMarri Devender Rao                 }
1272cfcd5f6bSMarri Devender Rao                 BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doGet ID="
1273cfcd5f6bSMarri Devender Rao                                  << std::to_string(id);
1274cfcd5f6bSMarri Devender Rao                 std::string certURL =
1275cfcd5f6bSMarri Devender Rao                     "/redfish/v1/Managers/bmc/Truststore/Certificates/" +
1276cfcd5f6bSMarri Devender Rao                     std::to_string(id);
1277cfcd5f6bSMarri Devender Rao                 std::string objectPath = certs::authorityObjectPath;
1278cfcd5f6bSMarri Devender Rao                 objectPath += "/";
1279cfcd5f6bSMarri Devender Rao                 objectPath += std::to_string(id);
1280cfcd5f6bSMarri Devender Rao                 getCertificateProperties(asyncResp, objectPath,
12817e860f15SJohn Edward Broadbent                                          certs::authorityServiceName, id,
12827e860f15SJohn Edward Broadbent                                          certURL, "TrustStore Certificate");
12837e860f15SJohn Edward Broadbent             });
128407a60299SZbigniew Kurzynski 
12857e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
1286ed398213SEd Tanous         .privileges(redfish::privileges::deleteCertificate)
12877e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::delete_)(
12887e860f15SJohn Edward Broadbent             [](const crow::Request& req,
12897e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
12907e860f15SJohn Edward Broadbent                const std::string& param) {
12917e860f15SJohn Edward Broadbent                 if (param.empty())
129207a60299SZbigniew Kurzynski                 {
129307a60299SZbigniew Kurzynski                     messages::internalError(asyncResp->res);
129407a60299SZbigniew Kurzynski                     return;
129507a60299SZbigniew Kurzynski                 }
129607a60299SZbigniew Kurzynski 
129707a60299SZbigniew Kurzynski                 long id = getIDFromURL(req.url);
129807a60299SZbigniew Kurzynski                 if (id < 0)
129907a60299SZbigniew Kurzynski                 {
130007a60299SZbigniew Kurzynski                     BMCWEB_LOG_ERROR << "Invalid url value: " << req.url;
13017e860f15SJohn Edward Broadbent                     messages::resourceNotFound(asyncResp->res,
13027e860f15SJohn Edward Broadbent                                                "TrustStore Certificate",
130307a60299SZbigniew Kurzynski                                                std::string(req.url));
130407a60299SZbigniew Kurzynski                     return;
130507a60299SZbigniew Kurzynski                 }
130607a60299SZbigniew Kurzynski                 BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doDelete ID="
130707a60299SZbigniew Kurzynski                                  << std::to_string(id);
130807a60299SZbigniew Kurzynski                 std::string certPath = certs::authorityObjectPath;
130907a60299SZbigniew Kurzynski                 certPath += "/";
131007a60299SZbigniew Kurzynski                 certPath += std::to_string(id);
131107a60299SZbigniew Kurzynski 
131207a60299SZbigniew Kurzynski                 crow::connections::systemBus->async_method_call(
131307a60299SZbigniew Kurzynski                     [asyncResp, id](const boost::system::error_code ec) {
131407a60299SZbigniew Kurzynski                         if (ec)
131507a60299SZbigniew Kurzynski                         {
131607a60299SZbigniew Kurzynski                             messages::resourceNotFound(asyncResp->res,
131707a60299SZbigniew Kurzynski                                                        "TrustStore Certificate",
131807a60299SZbigniew Kurzynski                                                        std::to_string(id));
131907a60299SZbigniew Kurzynski                             return;
132007a60299SZbigniew Kurzynski                         }
132107a60299SZbigniew Kurzynski                         BMCWEB_LOG_INFO << "Certificate deleted";
13227e860f15SJohn Edward Broadbent                         asyncResp->res.result(
13237e860f15SJohn Edward Broadbent                             boost::beast::http::status::no_content);
132407a60299SZbigniew Kurzynski                     },
132507a60299SZbigniew Kurzynski                     certs::authorityServiceName, certPath, certs::objDeleteIntf,
132607a60299SZbigniew Kurzynski                     "Delete");
13277e860f15SJohn Edward Broadbent             });
13287e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificate
13295968caeeSMarri Devender Rao } // namespace redfish
1330