xref: /openbmc/bmcweb/features/redfish/lib/certificate_service.hpp (revision b9d36b4791d77a47e1f3c5c4564fcdf7cc68c115)
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>
6168e20c1SEd Tanous #include <dbus_utility.hpp>
7ed398213SEd Tanous #include <registries/privilege_registry.hpp>
81214b7e7SGunnar Mills 
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             }
700fda0f12SGeorge Liu             asyncResp->res
710fda0f12SGeorge Liu                 .jsonValue["Actions"]
720fda0f12SGeorge Liu                           ["#CertificateService.ReplaceCertificate"] = {
730fda0f12SGeorge Liu                 {"target",
740fda0f12SGeorge Liu                  "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate"},
755968caeeSMarri Devender Rao                 {"CertificateType@Redfish.AllowableValues", {"PEM"}}};
767e860f15SJohn Edward Broadbent             asyncResp->res
777e860f15SJohn Edward Broadbent                 .jsonValue["Actions"]["#CertificateService.GenerateCSR"] = {
780fda0f12SGeorge Liu                 {"target",
790fda0f12SGeorge Liu                  "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR"}};
807e860f15SJohn Edward Broadbent         });
817e860f15SJohn Edward Broadbent } // requestRoutesCertificateService
8237cce918SMarri Devender Rao 
835968caeeSMarri Devender Rao /**
845968caeeSMarri Devender Rao  * @brief Find the ID specified in the URL
855968caeeSMarri Devender Rao  * Finds the numbers specified after the last "/" in the URL and returns.
865968caeeSMarri Devender Rao  * @param[in] path URL
875968caeeSMarri Devender Rao  * @return -1 on failure and number on success
885968caeeSMarri Devender Rao  */
8923a21a1cSEd Tanous inline long getIDFromURL(const std::string_view url)
905968caeeSMarri Devender Rao {
91f23b7296SEd Tanous     std::size_t found = url.rfind('/');
925968caeeSMarri Devender Rao     if (found == std::string::npos)
935968caeeSMarri Devender Rao     {
945968caeeSMarri Devender Rao         return -1;
955968caeeSMarri Devender Rao     }
96e6604b11SIwona Klimaszewska 
975968caeeSMarri Devender Rao     if ((found + 1) < url.length())
985968caeeSMarri Devender Rao     {
995968caeeSMarri Devender Rao         std::string_view str = url.substr(found + 1);
100e6604b11SIwona Klimaszewska 
101e6604b11SIwona Klimaszewska         return boost::convert<long>(str, boost::cnv::strtol()).value_or(-1);
1025968caeeSMarri Devender Rao     }
103e6604b11SIwona Klimaszewska 
1045968caeeSMarri Devender Rao     return -1;
1055968caeeSMarri Devender Rao }
1065968caeeSMarri Devender Rao 
1078d1b46d7Szhanghch05 inline std::string getCertificateFromReqBody(
1088d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
10958eb238fSKowalski, Kamil     const crow::Request& req)
11058eb238fSKowalski, Kamil {
11158eb238fSKowalski, Kamil     nlohmann::json reqJson = nlohmann::json::parse(req.body, nullptr, false);
11258eb238fSKowalski, Kamil 
11358eb238fSKowalski, Kamil     if (reqJson.is_discarded())
11458eb238fSKowalski, Kamil     {
11558eb238fSKowalski, Kamil         // We did not receive JSON request, proceed as it is RAW data
11658eb238fSKowalski, Kamil         return req.body;
11758eb238fSKowalski, Kamil     }
11858eb238fSKowalski, Kamil 
11958eb238fSKowalski, Kamil     std::string certificate;
12058eb238fSKowalski, Kamil     std::optional<std::string> certificateType = "PEM";
12158eb238fSKowalski, Kamil 
12215ed6780SWilly Tu     if (!json_util::readJsonPatch(req, asyncResp->res, "CertificateString",
12315ed6780SWilly Tu                                   certificate, "CertificateType",
12415ed6780SWilly Tu                                   certificateType))
12558eb238fSKowalski, Kamil     {
12658eb238fSKowalski, Kamil         BMCWEB_LOG_ERROR << "Required parameters are missing";
12758eb238fSKowalski, Kamil         messages::internalError(asyncResp->res);
128abb93cddSEd Tanous         return {};
12958eb238fSKowalski, Kamil     }
13058eb238fSKowalski, Kamil 
13158eb238fSKowalski, Kamil     if (*certificateType != "PEM")
13258eb238fSKowalski, Kamil     {
13358eb238fSKowalski, Kamil         messages::propertyValueNotInList(asyncResp->res, *certificateType,
13458eb238fSKowalski, Kamil                                          "CertificateType");
135abb93cddSEd Tanous         return {};
13658eb238fSKowalski, Kamil     }
13758eb238fSKowalski, Kamil 
13858eb238fSKowalski, Kamil     return certificate;
13958eb238fSKowalski, Kamil }
14058eb238fSKowalski, Kamil 
1415968caeeSMarri Devender Rao /**
1425968caeeSMarri Devender Rao  * Class to create a temporary certificate file for uploading to system
1435968caeeSMarri Devender Rao  */
1445968caeeSMarri Devender Rao class CertificateFile
1455968caeeSMarri Devender Rao {
1465968caeeSMarri Devender Rao   public:
1475968caeeSMarri Devender Rao     CertificateFile() = delete;
1485968caeeSMarri Devender Rao     CertificateFile(const CertificateFile&) = delete;
1495968caeeSMarri Devender Rao     CertificateFile& operator=(const CertificateFile&) = delete;
1505968caeeSMarri Devender Rao     CertificateFile(CertificateFile&&) = delete;
1515968caeeSMarri Devender Rao     CertificateFile& operator=(CertificateFile&&) = delete;
1525968caeeSMarri Devender Rao     CertificateFile(const std::string& certString)
1535968caeeSMarri Devender Rao     {
15472d52d25SEd Tanous         std::array<char, 18> dirTemplate = {'/', 't', 'm', 'p', '/', 'C',
1555207438cSEd Tanous                                             'e', 'r', 't', 's', '.', 'X',
1565207438cSEd Tanous                                             'X', 'X', 'X', 'X', 'X', '\0'};
1575207438cSEd Tanous         char* tempDirectory = mkdtemp(dirTemplate.data());
158e662eae8SEd Tanous         if (tempDirectory != nullptr)
1595968caeeSMarri Devender Rao         {
1605968caeeSMarri Devender Rao             certDirectory = tempDirectory;
1615968caeeSMarri Devender Rao             certificateFile = certDirectory / "cert.pem";
1625968caeeSMarri Devender Rao             std::ofstream out(certificateFile, std::ofstream::out |
1635968caeeSMarri Devender Rao                                                    std::ofstream::binary |
1645968caeeSMarri Devender Rao                                                    std::ofstream::trunc);
1655968caeeSMarri Devender Rao             out << certString;
1665968caeeSMarri Devender Rao             out.close();
1678cc8edecSEd Tanous             BMCWEB_LOG_DEBUG << "Creating certificate file"
1688cc8edecSEd Tanous                              << certificateFile.string();
1695968caeeSMarri Devender Rao         }
1705968caeeSMarri Devender Rao     }
1715968caeeSMarri Devender Rao     ~CertificateFile()
1725968caeeSMarri Devender Rao     {
1735968caeeSMarri Devender Rao         if (std::filesystem::exists(certDirectory))
1745968caeeSMarri Devender Rao         {
1758cc8edecSEd Tanous             BMCWEB_LOG_DEBUG << "Removing certificate file"
1768cc8edecSEd Tanous                              << certificateFile.string();
17723a21a1cSEd Tanous             std::error_code ec;
17823a21a1cSEd Tanous             std::filesystem::remove_all(certDirectory, ec);
17923a21a1cSEd Tanous             if (ec)
1805968caeeSMarri Devender Rao             {
1815968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "Failed to remove temp directory"
1828cc8edecSEd Tanous                                  << certDirectory.string();
1835968caeeSMarri Devender Rao             }
1845968caeeSMarri Devender Rao         }
1855968caeeSMarri Devender Rao     }
1865968caeeSMarri Devender Rao     std::string getCertFilePath()
1875968caeeSMarri Devender Rao     {
1885968caeeSMarri Devender Rao         return certificateFile;
1895968caeeSMarri Devender Rao     }
1905968caeeSMarri Devender Rao 
1915968caeeSMarri Devender Rao   private:
1925968caeeSMarri Devender Rao     std::filesystem::path certificateFile;
1935968caeeSMarri Devender Rao     std::filesystem::path certDirectory;
1945968caeeSMarri Devender Rao };
1955968caeeSMarri Devender Rao 
19630215816SMarri Devender Rao static std::unique_ptr<sdbusplus::bus::match::match> csrMatcher;
19730215816SMarri Devender Rao /**
19830215816SMarri Devender Rao  * @brief Read data from CSR D-bus object and set to response
19930215816SMarri Devender Rao  *
20030215816SMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
20130215816SMarri Devender Rao  * @param[in] certURI Link to certifiate collection URI
20230215816SMarri Devender Rao  * @param[in] service D-Bus service name
20330215816SMarri Devender Rao  * @param[in] certObjPath certificate D-Bus object path
20430215816SMarri Devender Rao  * @param[in] csrObjPath CSR D-Bus object path
20530215816SMarri Devender Rao  * @return None
20630215816SMarri Devender Rao  */
2078d1b46d7Szhanghch05 static void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
20830215816SMarri Devender Rao                    const std::string& certURI, const std::string& service,
20930215816SMarri Devender Rao                    const std::string& certObjPath,
21030215816SMarri Devender Rao                    const std::string& csrObjPath)
21130215816SMarri Devender Rao {
21230215816SMarri Devender Rao     BMCWEB_LOG_DEBUG << "getCSR CertObjectPath" << certObjPath
21330215816SMarri Devender Rao                      << " CSRObjectPath=" << csrObjPath
21430215816SMarri Devender Rao                      << " service=" << service;
21530215816SMarri Devender Rao     crow::connections::systemBus->async_method_call(
21630215816SMarri Devender Rao         [asyncResp, certURI](const boost::system::error_code ec,
21730215816SMarri Devender Rao                              const std::string& csr) {
21830215816SMarri Devender Rao             if (ec)
21930215816SMarri Devender Rao             {
22030215816SMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
22130215816SMarri Devender Rao                 messages::internalError(asyncResp->res);
22230215816SMarri Devender Rao                 return;
22330215816SMarri Devender Rao             }
22430215816SMarri Devender Rao             if (csr.empty())
22530215816SMarri Devender Rao             {
22630215816SMarri Devender Rao                 BMCWEB_LOG_ERROR << "CSR read is empty";
22730215816SMarri Devender Rao                 messages::internalError(asyncResp->res);
22830215816SMarri Devender Rao                 return;
22930215816SMarri Devender Rao             }
23030215816SMarri Devender Rao             asyncResp->res.jsonValue["CSRString"] = csr;
23130215816SMarri Devender Rao             asyncResp->res.jsonValue["CertificateCollection"] = {
23230215816SMarri Devender Rao                 {"@odata.id", certURI}};
23330215816SMarri Devender Rao         },
23430215816SMarri Devender Rao         service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR");
23530215816SMarri Devender Rao }
23630215816SMarri Devender Rao 
23730215816SMarri Devender Rao /**
23830215816SMarri Devender Rao  * Action to Generate CSR
23930215816SMarri Devender Rao  */
2407e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionGenerateCSR(App& app)
24130215816SMarri Devender Rao {
2420fda0f12SGeorge Liu     BMCWEB_ROUTE(
2430fda0f12SGeorge Liu         app,
2440fda0f12SGeorge Liu         "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR/")
245ed398213SEd Tanous         // Incorrect Privilege;  Should be ConfigureManager
246ed398213SEd Tanous         //.privileges(redfish::privileges::postCertificateService)
247432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
2480fda0f12SGeorge Liu         .methods(
2490fda0f12SGeorge Liu             boost::beast::http::verb::
2500fda0f12SGeorge Liu                 post)([](const crow::Request& req,
2517e860f15SJohn Edward Broadbent                          const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2522c70f800SEd Tanous             static const int rsaKeyBitLength = 2048;
2538d1b46d7Szhanghch05 
25430215816SMarri Devender Rao             // Required parameters
25530215816SMarri Devender Rao             std::string city;
25630215816SMarri Devender Rao             std::string commonName;
25730215816SMarri Devender Rao             std::string country;
25830215816SMarri Devender Rao             std::string organization;
25930215816SMarri Devender Rao             std::string organizationalUnit;
26030215816SMarri Devender Rao             std::string state;
26130215816SMarri Devender Rao             nlohmann::json certificateCollection;
26230215816SMarri Devender Rao 
26330215816SMarri Devender Rao             // Optional parameters
26430215816SMarri Devender Rao             std::optional<std::vector<std::string>> optAlternativeNames =
26530215816SMarri Devender Rao                 std::vector<std::string>();
26630215816SMarri Devender Rao             std::optional<std::string> optContactPerson = "";
26730215816SMarri Devender Rao             std::optional<std::string> optChallengePassword = "";
26830215816SMarri Devender Rao             std::optional<std::string> optEmail = "";
26930215816SMarri Devender Rao             std::optional<std::string> optGivenName = "";
27030215816SMarri Devender Rao             std::optional<std::string> optInitials = "";
2712c70f800SEd Tanous             std::optional<int64_t> optKeyBitLength = rsaKeyBitLength;
272aaf3206fSVernon Mauery             std::optional<std::string> optKeyCurveId = "secp384r1";
27330215816SMarri Devender Rao             std::optional<std::string> optKeyPairAlgorithm = "EC";
27430215816SMarri Devender Rao             std::optional<std::vector<std::string>> optKeyUsage =
27530215816SMarri Devender Rao                 std::vector<std::string>();
27630215816SMarri Devender Rao             std::optional<std::string> optSurname = "";
27730215816SMarri Devender Rao             std::optional<std::string> optUnstructuredName = "";
27815ed6780SWilly Tu             if (!json_util::readJsonAction(
2790fda0f12SGeorge Liu                     req, asyncResp->res, "City", city, "CommonName", commonName,
2800fda0f12SGeorge Liu                     "ContactPerson", optContactPerson, "Country", country,
2810fda0f12SGeorge Liu                     "Organization", organization, "OrganizationalUnit",
2820fda0f12SGeorge Liu                     organizationalUnit, "State", state, "CertificateCollection",
2830fda0f12SGeorge Liu                     certificateCollection, "AlternativeNames",
2840fda0f12SGeorge Liu                     optAlternativeNames, "ChallengePassword",
2850fda0f12SGeorge Liu                     optChallengePassword, "Email", optEmail, "GivenName",
2860fda0f12SGeorge Liu                     optGivenName, "Initials", optInitials, "KeyBitLength",
2870fda0f12SGeorge Liu                     optKeyBitLength, "KeyCurveId", optKeyCurveId,
2880fda0f12SGeorge Liu                     "KeyPairAlgorithm", optKeyPairAlgorithm, "KeyUsage",
2890fda0f12SGeorge Liu                     optKeyUsage, "Surname", optSurname, "UnstructuredName",
2900fda0f12SGeorge Liu                     optUnstructuredName))
29130215816SMarri Devender Rao             {
29230215816SMarri Devender Rao                 return;
29330215816SMarri Devender Rao             }
29430215816SMarri Devender Rao 
29530215816SMarri Devender Rao             // bmcweb has no way to store or decode a private key challenge
2967e860f15SJohn Edward Broadbent             // password, which will likely cause bmcweb to crash on startup
2977e860f15SJohn Edward Broadbent             // if this is not set on a post so not allowing the user to set
2987e860f15SJohn Edward Broadbent             // value
29926f6976fSEd Tanous             if (!optChallengePassword->empty())
30030215816SMarri Devender Rao             {
3017e860f15SJohn Edward Broadbent                 messages::actionParameterNotSupported(
3027e860f15SJohn Edward Broadbent                     asyncResp->res, "GenerateCSR", "ChallengePassword");
30330215816SMarri Devender Rao                 return;
30430215816SMarri Devender Rao             }
30530215816SMarri Devender Rao 
30630215816SMarri Devender Rao             std::string certURI;
3077e860f15SJohn Edward Broadbent             if (!redfish::json_util::readJson(certificateCollection,
3087e860f15SJohn Edward Broadbent                                               asyncResp->res, "@odata.id",
3097e860f15SJohn Edward Broadbent                                               certURI))
31030215816SMarri Devender Rao             {
31130215816SMarri Devender Rao                 return;
31230215816SMarri Devender Rao             }
31330215816SMarri Devender Rao 
31430215816SMarri Devender Rao             std::string objectPath;
31530215816SMarri Devender Rao             std::string service;
3160fda0f12SGeorge Liu             if (boost::starts_with(
3170fda0f12SGeorge Liu                     certURI,
3180fda0f12SGeorge Liu                     "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"))
31930215816SMarri Devender Rao             {
32030215816SMarri Devender Rao                 objectPath = certs::httpsObjectPath;
32130215816SMarri Devender Rao                 service = certs::httpsServiceName;
32230215816SMarri Devender Rao             }
3233b7f0149SMarri Devender Rao             else if (boost::starts_with(
3247e860f15SJohn Edward Broadbent                          certURI,
3257e860f15SJohn Edward Broadbent                          "/redfish/v1/AccountService/LDAP/Certificates"))
3263b7f0149SMarri Devender Rao             {
3273b7f0149SMarri Devender Rao                 objectPath = certs::ldapObjectPath;
3283b7f0149SMarri Devender Rao                 service = certs::ldapServiceName;
3293b7f0149SMarri Devender Rao             }
33030215816SMarri Devender Rao             else
33130215816SMarri Devender Rao             {
33230215816SMarri Devender Rao                 messages::actionParameterNotSupported(
33330215816SMarri Devender Rao                     asyncResp->res, "CertificateCollection", "GenerateCSR");
33430215816SMarri Devender Rao                 return;
33530215816SMarri Devender Rao             }
33630215816SMarri Devender Rao 
33730215816SMarri Devender Rao             // supporting only EC and RSA algorithm
3380fda0f12SGeorge Liu             if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA")
33930215816SMarri Devender Rao             {
34030215816SMarri Devender Rao                 messages::actionParameterNotSupported(
34130215816SMarri Devender Rao                     asyncResp->res, "KeyPairAlgorithm", "GenerateCSR");
34230215816SMarri Devender Rao                 return;
34330215816SMarri Devender Rao             }
34430215816SMarri Devender Rao 
3457e860f15SJohn Edward Broadbent             // supporting only 2048 key bit length for RSA algorithm due to
3467e860f15SJohn Edward Broadbent             // time consumed in generating private key
34730215816SMarri Devender Rao             if (*optKeyPairAlgorithm == "RSA" &&
3482c70f800SEd Tanous                 *optKeyBitLength != rsaKeyBitLength)
34930215816SMarri Devender Rao             {
3507e860f15SJohn Edward Broadbent                 messages::propertyValueNotInList(
3517e860f15SJohn Edward Broadbent                     asyncResp->res, std::to_string(*optKeyBitLength),
35230215816SMarri Devender Rao                     "KeyBitLength");
35330215816SMarri Devender Rao                 return;
35430215816SMarri Devender Rao             }
35530215816SMarri Devender Rao 
35630215816SMarri Devender Rao             // validate KeyUsage supporting only 1 type based on URL
3570fda0f12SGeorge Liu             if (boost::starts_with(
3580fda0f12SGeorge Liu                     certURI,
3590fda0f12SGeorge Liu                     "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"))
36030215816SMarri Devender Rao             {
36126f6976fSEd Tanous                 if (optKeyUsage->empty())
36230215816SMarri Devender Rao                 {
36330215816SMarri Devender Rao                     optKeyUsage->push_back("ServerAuthentication");
36430215816SMarri Devender Rao                 }
36530215816SMarri Devender Rao                 else if (optKeyUsage->size() == 1)
36630215816SMarri Devender Rao                 {
36730215816SMarri Devender Rao                     if ((*optKeyUsage)[0] != "ServerAuthentication")
36830215816SMarri Devender Rao                     {
36930215816SMarri Devender Rao                         messages::propertyValueNotInList(
37030215816SMarri Devender Rao                             asyncResp->res, (*optKeyUsage)[0], "KeyUsage");
37130215816SMarri Devender Rao                         return;
37230215816SMarri Devender Rao                     }
37330215816SMarri Devender Rao                 }
37430215816SMarri Devender Rao                 else
37530215816SMarri Devender Rao                 {
37630215816SMarri Devender Rao                     messages::actionParameterNotSupported(
37730215816SMarri Devender Rao                         asyncResp->res, "KeyUsage", "GenerateCSR");
37830215816SMarri Devender Rao                     return;
37930215816SMarri Devender Rao                 }
38030215816SMarri Devender Rao             }
3813b7f0149SMarri Devender Rao             else if (boost::starts_with(
3827e860f15SJohn Edward Broadbent                          certURI,
3837e860f15SJohn Edward Broadbent                          "/redfish/v1/AccountService/LDAP/Certificates"))
3843b7f0149SMarri Devender Rao             {
38526f6976fSEd Tanous                 if (optKeyUsage->empty())
3863b7f0149SMarri Devender Rao                 {
3873b7f0149SMarri Devender Rao                     optKeyUsage->push_back("ClientAuthentication");
3883b7f0149SMarri Devender Rao                 }
3893b7f0149SMarri Devender Rao                 else if (optKeyUsage->size() == 1)
3903b7f0149SMarri Devender Rao                 {
3913b7f0149SMarri Devender Rao                     if ((*optKeyUsage)[0] != "ClientAuthentication")
3923b7f0149SMarri Devender Rao                     {
3933b7f0149SMarri Devender Rao                         messages::propertyValueNotInList(
3943b7f0149SMarri Devender Rao                             asyncResp->res, (*optKeyUsage)[0], "KeyUsage");
3953b7f0149SMarri Devender Rao                         return;
3963b7f0149SMarri Devender Rao                     }
3973b7f0149SMarri Devender Rao                 }
3983b7f0149SMarri Devender Rao                 else
3993b7f0149SMarri Devender Rao                 {
4003b7f0149SMarri Devender Rao                     messages::actionParameterNotSupported(
4013b7f0149SMarri Devender Rao                         asyncResp->res, "KeyUsage", "GenerateCSR");
4023b7f0149SMarri Devender Rao                     return;
4033b7f0149SMarri Devender Rao                 }
4043b7f0149SMarri Devender Rao             }
40530215816SMarri Devender Rao 
4067e860f15SJohn Edward Broadbent             // Only allow one CSR matcher at a time so setting retry
4077e860f15SJohn Edward Broadbent             // time-out and timer expiry to 10 seconds for now.
4082c70f800SEd Tanous             static const int timeOut = 10;
40930215816SMarri Devender Rao             if (csrMatcher)
41030215816SMarri Devender Rao             {
4117e860f15SJohn Edward Broadbent                 messages::serviceTemporarilyUnavailable(
4127e860f15SJohn Edward Broadbent                     asyncResp->res, std::to_string(timeOut));
41330215816SMarri Devender Rao                 return;
41430215816SMarri Devender Rao             }
41530215816SMarri Devender Rao 
41630215816SMarri Devender Rao             // Make this static so it survives outside this method
41730215816SMarri Devender Rao             static boost::asio::steady_timer timeout(*req.ioService);
4182c70f800SEd Tanous             timeout.expires_after(std::chrono::seconds(timeOut));
4190fda0f12SGeorge Liu             timeout.async_wait(
4200fda0f12SGeorge Liu                 [asyncResp](const boost::system::error_code& ec) {
42130215816SMarri Devender Rao                     csrMatcher = nullptr;
42230215816SMarri Devender Rao                     if (ec)
42330215816SMarri Devender Rao                     {
4247e860f15SJohn Edward Broadbent                         // operation_aborted is expected if timer is canceled
4257e860f15SJohn Edward Broadbent                         // before completion.
42630215816SMarri Devender Rao                         if (ec != boost::asio::error::operation_aborted)
42730215816SMarri Devender Rao                         {
42830215816SMarri Devender Rao                             BMCWEB_LOG_ERROR << "Async_wait failed " << ec;
42930215816SMarri Devender Rao                         }
43030215816SMarri Devender Rao                         return;
43130215816SMarri Devender Rao                     }
43230215816SMarri Devender Rao                     BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR";
43330215816SMarri Devender Rao                     messages::internalError(asyncResp->res);
43430215816SMarri Devender Rao                 });
43530215816SMarri Devender Rao 
43630215816SMarri Devender Rao             // create a matcher to wait on CSR object
43730215816SMarri Devender Rao             BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath;
4380fda0f12SGeorge Liu             std::string match("type='signal',"
43930215816SMarri Devender Rao                               "interface='org.freedesktop.DBus.ObjectManager',"
44030215816SMarri Devender Rao                               "path='" +
44130215816SMarri Devender Rao                               objectPath +
44230215816SMarri Devender Rao                               "',"
44330215816SMarri Devender Rao                               "member='InterfacesAdded'");
44430215816SMarri Devender Rao             csrMatcher = std::make_unique<sdbusplus::bus::match::match>(
44530215816SMarri Devender Rao                 *crow::connections::systemBus, match,
44630215816SMarri Devender Rao                 [asyncResp, service, objectPath,
44730215816SMarri Devender Rao                  certURI](sdbusplus::message::message& m) {
448271584abSEd Tanous                     timeout.cancel();
44930215816SMarri Devender Rao                     if (m.is_method_error())
45030215816SMarri Devender Rao                     {
45130215816SMarri Devender Rao                         BMCWEB_LOG_ERROR << "Dbus method error!!!";
45230215816SMarri Devender Rao                         messages::internalError(asyncResp->res);
45330215816SMarri Devender Rao                         return;
45430215816SMarri Devender Rao                     }
455*b9d36b47SEd Tanous 
456*b9d36b47SEd Tanous                     dbus::utility::DBusInteracesMap interfacesProperties;
457*b9d36b47SEd Tanous 
45830215816SMarri Devender Rao                     sdbusplus::message::object_path csrObjectPath;
45930215816SMarri Devender Rao                     m.read(csrObjectPath, interfacesProperties);
4600fda0f12SGeorge Liu                     BMCWEB_LOG_DEBUG << "CSR object added" << csrObjectPath.str;
46130215816SMarri Devender Rao                     for (auto& interface : interfacesProperties)
46230215816SMarri Devender Rao                     {
4630fda0f12SGeorge Liu                         if (interface.first == "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(
472914e2d5dSEd 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,
4850fda0f12SGeorge Liu                 *optGivenName, *optInitials, *optKeyBitLength, *optKeyCurveId,
4860fda0f12SGeorge Liu                 *optKeyPairAlgorithm, *optKeyUsage, organization,
4870fda0f12SGeorge Liu                 organizationalUnit, state, *optSurname, *optUnstructuredName);
4887e860f15SJohn Edward Broadbent         });
4897e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionGenerateCSR
49030215816SMarri Devender Rao 
4915968caeeSMarri Devender Rao /**
4924e0453b1SGunnar Mills  * @brief Parse and update Certificate Issue/Subject property
4935968caeeSMarri Devender Rao  *
4945968caeeSMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
4955968caeeSMarri Devender Rao  * @param[in] str  Issuer/Subject value in key=value pairs
4965968caeeSMarri Devender Rao  * @param[in] type Issuer/Subject
4975968caeeSMarri Devender Rao  * @return None
4985968caeeSMarri Devender Rao  */
4995968caeeSMarri Devender Rao static void updateCertIssuerOrSubject(nlohmann::json& out,
5005968caeeSMarri Devender Rao                                       const std::string_view value)
5015968caeeSMarri Devender Rao {
5025968caeeSMarri Devender Rao     // example: O=openbmc-project.xyz,CN=localhost
5035968caeeSMarri Devender Rao     std::string_view::iterator i = value.begin();
5045968caeeSMarri Devender Rao     while (i != value.end())
5055968caeeSMarri Devender Rao     {
5065968caeeSMarri Devender Rao         std::string_view::iterator tokenBegin = i;
5075968caeeSMarri Devender Rao         while (i != value.end() && *i != '=')
5085968caeeSMarri Devender Rao         {
50917a897dfSManojkiran Eda             ++i;
5105968caeeSMarri Devender Rao         }
5115968caeeSMarri Devender Rao         if (i == value.end())
5125968caeeSMarri Devender Rao         {
5135968caeeSMarri Devender Rao             break;
5145968caeeSMarri Devender Rao         }
515271584abSEd Tanous         const std::string_view key(tokenBegin,
516271584abSEd Tanous                                    static_cast<size_t>(i - tokenBegin));
51717a897dfSManojkiran Eda         ++i;
5185968caeeSMarri Devender Rao         tokenBegin = i;
5195968caeeSMarri Devender Rao         while (i != value.end() && *i != ',')
5205968caeeSMarri Devender Rao         {
52117a897dfSManojkiran Eda             ++i;
5225968caeeSMarri Devender Rao         }
523271584abSEd Tanous         const std::string_view val(tokenBegin,
524271584abSEd Tanous                                    static_cast<size_t>(i - tokenBegin));
5255968caeeSMarri Devender Rao         if (key == "L")
5265968caeeSMarri Devender Rao         {
5275968caeeSMarri Devender Rao             out["City"] = val;
5285968caeeSMarri Devender Rao         }
5295968caeeSMarri Devender Rao         else if (key == "CN")
5305968caeeSMarri Devender Rao         {
5315968caeeSMarri Devender Rao             out["CommonName"] = val;
5325968caeeSMarri Devender Rao         }
5335968caeeSMarri Devender Rao         else if (key == "C")
5345968caeeSMarri Devender Rao         {
5355968caeeSMarri Devender Rao             out["Country"] = val;
5365968caeeSMarri Devender Rao         }
5375968caeeSMarri Devender Rao         else if (key == "O")
5385968caeeSMarri Devender Rao         {
5395968caeeSMarri Devender Rao             out["Organization"] = val;
5405968caeeSMarri Devender Rao         }
5415968caeeSMarri Devender Rao         else if (key == "OU")
5425968caeeSMarri Devender Rao         {
5435968caeeSMarri Devender Rao             out["OrganizationalUnit"] = val;
5445968caeeSMarri Devender Rao         }
5455968caeeSMarri Devender Rao         else if (key == "ST")
5465968caeeSMarri Devender Rao         {
5475968caeeSMarri Devender Rao             out["State"] = val;
5485968caeeSMarri Devender Rao         }
5495968caeeSMarri Devender Rao         // skip comma character
5505968caeeSMarri Devender Rao         if (i != value.end())
5515968caeeSMarri Devender Rao         {
55217a897dfSManojkiran Eda             ++i;
5535968caeeSMarri Devender Rao         }
5545968caeeSMarri Devender Rao     }
5555968caeeSMarri Devender Rao }
5565968caeeSMarri Devender Rao 
5575968caeeSMarri Devender Rao /**
5585968caeeSMarri Devender Rao  * @brief Retrieve the certificates properties and append to the response
5595968caeeSMarri Devender Rao  * message
5605968caeeSMarri Devender Rao  *
5615968caeeSMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
5625968caeeSMarri Devender Rao  * @param[in] objectPath  Path of the D-Bus service object
5635968caeeSMarri Devender Rao  * @param[in] certId  Id of the certificate
5645968caeeSMarri Devender Rao  * @param[in] certURL  URL of the certificate object
5655968caeeSMarri Devender Rao  * @param[in] name  name of the certificate
5665968caeeSMarri Devender Rao  * @return None
5675968caeeSMarri Devender Rao  */
5685968caeeSMarri Devender Rao static void getCertificateProperties(
5698d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
5708d1b46d7Szhanghch05     const std::string& objectPath, const std::string& service, long certId,
5718d1b46d7Szhanghch05     const std::string& certURL, const std::string& name)
5725968caeeSMarri Devender Rao {
5735968caeeSMarri Devender Rao     BMCWEB_LOG_DEBUG << "getCertificateProperties Path=" << objectPath
5745968caeeSMarri Devender Rao                      << " certId=" << certId << " certURl=" << certURL;
5755968caeeSMarri Devender Rao     crow::connections::systemBus->async_method_call(
576*b9d36b47SEd Tanous         [asyncResp, certURL, certId,
577*b9d36b47SEd Tanous          name](const boost::system::error_code ec,
578*b9d36b47SEd Tanous                const dbus::utility::DBusPropertiesMap& properties) {
5795968caeeSMarri Devender Rao             if (ec)
5805968caeeSMarri Devender Rao             {
5815968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
5828aae75adSMarri Devender Rao                 messages::resourceNotFound(asyncResp->res, name,
5838aae75adSMarri Devender Rao                                            std::to_string(certId));
5845968caeeSMarri Devender Rao                 return;
5855968caeeSMarri Devender Rao             }
5865968caeeSMarri Devender Rao             asyncResp->res.jsonValue = {
5875968caeeSMarri Devender Rao                 {"@odata.id", certURL},
5885968caeeSMarri Devender Rao                 {"@odata.type", "#Certificate.v1_0_0.Certificate"},
5895968caeeSMarri Devender Rao                 {"Id", std::to_string(certId)},
5905968caeeSMarri Devender Rao                 {"Name", name},
5915968caeeSMarri Devender Rao                 {"Description", name}};
5925968caeeSMarri Devender Rao             for (const auto& property : properties)
5935968caeeSMarri Devender Rao             {
5945968caeeSMarri Devender Rao                 if (property.first == "CertificateString")
5955968caeeSMarri Devender Rao                 {
5965968caeeSMarri Devender Rao                     asyncResp->res.jsonValue["CertificateString"] = "";
5975968caeeSMarri Devender Rao                     const std::string* value =
5985968caeeSMarri Devender Rao                         std::get_if<std::string>(&property.second);
599e662eae8SEd Tanous                     if (value != nullptr)
6005968caeeSMarri Devender Rao                     {
60137cce918SMarri Devender Rao                         asyncResp->res.jsonValue["CertificateString"] = *value;
6025968caeeSMarri Devender Rao                     }
6035968caeeSMarri Devender Rao                 }
6045968caeeSMarri Devender Rao                 else if (property.first == "KeyUsage")
6055968caeeSMarri Devender Rao                 {
6065968caeeSMarri Devender Rao                     nlohmann::json& keyUsage =
6075968caeeSMarri Devender Rao                         asyncResp->res.jsonValue["KeyUsage"];
6085968caeeSMarri Devender Rao                     keyUsage = nlohmann::json::array();
6095968caeeSMarri Devender Rao                     const std::vector<std::string>* value =
61037cce918SMarri Devender Rao                         std::get_if<std::vector<std::string>>(&property.second);
611e662eae8SEd Tanous                     if (value != nullptr)
6125968caeeSMarri Devender Rao                     {
6135968caeeSMarri Devender Rao                         for (const std::string& usage : *value)
6145968caeeSMarri Devender Rao                         {
6155968caeeSMarri Devender Rao                             keyUsage.push_back(usage);
6165968caeeSMarri Devender Rao                         }
6175968caeeSMarri Devender Rao                     }
6185968caeeSMarri Devender Rao                 }
6195968caeeSMarri Devender Rao                 else if (property.first == "Issuer")
6205968caeeSMarri Devender Rao                 {
6215968caeeSMarri Devender Rao                     const std::string* value =
6225968caeeSMarri Devender Rao                         std::get_if<std::string>(&property.second);
623e662eae8SEd Tanous                     if (value != nullptr)
6245968caeeSMarri Devender Rao                     {
6255968caeeSMarri Devender Rao                         updateCertIssuerOrSubject(
6265968caeeSMarri Devender Rao                             asyncResp->res.jsonValue["Issuer"], *value);
6275968caeeSMarri Devender Rao                     }
6285968caeeSMarri Devender Rao                 }
6295968caeeSMarri Devender Rao                 else if (property.first == "Subject")
6305968caeeSMarri Devender Rao                 {
6315968caeeSMarri Devender Rao                     const std::string* value =
6325968caeeSMarri Devender Rao                         std::get_if<std::string>(&property.second);
633e662eae8SEd Tanous                     if (value != nullptr)
6345968caeeSMarri Devender Rao                     {
6355968caeeSMarri Devender Rao                         updateCertIssuerOrSubject(
63637cce918SMarri Devender Rao                             asyncResp->res.jsonValue["Subject"], *value);
6375968caeeSMarri Devender Rao                     }
6385968caeeSMarri Devender Rao                 }
6395968caeeSMarri Devender Rao                 else if (property.first == "ValidNotAfter")
6405968caeeSMarri Devender Rao                 {
6415968caeeSMarri Devender Rao                     const uint64_t* value =
6425968caeeSMarri Devender Rao                         std::get_if<uint64_t>(&property.second);
643e662eae8SEd Tanous                     if (value != nullptr)
6445968caeeSMarri Devender Rao                     {
6455968caeeSMarri Devender Rao                         asyncResp->res.jsonValue["ValidNotAfter"] =
6461d8782e7SNan Zhou                             crow::utility::getDateTimeUint(*value);
6475968caeeSMarri Devender Rao                     }
6485968caeeSMarri Devender Rao                 }
6495968caeeSMarri Devender Rao                 else if (property.first == "ValidNotBefore")
6505968caeeSMarri Devender Rao                 {
6515968caeeSMarri Devender Rao                     const uint64_t* value =
6525968caeeSMarri Devender Rao                         std::get_if<uint64_t>(&property.second);
653e662eae8SEd Tanous                     if (value != nullptr)
6545968caeeSMarri Devender Rao                     {
6555968caeeSMarri Devender Rao                         asyncResp->res.jsonValue["ValidNotBefore"] =
6561d8782e7SNan Zhou                             crow::utility::getDateTimeUint(*value);
6575968caeeSMarri Devender Rao                     }
6585968caeeSMarri Devender Rao                 }
6595968caeeSMarri Devender Rao             }
6605968caeeSMarri Devender Rao             asyncResp->res.addHeader("Location", certURL);
6615968caeeSMarri Devender Rao         },
6625968caeeSMarri Devender Rao         service, objectPath, certs::dbusPropIntf, "GetAll",
6635968caeeSMarri Devender Rao         certs::certPropIntf);
6645968caeeSMarri Devender Rao }
6655968caeeSMarri Devender Rao 
6665968caeeSMarri Devender Rao /**
6675968caeeSMarri Devender Rao  * Action to replace an existing certificate
6685968caeeSMarri Devender Rao  */
6697e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionsReplaceCertificate(App& app)
6705968caeeSMarri Devender Rao {
6710fda0f12SGeorge Liu     BMCWEB_ROUTE(
6720fda0f12SGeorge Liu         app,
6730fda0f12SGeorge Liu         "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate/")
674ed398213SEd Tanous         .privileges(redfish::privileges::postCertificateService)
6757e860f15SJohn Edward Broadbent         .methods(
6767e860f15SJohn Edward Broadbent             boost::beast::http::verb::
6777e860f15SJohn Edward Broadbent                 post)([](const crow::Request& req,
6787e860f15SJohn Edward Broadbent                          const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
6795968caeeSMarri Devender Rao             std::string certificate;
6805968caeeSMarri Devender Rao             nlohmann::json certificateUri;
6815968caeeSMarri Devender Rao             std::optional<std::string> certificateType = "PEM";
6828d1b46d7Szhanghch05 
68315ed6780SWilly Tu             if (!json_util::readJsonAction(req, asyncResp->res,
68415ed6780SWilly Tu                                            "CertificateString", certificate,
68515ed6780SWilly Tu                                            "CertificateUri", certificateUri,
68615ed6780SWilly Tu                                            "CertificateType", certificateType))
6875968caeeSMarri Devender Rao             {
6885968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "Required parameters are missing";
6895968caeeSMarri Devender Rao                 messages::internalError(asyncResp->res);
6905968caeeSMarri Devender Rao                 return;
6915968caeeSMarri Devender Rao             }
6925968caeeSMarri Devender Rao 
6935968caeeSMarri Devender Rao             if (!certificateType)
6945968caeeSMarri Devender Rao             {
6955968caeeSMarri Devender Rao                 // should never happen, but it never hurts to be paranoid.
6965968caeeSMarri Devender Rao                 return;
6975968caeeSMarri Devender Rao             }
6985968caeeSMarri Devender Rao             if (certificateType != "PEM")
6995968caeeSMarri Devender Rao             {
7005968caeeSMarri Devender Rao                 messages::actionParameterNotSupported(
7015968caeeSMarri Devender Rao                     asyncResp->res, "CertificateType", "ReplaceCertificate");
7025968caeeSMarri Devender Rao                 return;
7035968caeeSMarri Devender Rao             }
7045968caeeSMarri Devender Rao 
7055968caeeSMarri Devender Rao             std::string certURI;
7065968caeeSMarri Devender Rao             if (!redfish::json_util::readJson(certificateUri, asyncResp->res,
7075968caeeSMarri Devender Rao                                               "@odata.id", certURI))
7085968caeeSMarri Devender Rao             {
7095968caeeSMarri Devender Rao                 messages::actionParameterMissing(
7105968caeeSMarri Devender Rao                     asyncResp->res, "ReplaceCertificate", "CertificateUri");
7115968caeeSMarri Devender Rao                 return;
7125968caeeSMarri Devender Rao             }
7135968caeeSMarri Devender Rao 
7145968caeeSMarri Devender Rao             BMCWEB_LOG_INFO << "Certificate URI to replace" << certURI;
7155968caeeSMarri Devender Rao             long id = getIDFromURL(certURI);
7165968caeeSMarri Devender Rao             if (id < 0)
7175968caeeSMarri Devender Rao             {
7187e860f15SJohn Edward Broadbent                 messages::actionParameterValueFormatError(
7197e860f15SJohn Edward Broadbent                     asyncResp->res, certURI, "CertificateUri",
7205968caeeSMarri Devender Rao                     "ReplaceCertificate");
7215968caeeSMarri Devender Rao                 return;
7225968caeeSMarri Devender Rao             }
7235968caeeSMarri Devender Rao             std::string objectPath;
7245968caeeSMarri Devender Rao             std::string name;
72537cce918SMarri Devender Rao             std::string service;
7260fda0f12SGeorge Liu             if (boost::starts_with(
7270fda0f12SGeorge Liu                     certURI,
7280fda0f12SGeorge Liu                     "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/"))
7295968caeeSMarri Devender Rao             {
7307e860f15SJohn Edward Broadbent                 objectPath = std::string(certs::httpsObjectPath) + "/" +
7317e860f15SJohn Edward Broadbent                              std::to_string(id);
7325968caeeSMarri Devender Rao                 name = "HTTPS certificate";
73337cce918SMarri Devender Rao                 service = certs::httpsServiceName;
73437cce918SMarri Devender Rao             }
73537cce918SMarri Devender Rao             else if (boost::starts_with(
7367e860f15SJohn Edward Broadbent                          certURI,
7377e860f15SJohn Edward Broadbent                          "/redfish/v1/AccountService/LDAP/Certificates/"))
73837cce918SMarri Devender Rao             {
7397e860f15SJohn Edward Broadbent                 objectPath = std::string(certs::ldapObjectPath) + "/" +
7407e860f15SJohn Edward Broadbent                              std::to_string(id);
74137cce918SMarri Devender Rao                 name = "LDAP certificate";
74237cce918SMarri Devender Rao                 service = certs::ldapServiceName;
7435968caeeSMarri Devender Rao             }
744cfcd5f6bSMarri Devender Rao             else if (boost::starts_with(
745cfcd5f6bSMarri Devender Rao                          certURI,
746cfcd5f6bSMarri Devender Rao                          "/redfish/v1/Managers/bmc/Truststore/Certificates/"))
747cfcd5f6bSMarri Devender Rao             {
748cfcd5f6bSMarri Devender Rao                 objectPath = std::string(certs::authorityObjectPath) + "/" +
749cfcd5f6bSMarri Devender Rao                              std::to_string(id);
750cfcd5f6bSMarri Devender Rao                 name = "TrustStore certificate";
751cfcd5f6bSMarri Devender Rao                 service = certs::authorityServiceName;
752cfcd5f6bSMarri Devender Rao             }
7535968caeeSMarri Devender Rao             else
7545968caeeSMarri Devender Rao             {
7555968caeeSMarri Devender Rao                 messages::actionParameterNotSupported(
7565968caeeSMarri Devender Rao                     asyncResp->res, "CertificateUri", "ReplaceCertificate");
7575968caeeSMarri Devender Rao                 return;
7585968caeeSMarri Devender Rao             }
7595968caeeSMarri Devender Rao 
7605968caeeSMarri Devender Rao             std::shared_ptr<CertificateFile> certFile =
7615968caeeSMarri Devender Rao                 std::make_shared<CertificateFile>(certificate);
7625968caeeSMarri Devender Rao             crow::connections::systemBus->async_method_call(
76337cce918SMarri Devender Rao                 [asyncResp, certFile, objectPath, service, certURI, id,
7645968caeeSMarri Devender Rao                  name](const boost::system::error_code ec) {
7655968caeeSMarri Devender Rao                     if (ec)
7665968caeeSMarri Devender Rao                     {
7675968caeeSMarri Devender Rao                         BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
7688aae75adSMarri Devender Rao                         messages::resourceNotFound(asyncResp->res, name,
7698aae75adSMarri Devender Rao                                                    std::to_string(id));
7705968caeeSMarri Devender Rao                         return;
7715968caeeSMarri Devender Rao                     }
77237cce918SMarri Devender Rao                     getCertificateProperties(asyncResp, objectPath, service, id,
7735968caeeSMarri Devender Rao                                              certURI, name);
7745968caeeSMarri Devender Rao                     BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
7755968caeeSMarri Devender Rao                                      << certFile->getCertFilePath();
7765968caeeSMarri Devender Rao                 },
7775968caeeSMarri Devender Rao                 service, objectPath, certs::certReplaceIntf, "Replace",
7785968caeeSMarri Devender Rao                 certFile->getCertFilePath());
7797e860f15SJohn Edward Broadbent         });
7807e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionsReplaceCertificate
7815968caeeSMarri Devender Rao 
7825968caeeSMarri Devender Rao /**
7835968caeeSMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
7845968caeeSMarri Devender Rao  * of a component, account or service.
7855968caeeSMarri Devender Rao  */
7865968caeeSMarri Devender Rao 
7877e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificate(App& app)
7885968caeeSMarri Devender Rao {
7897e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
7907e860f15SJohn Edward Broadbent         app,
7917e860f15SJohn Edward Broadbent         "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/<str>/")
792ed398213SEd Tanous         .privileges(redfish::privileges::getCertificate)
7937e860f15SJohn Edward Broadbent         .methods(
7947e860f15SJohn Edward Broadbent             boost::beast::http::verb::
7957e860f15SJohn Edward Broadbent                 get)([](const crow::Request& req,
7967e860f15SJohn Edward Broadbent                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
7977e860f15SJohn Edward Broadbent                         const std::string& param) -> void {
7987e860f15SJohn Edward Broadbent             if (param.empty())
7995968caeeSMarri Devender Rao             {
8005968caeeSMarri Devender Rao                 messages::internalError(asyncResp->res);
8015968caeeSMarri Devender Rao                 return;
8025968caeeSMarri Devender Rao             }
8035968caeeSMarri Devender Rao             long id = getIDFromURL(req.url);
8045968caeeSMarri Devender Rao 
8057e860f15SJohn Edward Broadbent             BMCWEB_LOG_DEBUG << "HTTPSCertificate::doGet ID="
8067e860f15SJohn Edward Broadbent                              << std::to_string(id);
8075968caeeSMarri Devender Rao             std::string certURL =
8085968caeeSMarri Devender Rao                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" +
8095968caeeSMarri Devender Rao                 std::to_string(id);
8105968caeeSMarri Devender Rao             std::string objectPath = certs::httpsObjectPath;
8115968caeeSMarri Devender Rao             objectPath += "/";
8125968caeeSMarri Devender Rao             objectPath += std::to_string(id);
8137e860f15SJohn Edward Broadbent             getCertificateProperties(asyncResp, objectPath,
8147e860f15SJohn Edward Broadbent                                      certs::httpsServiceName, id, certURL,
8157e860f15SJohn Edward Broadbent                                      "HTTPS Certificate");
8167e860f15SJohn Edward Broadbent         });
8175968caeeSMarri Devender Rao }
8185968caeeSMarri Devender Rao 
8195968caeeSMarri Devender Rao /**
8205968caeeSMarri Devender Rao  * Collection of HTTPS certificates
8215968caeeSMarri Devender Rao  */
8227e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificateCollection(App& app)
8235968caeeSMarri Devender Rao {
8247e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
8255968caeeSMarri Devender Rao                  "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
826ed398213SEd Tanous         .privileges(redfish::privileges::getCertificateCollection)
8277e860f15SJohn Edward Broadbent         .methods(
8287e860f15SJohn Edward Broadbent             boost::beast::http::verb::
8297e860f15SJohn Edward Broadbent                 get)([](const crow::Request&,
8307e860f15SJohn Edward Broadbent                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
8318d1b46d7Szhanghch05             asyncResp->res.jsonValue = {
8325968caeeSMarri Devender Rao                 {"@odata.id",
8335968caeeSMarri Devender Rao                  "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"},
8345968caeeSMarri Devender Rao                 {"@odata.type", "#CertificateCollection.CertificateCollection"},
8355968caeeSMarri Devender Rao                 {"Name", "HTTPS Certificates Collection"},
8365968caeeSMarri Devender Rao                 {"Description", "A Collection of HTTPS certificate instances"}};
8378d1b46d7Szhanghch05 
8385968caeeSMarri Devender Rao             crow::connections::systemBus->async_method_call(
8395968caeeSMarri Devender Rao                 [asyncResp](const boost::system::error_code ec,
840711ac7a9SEd Tanous                             const dbus::utility::ManagedObjectType& certs) {
8415968caeeSMarri Devender Rao                     if (ec)
8425968caeeSMarri Devender Rao                     {
8435968caeeSMarri Devender Rao                         BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
8445968caeeSMarri Devender Rao                         messages::internalError(asyncResp->res);
8455968caeeSMarri Devender Rao                         return;
8465968caeeSMarri Devender Rao                     }
8477e860f15SJohn Edward Broadbent                     nlohmann::json& members =
8487e860f15SJohn Edward Broadbent                         asyncResp->res.jsonValue["Members"];
8495968caeeSMarri Devender Rao                     members = nlohmann::json::array();
8505968caeeSMarri Devender Rao                     for (const auto& cert : certs)
8515968caeeSMarri Devender Rao                     {
8525968caeeSMarri Devender Rao                         long id = getIDFromURL(cert.first.str);
85337cce918SMarri Devender Rao                         if (id >= 0)
8545968caeeSMarri Devender Rao                         {
8555968caeeSMarri Devender Rao                             members.push_back(
8565968caeeSMarri Devender Rao                                 {{"@odata.id",
8570fda0f12SGeorge Liu                                   "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" +
8585968caeeSMarri Devender Rao                                       std::to_string(id)}});
8595968caeeSMarri Devender Rao                         }
8605968caeeSMarri Devender Rao                     }
8615968caeeSMarri Devender Rao                     asyncResp->res.jsonValue["Members@odata.count"] =
8625968caeeSMarri Devender Rao                         members.size();
8635968caeeSMarri Devender Rao                 },
86437cce918SMarri Devender Rao                 certs::httpsServiceName, certs::httpsObjectPath,
86537cce918SMarri Devender Rao                 certs::dbusObjManagerIntf, "GetManagedObjects");
8667e860f15SJohn Edward Broadbent         });
8675968caeeSMarri Devender Rao 
8687e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
8697e860f15SJohn Edward Broadbent                  "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
870ed398213SEd Tanous         .privileges(redfish::privileges::postCertificateCollection)
8710fda0f12SGeorge Liu         .methods(
8720fda0f12SGeorge Liu             boost::beast::http::verb::
8730fda0f12SGeorge Liu                 post)([](const crow::Request& req,
8747e860f15SJohn Edward Broadbent                          const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
8755968caeeSMarri Devender Rao             BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost";
8768d1b46d7Szhanghch05 
8770fda0f12SGeorge Liu             asyncResp->res.jsonValue = {{"Name", "HTTPS Certificate"},
8785968caeeSMarri Devender Rao                                         {"Description", "HTTPS Certificate"}};
8795968caeeSMarri Devender Rao 
8807e860f15SJohn Edward Broadbent             std::string certFileBody =
8817e860f15SJohn Edward Broadbent                 getCertificateFromReqBody(asyncResp, req);
88258eb238fSKowalski, Kamil 
88358eb238fSKowalski, Kamil             if (certFileBody.empty())
88458eb238fSKowalski, Kamil             {
8850fda0f12SGeorge Liu                 BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
886a08752f5SZbigniew Kurzynski                 messages::unrecognizedRequestBody(asyncResp->res);
88758eb238fSKowalski, Kamil                 return;
88858eb238fSKowalski, Kamil             }
88958eb238fSKowalski, Kamil 
8905968caeeSMarri Devender Rao             std::shared_ptr<CertificateFile> certFile =
89158eb238fSKowalski, Kamil                 std::make_shared<CertificateFile>(certFileBody);
8925968caeeSMarri Devender Rao 
8935968caeeSMarri Devender Rao             crow::connections::systemBus->async_method_call(
894656ec7e3SZbigniew Kurzynski                 [asyncResp, certFile](const boost::system::error_code ec,
895656ec7e3SZbigniew Kurzynski                                       const std::string& objectPath) {
8965968caeeSMarri Devender Rao                     if (ec)
8975968caeeSMarri Devender Rao                     {
8985968caeeSMarri Devender Rao                         BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
8995968caeeSMarri Devender Rao                         messages::internalError(asyncResp->res);
9005968caeeSMarri Devender Rao                         return;
9015968caeeSMarri Devender Rao                     }
902656ec7e3SZbigniew Kurzynski                     long certId = getIDFromURL(objectPath);
903656ec7e3SZbigniew Kurzynski                     if (certId < 0)
904656ec7e3SZbigniew Kurzynski                     {
905656ec7e3SZbigniew Kurzynski                         BMCWEB_LOG_ERROR << "Invalid objectPath value"
906656ec7e3SZbigniew Kurzynski                                          << objectPath;
907656ec7e3SZbigniew Kurzynski                         messages::internalError(asyncResp->res);
908656ec7e3SZbigniew Kurzynski                         return;
909656ec7e3SZbigniew Kurzynski                     }
9105968caeeSMarri Devender Rao                     std::string certURL =
9110fda0f12SGeorge Liu                         "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" +
9125968caeeSMarri Devender Rao                         std::to_string(certId);
9130fda0f12SGeorge Liu                     getCertificateProperties(asyncResp, objectPath,
9140fda0f12SGeorge Liu                                              certs::httpsServiceName, certId,
9150fda0f12SGeorge Liu                                              certURL, "HTTPS Certificate");
9165968caeeSMarri Devender Rao                     BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
9175968caeeSMarri Devender Rao                                      << certFile->getCertFilePath();
9185968caeeSMarri Devender Rao                 },
91937cce918SMarri Devender Rao                 certs::httpsServiceName, certs::httpsObjectPath,
9200fda0f12SGeorge Liu                 certs::certInstallIntf, "Install", certFile->getCertFilePath());
9217e860f15SJohn Edward Broadbent         });
9227e860f15SJohn Edward Broadbent } // requestRoutesHTTPSCertificateCollection
9235968caeeSMarri Devender Rao 
9245968caeeSMarri Devender Rao /**
92537cce918SMarri Devender Rao  * @brief Retrieve the certificates installed list and append to the
92637cce918SMarri Devender Rao  * response
92737cce918SMarri Devender Rao  *
92837cce918SMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
92937cce918SMarri Devender Rao  * @param[in] certURL  Path of the certificate object
93037cce918SMarri Devender Rao  * @param[in] path  Path of the D-Bus service object
93137cce918SMarri Devender Rao  * @return None
93237cce918SMarri Devender Rao  */
9334f48d5f6SEd Tanous inline void
9344f48d5f6SEd Tanous     getCertificateLocations(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
9358d1b46d7Szhanghch05                             const std::string& certURL, const std::string& path,
93637cce918SMarri Devender Rao                             const std::string& service)
93737cce918SMarri Devender Rao {
93837cce918SMarri Devender Rao     BMCWEB_LOG_DEBUG << "getCertificateLocations URI=" << certURL
93937cce918SMarri Devender Rao                      << " Path=" << path << " service= " << service;
94037cce918SMarri Devender Rao     crow::connections::systemBus->async_method_call(
94137cce918SMarri Devender Rao         [asyncResp, certURL](const boost::system::error_code ec,
942711ac7a9SEd Tanous                              const dbus::utility::ManagedObjectType& certs) {
94337cce918SMarri Devender Rao             if (ec)
94437cce918SMarri Devender Rao             {
9459c8e039eSJonathan Doman                 BMCWEB_LOG_WARNING
9469c8e039eSJonathan Doman                     << "Certificate collection query failed: " << ec
9479c8e039eSJonathan Doman                     << ", skipping " << certURL;
94837cce918SMarri Devender Rao                 return;
94937cce918SMarri Devender Rao             }
95037cce918SMarri Devender Rao             nlohmann::json& links =
95137cce918SMarri Devender Rao                 asyncResp->res.jsonValue["Links"]["Certificates"];
9529eb808c1SEd Tanous             for (const auto& cert : certs)
95337cce918SMarri Devender Rao             {
95437cce918SMarri Devender Rao                 long id = getIDFromURL(cert.first.str);
95537cce918SMarri Devender Rao                 if (id >= 0)
95637cce918SMarri Devender Rao                 {
95737cce918SMarri Devender Rao                     links.push_back(
95837cce918SMarri Devender Rao                         {{"@odata.id", certURL + std::to_string(id)}});
95937cce918SMarri Devender Rao                 }
96037cce918SMarri Devender Rao             }
96137cce918SMarri Devender Rao             asyncResp->res.jsonValue["Links"]["Certificates@odata.count"] =
96237cce918SMarri Devender Rao                 links.size();
96337cce918SMarri Devender Rao         },
96437cce918SMarri Devender Rao         service, path, certs::dbusObjManagerIntf, "GetManagedObjects");
9655968caeeSMarri Devender Rao }
9667e860f15SJohn Edward Broadbent 
9677e860f15SJohn Edward Broadbent /**
9687e860f15SJohn Edward Broadbent  * The certificate location schema defines a resource that an administrator
9697e860f15SJohn Edward Broadbent  * can use in order to locate all certificates installed on a given service.
9707e860f15SJohn Edward Broadbent  */
9717e860f15SJohn Edward Broadbent inline void requestRoutesCertificateLocations(App& app)
9727e860f15SJohn Edward Broadbent {
9737e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/")
974ed398213SEd Tanous         .privileges(redfish::privileges::getCertificateLocations)
9757e860f15SJohn Edward Broadbent         .methods(
9767e860f15SJohn Edward Broadbent             boost::beast::http::verb::
9777e860f15SJohn Edward Broadbent                 get)([](const crow::Request&,
9787e860f15SJohn Edward Broadbent                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
9797e860f15SJohn Edward Broadbent             asyncResp->res.jsonValue = {
9807e860f15SJohn Edward Broadbent                 {"@odata.id",
9817e860f15SJohn Edward Broadbent                  "/redfish/v1/CertificateService/CertificateLocations"},
9827e860f15SJohn Edward Broadbent                 {"@odata.type",
9837e860f15SJohn Edward Broadbent                  "#CertificateLocations.v1_0_0.CertificateLocations"},
9847e860f15SJohn Edward Broadbent                 {"Name", "Certificate Locations"},
9857e860f15SJohn Edward Broadbent                 {"Id", "CertificateLocations"},
9867e860f15SJohn Edward Broadbent                 {"Description",
9877e860f15SJohn Edward Broadbent                  "Defines a resource that an administrator can use in order to "
9887e860f15SJohn Edward Broadbent                  "locate all certificates installed on a given service"}};
9897e860f15SJohn Edward Broadbent 
9907e860f15SJohn Edward Broadbent             nlohmann::json& links =
9917e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["Links"]["Certificates"];
9927e860f15SJohn Edward Broadbent             links = nlohmann::json::array();
9937e860f15SJohn Edward Broadbent             getCertificateLocations(
9947e860f15SJohn Edward Broadbent                 asyncResp,
9957e860f15SJohn Edward Broadbent                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/",
9967e860f15SJohn Edward Broadbent                 certs::httpsObjectPath, certs::httpsServiceName);
9977e860f15SJohn Edward Broadbent             getCertificateLocations(
9987e860f15SJohn Edward Broadbent                 asyncResp, "/redfish/v1/AccountService/LDAP/Certificates/",
9997e860f15SJohn Edward Broadbent                 certs::ldapObjectPath, certs::ldapServiceName);
10007e860f15SJohn Edward Broadbent             getCertificateLocations(
10017e860f15SJohn Edward Broadbent                 asyncResp, "/redfish/v1/Managers/bmc/Truststore/Certificates/",
10027e860f15SJohn Edward Broadbent                 certs::authorityObjectPath, certs::authorityServiceName);
10037e860f15SJohn Edward Broadbent         });
10047e860f15SJohn Edward Broadbent }
10057e860f15SJohn Edward Broadbent // requestRoutesCertificateLocations
100637cce918SMarri Devender Rao 
100737cce918SMarri Devender Rao /**
100837cce918SMarri Devender Rao  * Collection of LDAP certificates
100937cce918SMarri Devender Rao  */
10107e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificateCollection(App& app)
101137cce918SMarri Devender Rao {
10127e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
1013ed398213SEd Tanous         .privileges(redfish::privileges::getCertificateCollection)
10140fda0f12SGeorge Liu         .methods(
10150fda0f12SGeorge Liu             boost::beast::http::verb::
10160fda0f12SGeorge Liu                 get)([](const crow::Request&,
10177e860f15SJohn Edward Broadbent                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
10188d1b46d7Szhanghch05             asyncResp->res.jsonValue = {
10190fda0f12SGeorge Liu                 {"@odata.id", "/redfish/v1/AccountService/LDAP/Certificates"},
10200fda0f12SGeorge Liu                 {"@odata.type", "#CertificateCollection.CertificateCollection"},
102137cce918SMarri Devender Rao                 {"Name", "LDAP Certificates Collection"},
10220fda0f12SGeorge Liu                 {"Description", "A Collection of LDAP certificate instances"}};
10238d1b46d7Szhanghch05 
102437cce918SMarri Devender Rao             crow::connections::systemBus->async_method_call(
102537cce918SMarri Devender Rao                 [asyncResp](const boost::system::error_code ec,
1026711ac7a9SEd Tanous                             const dbus::utility::ManagedObjectType& certs) {
10277e860f15SJohn Edward Broadbent                     nlohmann::json& members =
10287e860f15SJohn Edward Broadbent                         asyncResp->res.jsonValue["Members"];
10299c8e039eSJonathan Doman                     nlohmann::json& count =
10309c8e039eSJonathan Doman                         asyncResp->res.jsonValue["Members@odata.count"];
10319c8e039eSJonathan Doman                     members = nlohmann::json::array();
10329c8e039eSJonathan Doman                     count = 0;
103337cce918SMarri Devender Rao                     if (ec)
103437cce918SMarri Devender Rao                     {
10350fda0f12SGeorge Liu                         BMCWEB_LOG_WARNING << "LDAP certificate query failed: "
10360fda0f12SGeorge Liu                                            << ec;
103737cce918SMarri Devender Rao                         return;
103837cce918SMarri Devender Rao                     }
103937cce918SMarri Devender Rao                     for (const auto& cert : certs)
104037cce918SMarri Devender Rao                     {
104137cce918SMarri Devender Rao                         long id = getIDFromURL(cert.first.str);
104237cce918SMarri Devender Rao                         if (id >= 0)
104337cce918SMarri Devender Rao                         {
104437cce918SMarri Devender Rao                             members.push_back(
10450fda0f12SGeorge Liu                                 {{"@odata.id",
10460fda0f12SGeorge Liu                                   "/redfish/v1/AccountService/LDAP/Certificates/" +
104737cce918SMarri Devender Rao                                       std::to_string(id)}});
104837cce918SMarri Devender Rao                         }
104937cce918SMarri Devender Rao                     }
10509c8e039eSJonathan Doman                     count = members.size();
105137cce918SMarri Devender Rao                 },
105237cce918SMarri Devender Rao                 certs::ldapServiceName, certs::ldapObjectPath,
105337cce918SMarri Devender Rao                 certs::dbusObjManagerIntf, "GetManagedObjects");
10547e860f15SJohn Edward Broadbent         });
105537cce918SMarri Devender Rao 
10567e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
1057ed398213SEd Tanous         .privileges(redfish::privileges::postCertificateCollection)
10587e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
10597e860f15SJohn Edward Broadbent             [](const crow::Request& req,
10607e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
10617e860f15SJohn Edward Broadbent                 std::string certFileBody =
10627e860f15SJohn Edward Broadbent                     getCertificateFromReqBody(asyncResp, req);
106358eb238fSKowalski, Kamil 
106458eb238fSKowalski, Kamil                 if (certFileBody.empty())
106558eb238fSKowalski, Kamil                 {
10667e860f15SJohn Edward Broadbent                     BMCWEB_LOG_ERROR
10677e860f15SJohn Edward Broadbent                         << "Cannot get certificate from request body.";
1068a08752f5SZbigniew Kurzynski                     messages::unrecognizedRequestBody(asyncResp->res);
106958eb238fSKowalski, Kamil                     return;
107058eb238fSKowalski, Kamil                 }
107158eb238fSKowalski, Kamil 
107258eb238fSKowalski, Kamil                 std::shared_ptr<CertificateFile> certFile =
107358eb238fSKowalski, Kamil                     std::make_shared<CertificateFile>(certFileBody);
107458eb238fSKowalski, Kamil 
107537cce918SMarri Devender Rao                 crow::connections::systemBus->async_method_call(
1076656ec7e3SZbigniew Kurzynski                     [asyncResp, certFile](const boost::system::error_code ec,
1077656ec7e3SZbigniew Kurzynski                                           const std::string& objectPath) {
107837cce918SMarri Devender Rao                         if (ec)
107937cce918SMarri Devender Rao                         {
108037cce918SMarri Devender Rao                             BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
108137cce918SMarri Devender Rao                             messages::internalError(asyncResp->res);
108237cce918SMarri Devender Rao                             return;
108337cce918SMarri Devender Rao                         }
1084656ec7e3SZbigniew Kurzynski                         long certId = getIDFromURL(objectPath);
1085656ec7e3SZbigniew Kurzynski                         if (certId < 0)
1086656ec7e3SZbigniew Kurzynski                         {
1087656ec7e3SZbigniew Kurzynski                             BMCWEB_LOG_ERROR << "Invalid objectPath value"
1088656ec7e3SZbigniew Kurzynski                                              << objectPath;
1089656ec7e3SZbigniew Kurzynski                             messages::internalError(asyncResp->res);
1090656ec7e3SZbigniew Kurzynski                             return;
1091656ec7e3SZbigniew Kurzynski                         }
109237cce918SMarri Devender Rao                         std::string certURL =
109337cce918SMarri Devender Rao                             "/redfish/v1/AccountService/LDAP/Certificates/" +
109437cce918SMarri Devender Rao                             std::to_string(certId);
109537cce918SMarri Devender Rao                         getCertificateProperties(asyncResp, objectPath,
109637cce918SMarri Devender Rao                                                  certs::ldapServiceName, certId,
109737cce918SMarri Devender Rao                                                  certURL, "LDAP Certificate");
109837cce918SMarri Devender Rao                         BMCWEB_LOG_DEBUG << "LDAP certificate install file="
109937cce918SMarri Devender Rao                                          << certFile->getCertFilePath();
110037cce918SMarri Devender Rao                     },
110137cce918SMarri Devender Rao                     certs::ldapServiceName, certs::ldapObjectPath,
11027e860f15SJohn Edward Broadbent                     certs::certInstallIntf, "Install",
11037e860f15SJohn Edward Broadbent                     certFile->getCertFilePath());
11047e860f15SJohn Edward Broadbent             });
11057e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificateCollection
110637cce918SMarri Devender Rao 
110737cce918SMarri Devender Rao /**
110837cce918SMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
110937cce918SMarri Devender Rao  * of a component, account or service.
111037cce918SMarri Devender Rao  */
11117e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificate(App& app)
111237cce918SMarri Devender Rao {
11137e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/")
1114ed398213SEd Tanous         .privileges(redfish::privileges::getCertificate)
11157e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
11167e860f15SJohn Edward Broadbent             [](const crow::Request& req,
11177e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
11187e860f15SJohn Edward Broadbent                const std::string&) {
111937cce918SMarri Devender Rao                 long id = getIDFromURL(req.url);
112037cce918SMarri Devender Rao                 if (id < 0)
112137cce918SMarri Devender Rao                 {
112237cce918SMarri Devender Rao                     BMCWEB_LOG_ERROR << "Invalid url value" << req.url;
112337cce918SMarri Devender Rao                     messages::internalError(asyncResp->res);
112437cce918SMarri Devender Rao                     return;
112537cce918SMarri Devender Rao                 }
11267e860f15SJohn Edward Broadbent                 BMCWEB_LOG_DEBUG << "LDAP Certificate ID="
11277e860f15SJohn Edward Broadbent                                  << std::to_string(id);
11287e860f15SJohn Edward Broadbent                 std::string certURL =
11297e860f15SJohn Edward Broadbent                     "/redfish/v1/AccountService/LDAP/Certificates/" +
113037cce918SMarri Devender Rao                     std::to_string(id);
113137cce918SMarri Devender Rao                 std::string objectPath = certs::ldapObjectPath;
113237cce918SMarri Devender Rao                 objectPath += "/";
113337cce918SMarri Devender Rao                 objectPath += std::to_string(id);
11347e860f15SJohn Edward Broadbent                 getCertificateProperties(asyncResp, objectPath,
11357e860f15SJohn Edward Broadbent                                          certs::ldapServiceName, id, certURL,
11367e860f15SJohn Edward Broadbent                                          "LDAP Certificate");
11377e860f15SJohn Edward Broadbent             });
11387e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificate
1139cfcd5f6bSMarri Devender Rao /**
1140cfcd5f6bSMarri Devender Rao  * Collection of TrustStoreCertificate certificates
1141cfcd5f6bSMarri Devender Rao  */
11427e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificateCollection(App& app)
1143cfcd5f6bSMarri Devender Rao {
11447e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
1145ed398213SEd Tanous         .privileges(redfish::privileges::getCertificate)
11460fda0f12SGeorge Liu         .methods(
11470fda0f12SGeorge Liu             boost::beast::http::verb::
11480fda0f12SGeorge Liu                 get)([](const crow::Request&,
11497e860f15SJohn Edward Broadbent                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
11508d1b46d7Szhanghch05             asyncResp->res.jsonValue = {
11517e860f15SJohn Edward Broadbent                 {"@odata.id",
11527e860f15SJohn Edward Broadbent                  "/redfish/v1/Managers/bmc/Truststore/Certificates/"},
11530fda0f12SGeorge Liu                 {"@odata.type", "#CertificateCollection.CertificateCollection"},
1154cfcd5f6bSMarri Devender Rao                 {"Name", "TrustStore Certificates Collection"},
1155cfcd5f6bSMarri Devender Rao                 {"Description",
1156cfcd5f6bSMarri Devender Rao                  "A Collection of TrustStore certificate instances"}};
11578d1b46d7Szhanghch05 
1158cfcd5f6bSMarri Devender Rao             crow::connections::systemBus->async_method_call(
1159cfcd5f6bSMarri Devender Rao                 [asyncResp](const boost::system::error_code ec,
1160711ac7a9SEd Tanous                             const dbus::utility::ManagedObjectType& certs) {
1161cfcd5f6bSMarri Devender Rao                     if (ec)
1162cfcd5f6bSMarri Devender Rao                     {
1163cfcd5f6bSMarri Devender Rao                         BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
1164cfcd5f6bSMarri Devender Rao                         messages::internalError(asyncResp->res);
1165cfcd5f6bSMarri Devender Rao                         return;
1166cfcd5f6bSMarri Devender Rao                     }
11677e860f15SJohn Edward Broadbent                     nlohmann::json& members =
11687e860f15SJohn Edward Broadbent                         asyncResp->res.jsonValue["Members"];
1169cfcd5f6bSMarri Devender Rao                     members = nlohmann::json::array();
1170cfcd5f6bSMarri Devender Rao                     for (const auto& cert : certs)
1171cfcd5f6bSMarri Devender Rao                     {
1172cfcd5f6bSMarri Devender Rao                         long id = getIDFromURL(cert.first.str);
1173cfcd5f6bSMarri Devender Rao                         if (id >= 0)
1174cfcd5f6bSMarri Devender Rao                         {
1175cfcd5f6bSMarri Devender Rao                             members.push_back(
11760fda0f12SGeorge Liu                                 {{"@odata.id",
11770fda0f12SGeorge Liu                                   "/redfish/v1/Managers/bmc/Truststore/Certificates/" +
1178cfcd5f6bSMarri Devender Rao                                       std::to_string(id)}});
1179cfcd5f6bSMarri Devender Rao                         }
1180cfcd5f6bSMarri Devender Rao                     }
1181cfcd5f6bSMarri Devender Rao                     asyncResp->res.jsonValue["Members@odata.count"] =
1182cfcd5f6bSMarri Devender Rao                         members.size();
1183cfcd5f6bSMarri Devender Rao                 },
1184cfcd5f6bSMarri Devender Rao                 certs::authorityServiceName, certs::authorityObjectPath,
1185cfcd5f6bSMarri Devender Rao                 certs::dbusObjManagerIntf, "GetManagedObjects");
11867e860f15SJohn Edward Broadbent         });
1187cfcd5f6bSMarri Devender Rao 
11887e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
1189ed398213SEd Tanous         .privileges(redfish::privileges::postCertificateCollection)
11900fda0f12SGeorge Liu         .methods(
11910fda0f12SGeorge Liu             boost::beast::http::verb::
11920fda0f12SGeorge Liu                 post)([](const crow::Request& req,
11937e860f15SJohn Edward Broadbent                          const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
11947e860f15SJohn Edward Broadbent             std::string certFileBody =
11957e860f15SJohn Edward Broadbent                 getCertificateFromReqBody(asyncResp, req);
1196a08752f5SZbigniew Kurzynski 
1197a08752f5SZbigniew Kurzynski             if (certFileBody.empty())
1198a08752f5SZbigniew Kurzynski             {
11990fda0f12SGeorge Liu                 BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
1200a08752f5SZbigniew Kurzynski                 messages::unrecognizedRequestBody(asyncResp->res);
1201a08752f5SZbigniew Kurzynski                 return;
1202a08752f5SZbigniew Kurzynski             }
1203a08752f5SZbigniew Kurzynski 
1204a08752f5SZbigniew Kurzynski             std::shared_ptr<CertificateFile> certFile =
1205a08752f5SZbigniew Kurzynski                 std::make_shared<CertificateFile>(certFileBody);
1206cfcd5f6bSMarri Devender Rao             crow::connections::systemBus->async_method_call(
1207656ec7e3SZbigniew Kurzynski                 [asyncResp, certFile](const boost::system::error_code ec,
1208656ec7e3SZbigniew Kurzynski                                       const std::string& objectPath) {
1209cfcd5f6bSMarri Devender Rao                     if (ec)
1210cfcd5f6bSMarri Devender Rao                     {
1211cfcd5f6bSMarri Devender Rao                         BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
1212cfcd5f6bSMarri Devender Rao                         messages::internalError(asyncResp->res);
1213cfcd5f6bSMarri Devender Rao                         return;
1214cfcd5f6bSMarri Devender Rao                     }
1215656ec7e3SZbigniew Kurzynski                     long certId = getIDFromURL(objectPath);
1216656ec7e3SZbigniew Kurzynski                     if (certId < 0)
1217656ec7e3SZbigniew Kurzynski                     {
1218656ec7e3SZbigniew Kurzynski                         BMCWEB_LOG_ERROR << "Invalid objectPath value"
1219656ec7e3SZbigniew Kurzynski                                          << objectPath;
1220656ec7e3SZbigniew Kurzynski                         messages::internalError(asyncResp->res);
1221656ec7e3SZbigniew Kurzynski                         return;
1222656ec7e3SZbigniew Kurzynski                     }
12230fda0f12SGeorge Liu                     std::string certURL =
12240fda0f12SGeorge Liu                         "/redfish/v1/Managers/bmc/Truststore/Certificates/" +
1225cfcd5f6bSMarri Devender Rao                         std::to_string(certId);
1226656ec7e3SZbigniew Kurzynski 
12277e860f15SJohn Edward Broadbent                     getCertificateProperties(
12287e860f15SJohn Edward Broadbent                         asyncResp, objectPath, certs::authorityServiceName,
12297e860f15SJohn Edward Broadbent                         certId, certURL, "TrustStore Certificate");
12300fda0f12SGeorge Liu                     BMCWEB_LOG_DEBUG << "TrustStore certificate install file="
1231cfcd5f6bSMarri Devender Rao                                      << certFile->getCertFilePath();
1232cfcd5f6bSMarri Devender Rao                 },
1233cfcd5f6bSMarri Devender Rao                 certs::authorityServiceName, certs::authorityObjectPath,
12340fda0f12SGeorge Liu                 certs::certInstallIntf, "Install", certFile->getCertFilePath());
12357e860f15SJohn Edward Broadbent         });
12367e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificateCollection
1237cfcd5f6bSMarri Devender Rao 
1238cfcd5f6bSMarri Devender Rao /**
1239cfcd5f6bSMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
1240cfcd5f6bSMarri Devender Rao  * of a component, account or service.
1241cfcd5f6bSMarri Devender Rao  */
12427e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificate(App& app)
1243cfcd5f6bSMarri Devender Rao {
12447e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
1245ed398213SEd Tanous         .privileges(redfish::privileges::getCertificate)
12467e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
12477e860f15SJohn Edward Broadbent             [](const crow::Request& req,
12487e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
12497e860f15SJohn Edward Broadbent                const std::string&) {
1250cfcd5f6bSMarri Devender Rao                 long id = getIDFromURL(req.url);
1251cfcd5f6bSMarri Devender Rao                 if (id < 0)
1252cfcd5f6bSMarri Devender Rao                 {
1253cfcd5f6bSMarri Devender Rao                     BMCWEB_LOG_ERROR << "Invalid url value" << req.url;
1254cfcd5f6bSMarri Devender Rao                     messages::internalError(asyncResp->res);
1255cfcd5f6bSMarri Devender Rao                     return;
1256cfcd5f6bSMarri Devender Rao                 }
1257cfcd5f6bSMarri Devender Rao                 BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doGet ID="
1258cfcd5f6bSMarri Devender Rao                                  << std::to_string(id);
1259cfcd5f6bSMarri Devender Rao                 std::string certURL =
1260cfcd5f6bSMarri Devender Rao                     "/redfish/v1/Managers/bmc/Truststore/Certificates/" +
1261cfcd5f6bSMarri Devender Rao                     std::to_string(id);
1262cfcd5f6bSMarri Devender Rao                 std::string objectPath = certs::authorityObjectPath;
1263cfcd5f6bSMarri Devender Rao                 objectPath += "/";
1264cfcd5f6bSMarri Devender Rao                 objectPath += std::to_string(id);
1265cfcd5f6bSMarri Devender Rao                 getCertificateProperties(asyncResp, objectPath,
12667e860f15SJohn Edward Broadbent                                          certs::authorityServiceName, id,
12677e860f15SJohn Edward Broadbent                                          certURL, "TrustStore Certificate");
12687e860f15SJohn Edward Broadbent             });
126907a60299SZbigniew Kurzynski 
12707e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
1271ed398213SEd Tanous         .privileges(redfish::privileges::deleteCertificate)
12727e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::delete_)(
12737e860f15SJohn Edward Broadbent             [](const crow::Request& req,
12747e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
12757e860f15SJohn Edward Broadbent                const std::string& param) {
12767e860f15SJohn Edward Broadbent                 if (param.empty())
127707a60299SZbigniew Kurzynski                 {
127807a60299SZbigniew Kurzynski                     messages::internalError(asyncResp->res);
127907a60299SZbigniew Kurzynski                     return;
128007a60299SZbigniew Kurzynski                 }
128107a60299SZbigniew Kurzynski 
128207a60299SZbigniew Kurzynski                 long id = getIDFromURL(req.url);
128307a60299SZbigniew Kurzynski                 if (id < 0)
128407a60299SZbigniew Kurzynski                 {
128507a60299SZbigniew Kurzynski                     BMCWEB_LOG_ERROR << "Invalid url value: " << req.url;
12867e860f15SJohn Edward Broadbent                     messages::resourceNotFound(asyncResp->res,
12877e860f15SJohn Edward Broadbent                                                "TrustStore Certificate",
128807a60299SZbigniew Kurzynski                                                std::string(req.url));
128907a60299SZbigniew Kurzynski                     return;
129007a60299SZbigniew Kurzynski                 }
129107a60299SZbigniew Kurzynski                 BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doDelete ID="
129207a60299SZbigniew Kurzynski                                  << std::to_string(id);
129307a60299SZbigniew Kurzynski                 std::string certPath = certs::authorityObjectPath;
129407a60299SZbigniew Kurzynski                 certPath += "/";
129507a60299SZbigniew Kurzynski                 certPath += std::to_string(id);
129607a60299SZbigniew Kurzynski 
129707a60299SZbigniew Kurzynski                 crow::connections::systemBus->async_method_call(
129807a60299SZbigniew Kurzynski                     [asyncResp, id](const boost::system::error_code ec) {
129907a60299SZbigniew Kurzynski                         if (ec)
130007a60299SZbigniew Kurzynski                         {
130107a60299SZbigniew Kurzynski                             messages::resourceNotFound(asyncResp->res,
130207a60299SZbigniew Kurzynski                                                        "TrustStore Certificate",
130307a60299SZbigniew Kurzynski                                                        std::to_string(id));
130407a60299SZbigniew Kurzynski                             return;
130507a60299SZbigniew Kurzynski                         }
130607a60299SZbigniew Kurzynski                         BMCWEB_LOG_INFO << "Certificate deleted";
13077e860f15SJohn Edward Broadbent                         asyncResp->res.result(
13087e860f15SJohn Edward Broadbent                             boost::beast::http::status::no_content);
130907a60299SZbigniew Kurzynski                     },
131007a60299SZbigniew Kurzynski                     certs::authorityServiceName, certPath, certs::objDeleteIntf,
131107a60299SZbigniew Kurzynski                     "Delete");
13127e860f15SJohn Edward Broadbent             });
13137e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificate
13145968caeeSMarri Devender Rao } // namespace redfish
1315