xref: /openbmc/bmcweb/features/redfish/lib/certificate_service.hpp (revision 1e31259812dd195015f4e415675ed97b804829a6)
15968caeeSMarri Devender Rao #pragma once
25968caeeSMarri Devender Rao 
37e860f15SJohn Edward Broadbent #include <app.hpp>
490d2d1e8SJiaqing Zhao #include <boost/system/linux_error.hpp>
5168e20c1SEd Tanous #include <dbus_utility.hpp>
645ca1b86SEd Tanous #include <query.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* certInstallIntf = "xyz.openbmc_project.Certs.Install";
145968caeeSMarri Devender Rao constexpr char const* certReplaceIntf = "xyz.openbmc_project.Certs.Replace";
1507a60299SZbigniew Kurzynski constexpr char const* objDeleteIntf = "xyz.openbmc_project.Object.Delete";
165968caeeSMarri Devender Rao constexpr char const* certPropIntf = "xyz.openbmc_project.Certs.Certificate";
175968caeeSMarri Devender Rao constexpr char const* dbusPropIntf = "org.freedesktop.DBus.Properties";
185968caeeSMarri Devender Rao constexpr char const* dbusObjManagerIntf = "org.freedesktop.DBus.ObjectManager";
1937cce918SMarri Devender Rao constexpr char const* httpsServiceName =
2037cce918SMarri Devender Rao     "xyz.openbmc_project.Certs.Manager.Server.Https";
2137cce918SMarri Devender Rao constexpr char const* ldapServiceName =
2237cce918SMarri Devender Rao     "xyz.openbmc_project.Certs.Manager.Client.Ldap";
23cfcd5f6bSMarri Devender Rao constexpr char const* authorityServiceName =
24cfcd5f6bSMarri Devender Rao     "xyz.openbmc_project.Certs.Manager.Authority.Ldap";
25c6a8dfb1SJiaqing Zhao constexpr char const* baseObjectPath = "/xyz/openbmc_project/certs";
26c6a8dfb1SJiaqing Zhao constexpr char const* httpsObjectPath =
27c6a8dfb1SJiaqing Zhao     "/xyz/openbmc_project/certs/server/https";
28c6a8dfb1SJiaqing Zhao constexpr char const* ldapObjectPath = "/xyz/openbmc_project/certs/client/ldap";
29cfcd5f6bSMarri Devender Rao constexpr char const* authorityObjectPath =
30cfcd5f6bSMarri Devender Rao     "/xyz/openbmc_project/certs/authority/ldap";
315968caeeSMarri Devender Rao } // namespace certs
325968caeeSMarri Devender Rao 
335968caeeSMarri Devender Rao /**
345968caeeSMarri Devender Rao  * The Certificate schema defines a Certificate Service which represents the
355968caeeSMarri Devender Rao  * actions available to manage certificates and links to where certificates
365968caeeSMarri Devender Rao  * are installed.
375968caeeSMarri Devender Rao  */
387e860f15SJohn Edward Broadbent 
395968caeeSMarri Devender Rao // TODO: Issue#61 No entries are available for Certificate
404e0453b1SGunnar Mills // service at https://www.dmtf.org/standards/redfish
415968caeeSMarri Devender Rao // "redfish standard registries". Need to modify after DMTF
425968caeeSMarri Devender Rao // publish Privilege details for certificate service
435968caeeSMarri Devender Rao 
447e860f15SJohn Edward Broadbent inline void requestRoutesCertificateService(App& app)
455968caeeSMarri Devender Rao {
467e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/")
47ed398213SEd Tanous         .privileges(redfish::privileges::getCertificateService)
48002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
49002d39b4SEd Tanous             [&app](const crow::Request& req,
50002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
513ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
5245ca1b86SEd Tanous         {
5345ca1b86SEd Tanous             return;
5445ca1b86SEd Tanous         }
551476687dSEd Tanous 
561476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
571476687dSEd Tanous             "#CertificateService.v1_0_0.CertificateService";
581476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
591476687dSEd Tanous             "/redfish/v1/CertificateService";
601476687dSEd Tanous         asyncResp->res.jsonValue["Id"] = "CertificateService";
611476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = "Certificate Service";
621476687dSEd Tanous         asyncResp->res.jsonValue["Description"] =
631476687dSEd Tanous             "Actions available to manage certificates";
6472048780SAbhishek Patel         // /redfish/v1/CertificateService/CertificateLocations is something
6572048780SAbhishek Patel         // only ConfigureManager can access then only display when the user
6672048780SAbhishek Patel         // has permissions ConfigureManager
6772048780SAbhishek Patel         Privileges effectiveUserPrivileges =
6872048780SAbhishek Patel             redfish::getUserPrivileges(req.userRole);
6972048780SAbhishek Patel         if (isOperationAllowedWithPrivileges({{"ConfigureManager"}},
7072048780SAbhishek Patel                                              effectiveUserPrivileges))
7172048780SAbhishek Patel         {
721476687dSEd Tanous             asyncResp->res.jsonValue["CertificateLocations"]["@odata.id"] =
731476687dSEd Tanous                 "/redfish/v1/CertificateService/CertificateLocations";
7472048780SAbhishek Patel         }
750fda0f12SGeorge Liu         asyncResp->res
76002d39b4SEd Tanous             .jsonValue["Actions"]["#CertificateService.ReplaceCertificate"] = {
770fda0f12SGeorge Liu             {"target",
780fda0f12SGeorge Liu              "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate"},
795968caeeSMarri Devender Rao             {"CertificateType@Redfish.AllowableValues", {"PEM"}}};
807e860f15SJohn Edward Broadbent         asyncResp->res
817e860f15SJohn Edward Broadbent             .jsonValue["Actions"]["#CertificateService.GenerateCSR"] = {
820fda0f12SGeorge Liu             {"target",
830fda0f12SGeorge Liu              "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR"}};
847e860f15SJohn Edward Broadbent         });
857e860f15SJohn Edward Broadbent } // requestRoutesCertificateService
8637cce918SMarri Devender Rao 
878d1b46d7Szhanghch05 inline std::string getCertificateFromReqBody(
888d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
8958eb238fSKowalski, Kamil     const crow::Request& req)
9058eb238fSKowalski, Kamil {
9158eb238fSKowalski, Kamil     nlohmann::json reqJson = nlohmann::json::parse(req.body, nullptr, false);
9258eb238fSKowalski, Kamil 
9358eb238fSKowalski, Kamil     if (reqJson.is_discarded())
9458eb238fSKowalski, Kamil     {
9558eb238fSKowalski, Kamil         // We did not receive JSON request, proceed as it is RAW data
9658eb238fSKowalski, Kamil         return req.body;
9758eb238fSKowalski, Kamil     }
9858eb238fSKowalski, Kamil 
9958eb238fSKowalski, Kamil     std::string certificate;
10058eb238fSKowalski, Kamil     std::optional<std::string> certificateType = "PEM";
10158eb238fSKowalski, Kamil 
10215ed6780SWilly Tu     if (!json_util::readJsonPatch(req, asyncResp->res, "CertificateString",
10315ed6780SWilly Tu                                   certificate, "CertificateType",
10415ed6780SWilly Tu                                   certificateType))
10558eb238fSKowalski, Kamil     {
10658eb238fSKowalski, Kamil         BMCWEB_LOG_ERROR << "Required parameters are missing";
10758eb238fSKowalski, Kamil         messages::internalError(asyncResp->res);
108abb93cddSEd Tanous         return {};
10958eb238fSKowalski, Kamil     }
11058eb238fSKowalski, Kamil 
11158eb238fSKowalski, Kamil     if (*certificateType != "PEM")
11258eb238fSKowalski, Kamil     {
11358eb238fSKowalski, Kamil         messages::propertyValueNotInList(asyncResp->res, *certificateType,
11458eb238fSKowalski, Kamil                                          "CertificateType");
115abb93cddSEd Tanous         return {};
11658eb238fSKowalski, Kamil     }
11758eb238fSKowalski, Kamil 
11858eb238fSKowalski, Kamil     return certificate;
11958eb238fSKowalski, Kamil }
12058eb238fSKowalski, Kamil 
1215968caeeSMarri Devender Rao /**
1225968caeeSMarri Devender Rao  * Class to create a temporary certificate file for uploading to system
1235968caeeSMarri Devender Rao  */
1245968caeeSMarri Devender Rao class CertificateFile
1255968caeeSMarri Devender Rao {
1265968caeeSMarri Devender Rao   public:
1275968caeeSMarri Devender Rao     CertificateFile() = delete;
1285968caeeSMarri Devender Rao     CertificateFile(const CertificateFile&) = delete;
1295968caeeSMarri Devender Rao     CertificateFile& operator=(const CertificateFile&) = delete;
1305968caeeSMarri Devender Rao     CertificateFile(CertificateFile&&) = delete;
1315968caeeSMarri Devender Rao     CertificateFile& operator=(CertificateFile&&) = delete;
1324e23a444SEd Tanous     explicit CertificateFile(const std::string& certString)
1335968caeeSMarri Devender Rao     {
13472d52d25SEd Tanous         std::array<char, 18> dirTemplate = {'/', 't', 'm', 'p', '/', 'C',
1355207438cSEd Tanous                                             'e', 'r', 't', 's', '.', 'X',
1365207438cSEd Tanous                                             'X', 'X', 'X', 'X', 'X', '\0'};
1375207438cSEd Tanous         char* tempDirectory = mkdtemp(dirTemplate.data());
138e662eae8SEd Tanous         if (tempDirectory != nullptr)
1395968caeeSMarri Devender Rao         {
1405968caeeSMarri Devender Rao             certDirectory = tempDirectory;
1415968caeeSMarri Devender Rao             certificateFile = certDirectory / "cert.pem";
1425968caeeSMarri Devender Rao             std::ofstream out(certificateFile, std::ofstream::out |
1435968caeeSMarri Devender Rao                                                    std::ofstream::binary |
1445968caeeSMarri Devender Rao                                                    std::ofstream::trunc);
1455968caeeSMarri Devender Rao             out << certString;
1465968caeeSMarri Devender Rao             out.close();
1478cc8edecSEd Tanous             BMCWEB_LOG_DEBUG << "Creating certificate file"
1488cc8edecSEd Tanous                              << certificateFile.string();
1495968caeeSMarri Devender Rao         }
1505968caeeSMarri Devender Rao     }
1515968caeeSMarri Devender Rao     ~CertificateFile()
1525968caeeSMarri Devender Rao     {
1535968caeeSMarri Devender Rao         if (std::filesystem::exists(certDirectory))
1545968caeeSMarri Devender Rao         {
1558cc8edecSEd Tanous             BMCWEB_LOG_DEBUG << "Removing certificate file"
1568cc8edecSEd Tanous                              << certificateFile.string();
15723a21a1cSEd Tanous             std::error_code ec;
15823a21a1cSEd Tanous             std::filesystem::remove_all(certDirectory, ec);
15923a21a1cSEd Tanous             if (ec)
1605968caeeSMarri Devender Rao             {
1615968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "Failed to remove temp directory"
1628cc8edecSEd Tanous                                  << certDirectory.string();
1635968caeeSMarri Devender Rao             }
1645968caeeSMarri Devender Rao         }
1655968caeeSMarri Devender Rao     }
1665968caeeSMarri Devender Rao     std::string getCertFilePath()
1675968caeeSMarri Devender Rao     {
1685968caeeSMarri Devender Rao         return certificateFile;
1695968caeeSMarri Devender Rao     }
1705968caeeSMarri Devender Rao 
1715968caeeSMarri Devender Rao   private:
1725968caeeSMarri Devender Rao     std::filesystem::path certificateFile;
1735968caeeSMarri Devender Rao     std::filesystem::path certDirectory;
1745968caeeSMarri Devender Rao };
1755968caeeSMarri Devender Rao 
17659d494eeSPatrick Williams static std::unique_ptr<sdbusplus::bus::match_t> csrMatcher;
17730215816SMarri Devender Rao /**
17830215816SMarri Devender Rao  * @brief Read data from CSR D-bus object and set to response
17930215816SMarri Devender Rao  *
18030215816SMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
18130215816SMarri Devender Rao  * @param[in] certURI Link to certifiate collection URI
18230215816SMarri Devender Rao  * @param[in] service D-Bus service name
18330215816SMarri Devender Rao  * @param[in] certObjPath certificate D-Bus object path
18430215816SMarri Devender Rao  * @param[in] csrObjPath CSR D-Bus object path
18530215816SMarri Devender Rao  * @return None
18630215816SMarri Devender Rao  */
1878d1b46d7Szhanghch05 static void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
18830215816SMarri Devender Rao                    const std::string& certURI, const std::string& service,
18930215816SMarri Devender Rao                    const std::string& certObjPath,
19030215816SMarri Devender Rao                    const std::string& csrObjPath)
19130215816SMarri Devender Rao {
19230215816SMarri Devender Rao     BMCWEB_LOG_DEBUG << "getCSR CertObjectPath" << certObjPath
19330215816SMarri Devender Rao                      << " CSRObjectPath=" << csrObjPath
19430215816SMarri Devender Rao                      << " service=" << service;
19530215816SMarri Devender Rao     crow::connections::systemBus->async_method_call(
19630215816SMarri Devender Rao         [asyncResp, certURI](const boost::system::error_code ec,
19730215816SMarri Devender Rao                              const std::string& csr) {
19830215816SMarri Devender Rao         if (ec)
19930215816SMarri Devender Rao         {
20030215816SMarri Devender Rao             BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
20130215816SMarri Devender Rao             messages::internalError(asyncResp->res);
20230215816SMarri Devender Rao             return;
20330215816SMarri Devender Rao         }
20430215816SMarri Devender Rao         if (csr.empty())
20530215816SMarri Devender Rao         {
20630215816SMarri Devender Rao             BMCWEB_LOG_ERROR << "CSR read is empty";
20730215816SMarri Devender Rao             messages::internalError(asyncResp->res);
20830215816SMarri Devender Rao             return;
20930215816SMarri Devender Rao         }
21030215816SMarri Devender Rao         asyncResp->res.jsonValue["CSRString"] = csr;
2111476687dSEd Tanous         asyncResp->res.jsonValue["CertificateCollection"]["@odata.id"] =
2121476687dSEd Tanous             certURI;
21330215816SMarri Devender Rao         },
21430215816SMarri Devender Rao         service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR");
21530215816SMarri Devender Rao }
21630215816SMarri Devender Rao 
21730215816SMarri Devender Rao /**
21830215816SMarri Devender Rao  * Action to Generate CSR
21930215816SMarri Devender Rao  */
2207e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionGenerateCSR(App& app)
22130215816SMarri Devender Rao {
2220fda0f12SGeorge Liu     BMCWEB_ROUTE(
2230fda0f12SGeorge Liu         app,
2240fda0f12SGeorge Liu         "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR/")
2255344ab8eSAbhishek Patel         .privileges(redfish::privileges::postCertificateService)
226002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
227002d39b4SEd Tanous             [&app](const crow::Request& req,
2287e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2293ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
23045ca1b86SEd Tanous         {
23145ca1b86SEd Tanous             return;
23245ca1b86SEd Tanous         }
2332c70f800SEd Tanous         static const int rsaKeyBitLength = 2048;
2348d1b46d7Szhanghch05 
23530215816SMarri Devender Rao         // Required parameters
23630215816SMarri Devender Rao         std::string city;
23730215816SMarri Devender Rao         std::string commonName;
23830215816SMarri Devender Rao         std::string country;
23930215816SMarri Devender Rao         std::string organization;
24030215816SMarri Devender Rao         std::string organizationalUnit;
24130215816SMarri Devender Rao         std::string state;
24230215816SMarri Devender Rao         nlohmann::json certificateCollection;
24330215816SMarri Devender Rao 
24430215816SMarri Devender Rao         // Optional parameters
24530215816SMarri Devender Rao         std::optional<std::vector<std::string>> optAlternativeNames =
24630215816SMarri Devender Rao             std::vector<std::string>();
24730215816SMarri Devender Rao         std::optional<std::string> optContactPerson = "";
24830215816SMarri Devender Rao         std::optional<std::string> optChallengePassword = "";
24930215816SMarri Devender Rao         std::optional<std::string> optEmail = "";
25030215816SMarri Devender Rao         std::optional<std::string> optGivenName = "";
25130215816SMarri Devender Rao         std::optional<std::string> optInitials = "";
2522c70f800SEd Tanous         std::optional<int64_t> optKeyBitLength = rsaKeyBitLength;
253aaf3206fSVernon Mauery         std::optional<std::string> optKeyCurveId = "secp384r1";
25430215816SMarri Devender Rao         std::optional<std::string> optKeyPairAlgorithm = "EC";
25530215816SMarri Devender Rao         std::optional<std::vector<std::string>> optKeyUsage =
25630215816SMarri Devender Rao             std::vector<std::string>();
25730215816SMarri Devender Rao         std::optional<std::string> optSurname = "";
25830215816SMarri Devender Rao         std::optional<std::string> optUnstructuredName = "";
25915ed6780SWilly Tu         if (!json_util::readJsonAction(
2600fda0f12SGeorge Liu                 req, asyncResp->res, "City", city, "CommonName", commonName,
2610fda0f12SGeorge Liu                 "ContactPerson", optContactPerson, "Country", country,
2620fda0f12SGeorge Liu                 "Organization", organization, "OrganizationalUnit",
2630fda0f12SGeorge Liu                 organizationalUnit, "State", state, "CertificateCollection",
264002d39b4SEd Tanous                 certificateCollection, "AlternativeNames", optAlternativeNames,
265002d39b4SEd Tanous                 "ChallengePassword", optChallengePassword, "Email", optEmail,
266002d39b4SEd Tanous                 "GivenName", optGivenName, "Initials", optInitials,
267002d39b4SEd Tanous                 "KeyBitLength", optKeyBitLength, "KeyCurveId", optKeyCurveId,
2680fda0f12SGeorge Liu                 "KeyPairAlgorithm", optKeyPairAlgorithm, "KeyUsage",
2690fda0f12SGeorge Liu                 optKeyUsage, "Surname", optSurname, "UnstructuredName",
2700fda0f12SGeorge Liu                 optUnstructuredName))
27130215816SMarri Devender Rao         {
27230215816SMarri Devender Rao             return;
27330215816SMarri Devender Rao         }
27430215816SMarri Devender Rao 
27530215816SMarri Devender Rao         // bmcweb has no way to store or decode a private key challenge
2767e860f15SJohn Edward Broadbent         // password, which will likely cause bmcweb to crash on startup
2777e860f15SJohn Edward Broadbent         // if this is not set on a post so not allowing the user to set
2787e860f15SJohn Edward Broadbent         // value
27926f6976fSEd Tanous         if (!optChallengePassword->empty())
28030215816SMarri Devender Rao         {
281002d39b4SEd Tanous             messages::actionParameterNotSupported(asyncResp->res, "GenerateCSR",
282002d39b4SEd Tanous                                                   "ChallengePassword");
28330215816SMarri Devender Rao             return;
28430215816SMarri Devender Rao         }
28530215816SMarri Devender Rao 
28630215816SMarri Devender Rao         std::string certURI;
287002d39b4SEd Tanous         if (!redfish::json_util::readJson(certificateCollection, asyncResp->res,
288002d39b4SEd Tanous                                           "@odata.id", certURI))
28930215816SMarri Devender Rao         {
29030215816SMarri Devender Rao             return;
29130215816SMarri Devender Rao         }
29230215816SMarri Devender Rao 
29330215816SMarri Devender Rao         std::string objectPath;
29430215816SMarri Devender Rao         std::string service;
29511ba3979SEd Tanous         if (certURI.starts_with(
2960fda0f12SGeorge Liu                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"))
29730215816SMarri Devender Rao         {
29830215816SMarri Devender Rao             objectPath = certs::httpsObjectPath;
29930215816SMarri Devender Rao             service = certs::httpsServiceName;
30030215816SMarri Devender Rao         }
30111ba3979SEd Tanous         else if (certURI.starts_with(
30211ba3979SEd Tanous                      "/redfish/v1/AccountService/LDAP/Certificates"))
3033b7f0149SMarri Devender Rao         {
3043b7f0149SMarri Devender Rao             objectPath = certs::ldapObjectPath;
3053b7f0149SMarri Devender Rao             service = certs::ldapServiceName;
3063b7f0149SMarri Devender Rao         }
30730215816SMarri Devender Rao         else
30830215816SMarri Devender Rao         {
30930215816SMarri Devender Rao             messages::actionParameterNotSupported(
31030215816SMarri Devender Rao                 asyncResp->res, "CertificateCollection", "GenerateCSR");
31130215816SMarri Devender Rao             return;
31230215816SMarri Devender Rao         }
31330215816SMarri Devender Rao 
31430215816SMarri Devender Rao         // supporting only EC and RSA algorithm
3150fda0f12SGeorge Liu         if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA")
31630215816SMarri Devender Rao         {
31730215816SMarri Devender Rao             messages::actionParameterNotSupported(
31830215816SMarri Devender Rao                 asyncResp->res, "KeyPairAlgorithm", "GenerateCSR");
31930215816SMarri Devender Rao             return;
32030215816SMarri Devender Rao         }
32130215816SMarri Devender Rao 
3227e860f15SJohn Edward Broadbent         // supporting only 2048 key bit length for RSA algorithm due to
3237e860f15SJohn Edward Broadbent         // time consumed in generating private key
32430215816SMarri Devender Rao         if (*optKeyPairAlgorithm == "RSA" &&
3252c70f800SEd Tanous             *optKeyBitLength != rsaKeyBitLength)
32630215816SMarri Devender Rao         {
327002d39b4SEd Tanous             messages::propertyValueNotInList(asyncResp->res,
328002d39b4SEd Tanous                                              std::to_string(*optKeyBitLength),
32930215816SMarri Devender Rao                                              "KeyBitLength");
33030215816SMarri Devender Rao             return;
33130215816SMarri Devender Rao         }
33230215816SMarri Devender Rao 
33330215816SMarri Devender Rao         // validate KeyUsage supporting only 1 type based on URL
33411ba3979SEd Tanous         if (certURI.starts_with(
3350fda0f12SGeorge Liu                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"))
33630215816SMarri Devender Rao         {
33726f6976fSEd Tanous             if (optKeyUsage->empty())
33830215816SMarri Devender Rao             {
33930215816SMarri Devender Rao                 optKeyUsage->push_back("ServerAuthentication");
34030215816SMarri Devender Rao             }
34130215816SMarri Devender Rao             else if (optKeyUsage->size() == 1)
34230215816SMarri Devender Rao             {
34330215816SMarri Devender Rao                 if ((*optKeyUsage)[0] != "ServerAuthentication")
34430215816SMarri Devender Rao                 {
34530215816SMarri Devender Rao                     messages::propertyValueNotInList(
34630215816SMarri Devender Rao                         asyncResp->res, (*optKeyUsage)[0], "KeyUsage");
34730215816SMarri Devender Rao                     return;
34830215816SMarri Devender Rao                 }
34930215816SMarri Devender Rao             }
35030215816SMarri Devender Rao             else
35130215816SMarri Devender Rao             {
35230215816SMarri Devender Rao                 messages::actionParameterNotSupported(
35330215816SMarri Devender Rao                     asyncResp->res, "KeyUsage", "GenerateCSR");
35430215816SMarri Devender Rao                 return;
35530215816SMarri Devender Rao             }
35630215816SMarri Devender Rao         }
35711ba3979SEd Tanous         else if (certURI.starts_with(
35811ba3979SEd Tanous                      "/redfish/v1/AccountService/LDAP/Certificates"))
3593b7f0149SMarri Devender Rao         {
36026f6976fSEd Tanous             if (optKeyUsage->empty())
3613b7f0149SMarri Devender Rao             {
3623b7f0149SMarri Devender Rao                 optKeyUsage->push_back("ClientAuthentication");
3633b7f0149SMarri Devender Rao             }
3643b7f0149SMarri Devender Rao             else if (optKeyUsage->size() == 1)
3653b7f0149SMarri Devender Rao             {
3663b7f0149SMarri Devender Rao                 if ((*optKeyUsage)[0] != "ClientAuthentication")
3673b7f0149SMarri Devender Rao                 {
3683b7f0149SMarri Devender Rao                     messages::propertyValueNotInList(
3693b7f0149SMarri Devender Rao                         asyncResp->res, (*optKeyUsage)[0], "KeyUsage");
3703b7f0149SMarri Devender Rao                     return;
3713b7f0149SMarri Devender Rao                 }
3723b7f0149SMarri Devender Rao             }
3733b7f0149SMarri Devender Rao             else
3743b7f0149SMarri Devender Rao             {
3753b7f0149SMarri Devender Rao                 messages::actionParameterNotSupported(
3763b7f0149SMarri Devender Rao                     asyncResp->res, "KeyUsage", "GenerateCSR");
3773b7f0149SMarri Devender Rao                 return;
3783b7f0149SMarri Devender Rao             }
3793b7f0149SMarri Devender Rao         }
38030215816SMarri Devender Rao 
3817e860f15SJohn Edward Broadbent         // Only allow one CSR matcher at a time so setting retry
3827e860f15SJohn Edward Broadbent         // time-out and timer expiry to 10 seconds for now.
3832c70f800SEd Tanous         static const int timeOut = 10;
38430215816SMarri Devender Rao         if (csrMatcher)
38530215816SMarri Devender Rao         {
386002d39b4SEd Tanous             messages::serviceTemporarilyUnavailable(asyncResp->res,
387002d39b4SEd Tanous                                                     std::to_string(timeOut));
38830215816SMarri Devender Rao             return;
38930215816SMarri Devender Rao         }
39030215816SMarri Devender Rao 
39130215816SMarri Devender Rao         // Make this static so it survives outside this method
39230215816SMarri Devender Rao         static boost::asio::steady_timer timeout(*req.ioService);
3932c70f800SEd Tanous         timeout.expires_after(std::chrono::seconds(timeOut));
394002d39b4SEd Tanous         timeout.async_wait([asyncResp](const boost::system::error_code& ec) {
39530215816SMarri Devender Rao             csrMatcher = nullptr;
39630215816SMarri Devender Rao             if (ec)
39730215816SMarri Devender Rao             {
3987e860f15SJohn Edward Broadbent                 // operation_aborted is expected if timer is canceled
3997e860f15SJohn Edward Broadbent                 // before completion.
40030215816SMarri Devender Rao                 if (ec != boost::asio::error::operation_aborted)
40130215816SMarri Devender Rao                 {
40230215816SMarri Devender Rao                     BMCWEB_LOG_ERROR << "Async_wait failed " << ec;
40330215816SMarri Devender Rao                 }
40430215816SMarri Devender Rao                 return;
40530215816SMarri Devender Rao             }
40630215816SMarri Devender Rao             BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR";
40730215816SMarri Devender Rao             messages::internalError(asyncResp->res);
40830215816SMarri Devender Rao         });
40930215816SMarri Devender Rao 
41030215816SMarri Devender Rao         // create a matcher to wait on CSR object
41130215816SMarri Devender Rao         BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath;
4120fda0f12SGeorge Liu         std::string match("type='signal',"
41330215816SMarri Devender Rao                           "interface='org.freedesktop.DBus.ObjectManager',"
41430215816SMarri Devender Rao                           "path='" +
41530215816SMarri Devender Rao                           objectPath +
41630215816SMarri Devender Rao                           "',"
41730215816SMarri Devender Rao                           "member='InterfacesAdded'");
41859d494eeSPatrick Williams         csrMatcher = std::make_unique<sdbusplus::bus::match_t>(
41930215816SMarri Devender Rao             *crow::connections::systemBus, match,
42059d494eeSPatrick Williams             [asyncResp, service, objectPath, certURI](sdbusplus::message_t& m) {
421271584abSEd Tanous             timeout.cancel();
42230215816SMarri Devender Rao             if (m.is_method_error())
42330215816SMarri Devender Rao             {
42430215816SMarri Devender Rao                 BMCWEB_LOG_ERROR << "Dbus method error!!!";
42530215816SMarri Devender Rao                 messages::internalError(asyncResp->res);
42630215816SMarri Devender Rao                 return;
42730215816SMarri Devender Rao             }
428b9d36b47SEd Tanous 
429b9d36b47SEd Tanous             dbus::utility::DBusInteracesMap interfacesProperties;
430b9d36b47SEd Tanous 
43130215816SMarri Devender Rao             sdbusplus::message::object_path csrObjectPath;
43230215816SMarri Devender Rao             m.read(csrObjectPath, interfacesProperties);
4330fda0f12SGeorge Liu             BMCWEB_LOG_DEBUG << "CSR object added" << csrObjectPath.str;
43402cad96eSEd Tanous             for (const auto& interface : interfacesProperties)
43530215816SMarri Devender Rao             {
4360fda0f12SGeorge Liu                 if (interface.first == "xyz.openbmc_project.Certs.CSR")
43730215816SMarri Devender Rao                 {
43830215816SMarri Devender Rao                     getCSR(asyncResp, certURI, service, objectPath,
43930215816SMarri Devender Rao                            csrObjectPath.str);
44030215816SMarri Devender Rao                     break;
44130215816SMarri Devender Rao                 }
44230215816SMarri Devender Rao             }
44330215816SMarri Devender Rao             });
44430215816SMarri Devender Rao         crow::connections::systemBus->async_method_call(
445914e2d5dSEd Tanous             [asyncResp](const boost::system::error_code ec,
446cb13a392SEd Tanous                         const std::string&) {
44730215816SMarri Devender Rao             if (ec)
44830215816SMarri Devender Rao             {
449002d39b4SEd Tanous                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec.message();
45030215816SMarri Devender Rao                 messages::internalError(asyncResp->res);
45130215816SMarri Devender Rao                 return;
45230215816SMarri Devender Rao             }
45330215816SMarri Devender Rao             },
45430215816SMarri Devender Rao             service, objectPath, "xyz.openbmc_project.Certs.CSR.Create",
455002d39b4SEd Tanous             "GenerateCSR", *optAlternativeNames, *optChallengePassword, city,
456002d39b4SEd Tanous             commonName, *optContactPerson, country, *optEmail, *optGivenName,
457002d39b4SEd Tanous             *optInitials, *optKeyBitLength, *optKeyCurveId,
4580fda0f12SGeorge Liu             *optKeyPairAlgorithm, *optKeyUsage, organization,
4590fda0f12SGeorge Liu             organizationalUnit, state, *optSurname, *optUnstructuredName);
4607e860f15SJohn Edward Broadbent         });
4617e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionGenerateCSR
46230215816SMarri Devender Rao 
4635968caeeSMarri Devender Rao /**
4644e0453b1SGunnar Mills  * @brief Parse and update Certificate Issue/Subject property
4655968caeeSMarri Devender Rao  *
4665968caeeSMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
4675968caeeSMarri Devender Rao  * @param[in] str  Issuer/Subject value in key=value pairs
4685968caeeSMarri Devender Rao  * @param[in] type Issuer/Subject
4695968caeeSMarri Devender Rao  * @return None
4705968caeeSMarri Devender Rao  */
4715968caeeSMarri Devender Rao static void updateCertIssuerOrSubject(nlohmann::json& out,
4725968caeeSMarri Devender Rao                                       const std::string_view value)
4735968caeeSMarri Devender Rao {
4745968caeeSMarri Devender Rao     // example: O=openbmc-project.xyz,CN=localhost
4755968caeeSMarri Devender Rao     std::string_view::iterator i = value.begin();
4765968caeeSMarri Devender Rao     while (i != value.end())
4775968caeeSMarri Devender Rao     {
4785968caeeSMarri Devender Rao         std::string_view::iterator tokenBegin = i;
4795968caeeSMarri Devender Rao         while (i != value.end() && *i != '=')
4805968caeeSMarri Devender Rao         {
48117a897dfSManojkiran Eda             ++i;
4825968caeeSMarri Devender Rao         }
4835968caeeSMarri Devender Rao         if (i == value.end())
4845968caeeSMarri Devender Rao         {
4855968caeeSMarri Devender Rao             break;
4865968caeeSMarri Devender Rao         }
487271584abSEd Tanous         const std::string_view key(tokenBegin,
488271584abSEd Tanous                                    static_cast<size_t>(i - tokenBegin));
48917a897dfSManojkiran Eda         ++i;
4905968caeeSMarri Devender Rao         tokenBegin = i;
4915968caeeSMarri Devender Rao         while (i != value.end() && *i != ',')
4925968caeeSMarri Devender Rao         {
49317a897dfSManojkiran Eda             ++i;
4945968caeeSMarri Devender Rao         }
495271584abSEd Tanous         const std::string_view val(tokenBegin,
496271584abSEd Tanous                                    static_cast<size_t>(i - tokenBegin));
4975968caeeSMarri Devender Rao         if (key == "L")
4985968caeeSMarri Devender Rao         {
4995968caeeSMarri Devender Rao             out["City"] = val;
5005968caeeSMarri Devender Rao         }
5015968caeeSMarri Devender Rao         else if (key == "CN")
5025968caeeSMarri Devender Rao         {
5035968caeeSMarri Devender Rao             out["CommonName"] = val;
5045968caeeSMarri Devender Rao         }
5055968caeeSMarri Devender Rao         else if (key == "C")
5065968caeeSMarri Devender Rao         {
5075968caeeSMarri Devender Rao             out["Country"] = val;
5085968caeeSMarri Devender Rao         }
5095968caeeSMarri Devender Rao         else if (key == "O")
5105968caeeSMarri Devender Rao         {
5115968caeeSMarri Devender Rao             out["Organization"] = val;
5125968caeeSMarri Devender Rao         }
5135968caeeSMarri Devender Rao         else if (key == "OU")
5145968caeeSMarri Devender Rao         {
5155968caeeSMarri Devender Rao             out["OrganizationalUnit"] = val;
5165968caeeSMarri Devender Rao         }
5175968caeeSMarri Devender Rao         else if (key == "ST")
5185968caeeSMarri Devender Rao         {
5195968caeeSMarri Devender Rao             out["State"] = val;
5205968caeeSMarri Devender Rao         }
5215968caeeSMarri Devender Rao         // skip comma character
5225968caeeSMarri Devender Rao         if (i != value.end())
5235968caeeSMarri Devender Rao         {
52417a897dfSManojkiran Eda             ++i;
5255968caeeSMarri Devender Rao         }
5265968caeeSMarri Devender Rao     }
5275968caeeSMarri Devender Rao }
5285968caeeSMarri Devender Rao 
5295968caeeSMarri Devender Rao /**
530d3f92ce7SJiaqing Zhao  * @brief Retrieve the installed certificate list
531d3f92ce7SJiaqing Zhao  *
532d3f92ce7SJiaqing Zhao  * @param[in] asyncResp Shared pointer to the response message
533d3f92ce7SJiaqing Zhao  * @param[in] basePath DBus object path to search
534d3f92ce7SJiaqing Zhao  * @param[in] listPtr Json pointer to the list in asyncResp
535d3f92ce7SJiaqing Zhao  * @param[in] countPtr Json pointer to the count in asyncResp
536d3f92ce7SJiaqing Zhao  * @return None
537d3f92ce7SJiaqing Zhao  */
538d3f92ce7SJiaqing Zhao static void
539d3f92ce7SJiaqing Zhao     getCertificateList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
540d3f92ce7SJiaqing Zhao                        const std::string& basePath,
541d3f92ce7SJiaqing Zhao                        const nlohmann::json::json_pointer& listPtr,
542d3f92ce7SJiaqing Zhao                        const nlohmann::json::json_pointer& countPtr)
543d3f92ce7SJiaqing Zhao {
544d3f92ce7SJiaqing Zhao     crow::connections::systemBus->async_method_call(
545d3f92ce7SJiaqing Zhao         [asyncResp, listPtr, countPtr](
546d3f92ce7SJiaqing Zhao             const boost::system::error_code ec,
547d3f92ce7SJiaqing Zhao             const dbus::utility::MapperGetSubTreePathsResponse& certPaths) {
548d3f92ce7SJiaqing Zhao         if (ec)
549d3f92ce7SJiaqing Zhao         {
550d3f92ce7SJiaqing Zhao             BMCWEB_LOG_ERROR << "Certificate collection query failed: " << ec;
551d3f92ce7SJiaqing Zhao             messages::internalError(asyncResp->res);
552d3f92ce7SJiaqing Zhao             return;
553d3f92ce7SJiaqing Zhao         }
554d3f92ce7SJiaqing Zhao 
555d3f92ce7SJiaqing Zhao         nlohmann::json& links = asyncResp->res.jsonValue[listPtr];
556d3f92ce7SJiaqing Zhao         links = nlohmann::json::array();
557d3f92ce7SJiaqing Zhao         for (const auto& certPath : certPaths)
558d3f92ce7SJiaqing Zhao         {
559d3f92ce7SJiaqing Zhao             sdbusplus::message::object_path objPath(certPath);
560d3f92ce7SJiaqing Zhao             std::string certId = objPath.filename();
561d3f92ce7SJiaqing Zhao             if (certId.empty())
562d3f92ce7SJiaqing Zhao             {
563d3f92ce7SJiaqing Zhao                 BMCWEB_LOG_ERROR << "Invalid certificate objPath " << certPath;
564d3f92ce7SJiaqing Zhao                 continue;
565d3f92ce7SJiaqing Zhao             }
566d3f92ce7SJiaqing Zhao 
567d3f92ce7SJiaqing Zhao             boost::urls::url certURL;
568d3f92ce7SJiaqing Zhao             if (objPath.parent_path() == certs::httpsObjectPath)
569d3f92ce7SJiaqing Zhao             {
570d3f92ce7SJiaqing Zhao                 certURL = crow::utility::urlFromPieces(
571d3f92ce7SJiaqing Zhao                     "redfish", "v1", "Managers", "bmc", "NetworkProtocol",
572d3f92ce7SJiaqing Zhao                     "HTTPS", "Certificates", certId);
573d3f92ce7SJiaqing Zhao             }
574d3f92ce7SJiaqing Zhao             else if (objPath.parent_path() == certs::ldapObjectPath)
575d3f92ce7SJiaqing Zhao             {
576d3f92ce7SJiaqing Zhao                 certURL = crow::utility::urlFromPieces("redfish", "v1",
577d3f92ce7SJiaqing Zhao                                                        "AccountService", "LDAP",
578d3f92ce7SJiaqing Zhao                                                        "Certificates", certId);
579d3f92ce7SJiaqing Zhao             }
580d3f92ce7SJiaqing Zhao             else if (objPath.parent_path() == certs::authorityObjectPath)
581d3f92ce7SJiaqing Zhao             {
582d3f92ce7SJiaqing Zhao                 certURL = crow::utility::urlFromPieces(
583d3f92ce7SJiaqing Zhao                     "redfish", "v1", "Managers", "bmc", "Truststore",
584d3f92ce7SJiaqing Zhao                     "Certificates", certId);
585d3f92ce7SJiaqing Zhao             }
586d3f92ce7SJiaqing Zhao             else
587d3f92ce7SJiaqing Zhao             {
588d3f92ce7SJiaqing Zhao                 continue;
589d3f92ce7SJiaqing Zhao             }
590d3f92ce7SJiaqing Zhao 
591d3f92ce7SJiaqing Zhao             nlohmann::json::object_t link;
592d3f92ce7SJiaqing Zhao             link["@odata.id"] = certURL;
593d3f92ce7SJiaqing Zhao             links.emplace_back(std::move(link));
594d3f92ce7SJiaqing Zhao         }
595d3f92ce7SJiaqing Zhao 
596d3f92ce7SJiaqing Zhao         asyncResp->res.jsonValue[countPtr] = links.size();
597d3f92ce7SJiaqing Zhao         },
598d3f92ce7SJiaqing Zhao         "xyz.openbmc_project.ObjectMapper",
599d3f92ce7SJiaqing Zhao         "/xyz/openbmc_project/object_mapper",
600d3f92ce7SJiaqing Zhao         "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", basePath, 0,
601d3f92ce7SJiaqing Zhao         std::array<const char*, 1>{certs::certPropIntf});
602d3f92ce7SJiaqing Zhao }
603d3f92ce7SJiaqing Zhao 
604d3f92ce7SJiaqing Zhao /**
6055968caeeSMarri Devender Rao  * @brief Retrieve the certificates properties and append to the response
6065968caeeSMarri Devender Rao  * message
6075968caeeSMarri Devender Rao  *
6085968caeeSMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
6095968caeeSMarri Devender Rao  * @param[in] objectPath  Path of the D-Bus service object
6105968caeeSMarri Devender Rao  * @param[in] certId  Id of the certificate
6115968caeeSMarri Devender Rao  * @param[in] certURL  URL of the certificate object
6125968caeeSMarri Devender Rao  * @param[in] name  name of the certificate
6135968caeeSMarri Devender Rao  * @return None
6145968caeeSMarri Devender Rao  */
6155968caeeSMarri Devender Rao static void getCertificateProperties(
6168d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
617e19e97e2SJiaqing Zhao     const std::string& objectPath, const std::string& service,
618*1e312598SJiaqing Zhao     const std::string& certId, const boost::urls::url& certURL,
619e19e97e2SJiaqing Zhao     const std::string& name)
6205968caeeSMarri Devender Rao {
6215968caeeSMarri Devender Rao     BMCWEB_LOG_DEBUG << "getCertificateProperties Path=" << objectPath
6225968caeeSMarri Devender Rao                      << " certId=" << certId << " certURl=" << certURL;
6235968caeeSMarri Devender Rao     crow::connections::systemBus->async_method_call(
624b9d36b47SEd Tanous         [asyncResp, certURL, certId,
625b9d36b47SEd Tanous          name](const boost::system::error_code ec,
626b9d36b47SEd Tanous                const dbus::utility::DBusPropertiesMap& properties) {
6275968caeeSMarri Devender Rao         if (ec)
6285968caeeSMarri Devender Rao         {
6295968caeeSMarri Devender Rao             BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
630e19e97e2SJiaqing Zhao             messages::resourceNotFound(asyncResp->res, name, certId);
6315968caeeSMarri Devender Rao             return;
6325968caeeSMarri Devender Rao         }
6331476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] = certURL;
6341476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
6351476687dSEd Tanous             "#Certificate.v1_0_0.Certificate";
636e19e97e2SJiaqing Zhao         asyncResp->res.jsonValue["Id"] = certId;
6371476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = name;
6381476687dSEd Tanous         asyncResp->res.jsonValue["Description"] = name;
6395968caeeSMarri Devender Rao         for (const auto& property : properties)
6405968caeeSMarri Devender Rao         {
6415968caeeSMarri Devender Rao             if (property.first == "CertificateString")
6425968caeeSMarri Devender Rao             {
6435968caeeSMarri Devender Rao                 asyncResp->res.jsonValue["CertificateString"] = "";
6445968caeeSMarri Devender Rao                 const std::string* value =
6455968caeeSMarri Devender Rao                     std::get_if<std::string>(&property.second);
646e662eae8SEd Tanous                 if (value != nullptr)
6475968caeeSMarri Devender Rao                 {
64837cce918SMarri Devender Rao                     asyncResp->res.jsonValue["CertificateString"] = *value;
6495968caeeSMarri Devender Rao                 }
6505968caeeSMarri Devender Rao             }
6515968caeeSMarri Devender Rao             else if (property.first == "KeyUsage")
6525968caeeSMarri Devender Rao             {
653002d39b4SEd Tanous                 nlohmann::json& keyUsage = asyncResp->res.jsonValue["KeyUsage"];
6545968caeeSMarri Devender Rao                 keyUsage = nlohmann::json::array();
6555968caeeSMarri Devender Rao                 const std::vector<std::string>* value =
65637cce918SMarri Devender Rao                     std::get_if<std::vector<std::string>>(&property.second);
657e662eae8SEd Tanous                 if (value != nullptr)
6585968caeeSMarri Devender Rao                 {
6595968caeeSMarri Devender Rao                     for (const std::string& usage : *value)
6605968caeeSMarri Devender Rao                     {
6615968caeeSMarri Devender Rao                         keyUsage.push_back(usage);
6625968caeeSMarri Devender Rao                     }
6635968caeeSMarri Devender Rao                 }
6645968caeeSMarri Devender Rao             }
6655968caeeSMarri Devender Rao             else if (property.first == "Issuer")
6665968caeeSMarri Devender Rao             {
6675968caeeSMarri Devender Rao                 const std::string* value =
6685968caeeSMarri Devender Rao                     std::get_if<std::string>(&property.second);
669e662eae8SEd Tanous                 if (value != nullptr)
6705968caeeSMarri Devender Rao                 {
6715968caeeSMarri Devender Rao                     updateCertIssuerOrSubject(
6725968caeeSMarri Devender Rao                         asyncResp->res.jsonValue["Issuer"], *value);
6735968caeeSMarri Devender Rao                 }
6745968caeeSMarri Devender Rao             }
6755968caeeSMarri Devender Rao             else if (property.first == "Subject")
6765968caeeSMarri Devender Rao             {
6775968caeeSMarri Devender Rao                 const std::string* value =
6785968caeeSMarri Devender Rao                     std::get_if<std::string>(&property.second);
679e662eae8SEd Tanous                 if (value != nullptr)
6805968caeeSMarri Devender Rao                 {
6815968caeeSMarri Devender Rao                     updateCertIssuerOrSubject(
68237cce918SMarri Devender Rao                         asyncResp->res.jsonValue["Subject"], *value);
6835968caeeSMarri Devender Rao                 }
6845968caeeSMarri Devender Rao             }
6855968caeeSMarri Devender Rao             else if (property.first == "ValidNotAfter")
6865968caeeSMarri Devender Rao             {
687002d39b4SEd Tanous                 const uint64_t* value = std::get_if<uint64_t>(&property.second);
688e662eae8SEd Tanous                 if (value != nullptr)
6895968caeeSMarri Devender Rao                 {
6905968caeeSMarri Devender Rao                     asyncResp->res.jsonValue["ValidNotAfter"] =
6911d8782e7SNan Zhou                         crow::utility::getDateTimeUint(*value);
6925968caeeSMarri Devender Rao                 }
6935968caeeSMarri Devender Rao             }
6945968caeeSMarri Devender Rao             else if (property.first == "ValidNotBefore")
6955968caeeSMarri Devender Rao             {
696002d39b4SEd Tanous                 const uint64_t* value = std::get_if<uint64_t>(&property.second);
697e662eae8SEd Tanous                 if (value != nullptr)
6985968caeeSMarri Devender Rao                 {
6995968caeeSMarri Devender Rao                     asyncResp->res.jsonValue["ValidNotBefore"] =
7001d8782e7SNan Zhou                         crow::utility::getDateTimeUint(*value);
7015968caeeSMarri Devender Rao                 }
7025968caeeSMarri Devender Rao             }
7035968caeeSMarri Devender Rao         }
704*1e312598SJiaqing Zhao         asyncResp->res.addHeader(
705*1e312598SJiaqing Zhao             "Location", std::string_view(certURL.data(), certURL.size()));
7065968caeeSMarri Devender Rao         },
7075968caeeSMarri Devender Rao         service, objectPath, certs::dbusPropIntf, "GetAll",
7085968caeeSMarri Devender Rao         certs::certPropIntf);
7095968caeeSMarri Devender Rao }
7105968caeeSMarri Devender Rao 
7115968caeeSMarri Devender Rao /**
7125968caeeSMarri Devender Rao  * Action to replace an existing certificate
7135968caeeSMarri Devender Rao  */
7147e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionsReplaceCertificate(App& app)
7155968caeeSMarri Devender Rao {
7160fda0f12SGeorge Liu     BMCWEB_ROUTE(
7170fda0f12SGeorge Liu         app,
7180fda0f12SGeorge Liu         "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate/")
719ed398213SEd Tanous         .privileges(redfish::privileges::postCertificateService)
720002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
721002d39b4SEd Tanous             [&app](const crow::Request& req,
7227e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
7233ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
72445ca1b86SEd Tanous         {
72545ca1b86SEd Tanous             return;
72645ca1b86SEd Tanous         }
7275968caeeSMarri Devender Rao         std::string certificate;
7285968caeeSMarri Devender Rao         nlohmann::json certificateUri;
7295968caeeSMarri Devender Rao         std::optional<std::string> certificateType = "PEM";
7308d1b46d7Szhanghch05 
731002d39b4SEd Tanous         if (!json_util::readJsonAction(req, asyncResp->res, "CertificateString",
732002d39b4SEd Tanous                                        certificate, "CertificateUri",
733002d39b4SEd Tanous                                        certificateUri, "CertificateType",
734002d39b4SEd Tanous                                        certificateType))
7355968caeeSMarri Devender Rao         {
7365968caeeSMarri Devender Rao             BMCWEB_LOG_ERROR << "Required parameters are missing";
7375968caeeSMarri Devender Rao             messages::internalError(asyncResp->res);
7385968caeeSMarri Devender Rao             return;
7395968caeeSMarri Devender Rao         }
7405968caeeSMarri Devender Rao 
7415968caeeSMarri Devender Rao         if (!certificateType)
7425968caeeSMarri Devender Rao         {
7435968caeeSMarri Devender Rao             // should never happen, but it never hurts to be paranoid.
7445968caeeSMarri Devender Rao             return;
7455968caeeSMarri Devender Rao         }
7465968caeeSMarri Devender Rao         if (certificateType != "PEM")
7475968caeeSMarri Devender Rao         {
7485968caeeSMarri Devender Rao             messages::actionParameterNotSupported(
7495968caeeSMarri Devender Rao                 asyncResp->res, "CertificateType", "ReplaceCertificate");
7505968caeeSMarri Devender Rao             return;
7515968caeeSMarri Devender Rao         }
7525968caeeSMarri Devender Rao 
7535968caeeSMarri Devender Rao         std::string certURI;
7545968caeeSMarri Devender Rao         if (!redfish::json_util::readJson(certificateUri, asyncResp->res,
7555968caeeSMarri Devender Rao                                           "@odata.id", certURI))
7565968caeeSMarri Devender Rao         {
7575968caeeSMarri Devender Rao             messages::actionParameterMissing(
7585968caeeSMarri Devender Rao                 asyncResp->res, "ReplaceCertificate", "CertificateUri");
7595968caeeSMarri Devender Rao             return;
7605968caeeSMarri Devender Rao         }
76175b63a2cSJiaqing Zhao         BMCWEB_LOG_INFO << "Certificate URI to replace: " << certURI;
7625968caeeSMarri Devender Rao 
76375b63a2cSJiaqing Zhao         boost::urls::result<boost::urls::url_view> parsedUrl =
76475b63a2cSJiaqing Zhao             boost::urls::parse_relative_ref(certURI);
76575b63a2cSJiaqing Zhao         if (!parsedUrl)
7665968caeeSMarri Devender Rao         {
767002d39b4SEd Tanous             messages::actionParameterValueFormatError(asyncResp->res, certURI,
768002d39b4SEd Tanous                                                       "CertificateUri",
7695968caeeSMarri Devender Rao                                                       "ReplaceCertificate");
7705968caeeSMarri Devender Rao             return;
7715968caeeSMarri Devender Rao         }
77275b63a2cSJiaqing Zhao 
77375b63a2cSJiaqing Zhao         std::string id;
77475b63a2cSJiaqing Zhao         sdbusplus::message::object_path objectPath;
7755968caeeSMarri Devender Rao         std::string name;
77637cce918SMarri Devender Rao         std::string service;
77775b63a2cSJiaqing Zhao         if (crow::utility::readUrlSegments(
77875b63a2cSJiaqing Zhao                 *parsedUrl, "redfish", "v1", "Managers", "bmc",
77975b63a2cSJiaqing Zhao                 "NetworkProtocol", "HTTPS", "Certificates", std::ref(id)))
7805968caeeSMarri Devender Rao         {
781002d39b4SEd Tanous             objectPath =
78275b63a2cSJiaqing Zhao                 sdbusplus::message::object_path(certs::httpsObjectPath) / id;
7835968caeeSMarri Devender Rao             name = "HTTPS certificate";
78437cce918SMarri Devender Rao             service = certs::httpsServiceName;
78537cce918SMarri Devender Rao         }
78675b63a2cSJiaqing Zhao         else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1",
78775b63a2cSJiaqing Zhao                                                 "AccountService", "LDAP",
78875b63a2cSJiaqing Zhao                                                 "Certificates", std::ref(id)))
78937cce918SMarri Devender Rao         {
790002d39b4SEd Tanous             objectPath =
79175b63a2cSJiaqing Zhao                 sdbusplus::message::object_path(certs::ldapObjectPath) / id;
79237cce918SMarri Devender Rao             name = "LDAP certificate";
79337cce918SMarri Devender Rao             service = certs::ldapServiceName;
7945968caeeSMarri Devender Rao         }
79575b63a2cSJiaqing Zhao         else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1",
79675b63a2cSJiaqing Zhao                                                 "Managers", "bmc", "Truststore",
79775b63a2cSJiaqing Zhao                                                 "Certificates", std::ref(id)))
798cfcd5f6bSMarri Devender Rao         {
79975b63a2cSJiaqing Zhao             objectPath =
80075b63a2cSJiaqing Zhao                 sdbusplus::message::object_path(certs::authorityObjectPath) /
80175b63a2cSJiaqing Zhao                 id;
802cfcd5f6bSMarri Devender Rao             name = "TrustStore certificate";
803cfcd5f6bSMarri Devender Rao             service = certs::authorityServiceName;
804cfcd5f6bSMarri Devender Rao         }
8055968caeeSMarri Devender Rao         else
8065968caeeSMarri Devender Rao         {
8075968caeeSMarri Devender Rao             messages::actionParameterNotSupported(
8085968caeeSMarri Devender Rao                 asyncResp->res, "CertificateUri", "ReplaceCertificate");
8095968caeeSMarri Devender Rao             return;
8105968caeeSMarri Devender Rao         }
8115968caeeSMarri Devender Rao 
8125968caeeSMarri Devender Rao         std::shared_ptr<CertificateFile> certFile =
8135968caeeSMarri Devender Rao             std::make_shared<CertificateFile>(certificate);
8145968caeeSMarri Devender Rao         crow::connections::systemBus->async_method_call(
815*1e312598SJiaqing Zhao             [asyncResp, certFile, objectPath, service, url{*parsedUrl}, id,
8165968caeeSMarri Devender Rao              name](const boost::system::error_code ec) {
8175968caeeSMarri Devender Rao             if (ec)
8185968caeeSMarri Devender Rao             {
8195968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
82090d2d1e8SJiaqing Zhao                 if (ec.value() ==
82190d2d1e8SJiaqing Zhao                     boost::system::linux_error::bad_request_descriptor)
82290d2d1e8SJiaqing Zhao                 {
82375b63a2cSJiaqing Zhao                     messages::resourceNotFound(asyncResp->res, name, id);
8245968caeeSMarri Devender Rao                     return;
8255968caeeSMarri Devender Rao                 }
82690d2d1e8SJiaqing Zhao                 messages::internalError(asyncResp->res);
82790d2d1e8SJiaqing Zhao                 return;
82890d2d1e8SJiaqing Zhao             }
829*1e312598SJiaqing Zhao             getCertificateProperties(asyncResp, objectPath, service, id, url,
830*1e312598SJiaqing Zhao                                      name);
8315968caeeSMarri Devender Rao             BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
8325968caeeSMarri Devender Rao                              << certFile->getCertFilePath();
8335968caeeSMarri Devender Rao             },
8345968caeeSMarri Devender Rao             service, objectPath, certs::certReplaceIntf, "Replace",
8355968caeeSMarri Devender Rao             certFile->getCertFilePath());
8367e860f15SJohn Edward Broadbent         });
8377e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionsReplaceCertificate
8385968caeeSMarri Devender Rao 
8395968caeeSMarri Devender Rao /**
8405968caeeSMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
8415968caeeSMarri Devender Rao  * of a component, account or service.
8425968caeeSMarri Devender Rao  */
8435968caeeSMarri Devender Rao 
8447e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificate(App& app)
8455968caeeSMarri Devender Rao {
8467e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
8477e860f15SJohn Edward Broadbent         app,
8487e860f15SJohn Edward Broadbent         "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/<str>/")
849ed398213SEd Tanous         .privileges(redfish::privileges::getCertificate)
850*1e312598SJiaqing Zhao         .methods(boost::beast::http::verb::get)(
851*1e312598SJiaqing Zhao             [&app](const crow::Request& req,
8527e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
853717b9802SJiaqing Zhao                    const std::string& id) -> void {
8543ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
85545ca1b86SEd Tanous                 {
85645ca1b86SEd Tanous                     return;
85745ca1b86SEd Tanous                 }
8585968caeeSMarri Devender Rao 
859717b9802SJiaqing Zhao                 BMCWEB_LOG_DEBUG << "HTTPS Certificate ID=" << id;
860*1e312598SJiaqing Zhao                 const boost::urls::url certURL = crow::utility::urlFromPieces(
861*1e312598SJiaqing Zhao                     "redfish", "v1", "Managers", "bmc", "NetworkProtocol",
862*1e312598SJiaqing Zhao                     "HTTPS", "Certificates", id);
863717b9802SJiaqing Zhao                 std::string objPath =
864*1e312598SJiaqing Zhao                     sdbusplus::message::object_path(certs::httpsObjectPath) /
865*1e312598SJiaqing Zhao                     id;
866717b9802SJiaqing Zhao                 getCertificateProperties(asyncResp, objPath,
867717b9802SJiaqing Zhao                                          certs::httpsServiceName, id, certURL,
868717b9802SJiaqing Zhao                                          "HTTPS Certificate");
8697e860f15SJohn Edward Broadbent             });
8705968caeeSMarri Devender Rao }
8715968caeeSMarri Devender Rao 
8725968caeeSMarri Devender Rao /**
8735968caeeSMarri Devender Rao  * Collection of HTTPS certificates
8745968caeeSMarri Devender Rao  */
8757e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificateCollection(App& app)
8765968caeeSMarri Devender Rao {
8777e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
8785968caeeSMarri Devender Rao                  "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
879ed398213SEd Tanous         .privileges(redfish::privileges::getCertificateCollection)
880002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
881002d39b4SEd Tanous             [&app](const crow::Request& req,
882002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
8833ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
88445ca1b86SEd Tanous         {
88545ca1b86SEd Tanous             return;
88645ca1b86SEd Tanous         }
8871476687dSEd Tanous 
8881476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
8891476687dSEd Tanous             "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates";
8901476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
8911476687dSEd Tanous             "#CertificateCollection.CertificateCollection";
8921476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = "HTTPS Certificates Collection";
8931476687dSEd Tanous         asyncResp->res.jsonValue["Description"] =
8941476687dSEd Tanous             "A Collection of HTTPS certificate instances";
8958d1b46d7Szhanghch05 
896d3f92ce7SJiaqing Zhao         getCertificateList(asyncResp, certs::httpsObjectPath,
897d3f92ce7SJiaqing Zhao                            "/Members"_json_pointer,
898d3f92ce7SJiaqing Zhao                            "/Members@odata.count"_json_pointer);
8997e860f15SJohn Edward Broadbent         });
9005968caeeSMarri Devender Rao 
9017e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
9027e860f15SJohn Edward Broadbent                  "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
903ed398213SEd Tanous         .privileges(redfish::privileges::postCertificateCollection)
904002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
905002d39b4SEd Tanous             [&app](const crow::Request& req,
9067e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
9073ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
90845ca1b86SEd Tanous         {
90945ca1b86SEd Tanous             return;
91045ca1b86SEd Tanous         }
9115968caeeSMarri Devender Rao         BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost";
9128d1b46d7Szhanghch05 
9131476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = "HTTPS Certificate";
9141476687dSEd Tanous         asyncResp->res.jsonValue["Description"] = "HTTPS Certificate";
9155968caeeSMarri Devender Rao 
916002d39b4SEd Tanous         std::string certFileBody = getCertificateFromReqBody(asyncResp, req);
91758eb238fSKowalski, Kamil 
91858eb238fSKowalski, Kamil         if (certFileBody.empty())
91958eb238fSKowalski, Kamil         {
9200fda0f12SGeorge Liu             BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
921a08752f5SZbigniew Kurzynski             messages::unrecognizedRequestBody(asyncResp->res);
92258eb238fSKowalski, Kamil             return;
92358eb238fSKowalski, Kamil         }
92458eb238fSKowalski, Kamil 
9255968caeeSMarri Devender Rao         std::shared_ptr<CertificateFile> certFile =
92658eb238fSKowalski, Kamil             std::make_shared<CertificateFile>(certFileBody);
9275968caeeSMarri Devender Rao 
9285968caeeSMarri Devender Rao         crow::connections::systemBus->async_method_call(
929656ec7e3SZbigniew Kurzynski             [asyncResp, certFile](const boost::system::error_code ec,
930656ec7e3SZbigniew Kurzynski                                   const std::string& objectPath) {
9315968caeeSMarri Devender Rao             if (ec)
9325968caeeSMarri Devender Rao             {
9335968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
9345968caeeSMarri Devender Rao                 messages::internalError(asyncResp->res);
9355968caeeSMarri Devender Rao                 return;
9365968caeeSMarri Devender Rao             }
937717b9802SJiaqing Zhao 
938717b9802SJiaqing Zhao             sdbusplus::message::object_path path(objectPath);
939717b9802SJiaqing Zhao             std::string certId = path.filename();
940*1e312598SJiaqing Zhao             const boost::urls::url certURL = crow::utility::urlFromPieces(
941*1e312598SJiaqing Zhao                 "redfish", "v1", "Managers", "bmc", "NetworkProtocol", "HTTPS",
942*1e312598SJiaqing Zhao                 "Certificates", certId);
943717b9802SJiaqing Zhao             getCertificateProperties(asyncResp, objectPath,
944717b9802SJiaqing Zhao                                      certs::httpsServiceName, certId, certURL,
945717b9802SJiaqing Zhao                                      "HTTPS Certificate");
9465968caeeSMarri Devender Rao             BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
9475968caeeSMarri Devender Rao                              << certFile->getCertFilePath();
9485968caeeSMarri Devender Rao             },
94937cce918SMarri Devender Rao             certs::httpsServiceName, certs::httpsObjectPath,
9500fda0f12SGeorge Liu             certs::certInstallIntf, "Install", certFile->getCertFilePath());
9517e860f15SJohn Edward Broadbent         });
9527e860f15SJohn Edward Broadbent } // requestRoutesHTTPSCertificateCollection
9535968caeeSMarri Devender Rao 
9545968caeeSMarri Devender Rao /**
9557e860f15SJohn Edward Broadbent  * The certificate location schema defines a resource that an administrator
9567e860f15SJohn Edward Broadbent  * can use in order to locate all certificates installed on a given service.
9577e860f15SJohn Edward Broadbent  */
9587e860f15SJohn Edward Broadbent inline void requestRoutesCertificateLocations(App& app)
9597e860f15SJohn Edward Broadbent {
9607e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/")
961ed398213SEd Tanous         .privileges(redfish::privileges::getCertificateLocations)
962002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
963002d39b4SEd Tanous             [&app](const crow::Request& req,
964002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
9653ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
96645ca1b86SEd Tanous         {
96745ca1b86SEd Tanous             return;
96845ca1b86SEd Tanous         }
9691476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
9701476687dSEd Tanous             "/redfish/v1/CertificateService/CertificateLocations";
9711476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
9721476687dSEd Tanous             "#CertificateLocations.v1_0_0.CertificateLocations";
9731476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = "Certificate Locations";
9741476687dSEd Tanous         asyncResp->res.jsonValue["Id"] = "CertificateLocations";
9751476687dSEd Tanous         asyncResp->res.jsonValue["Description"] =
9767e860f15SJohn Edward Broadbent             "Defines a resource that an administrator can use in order to "
9771476687dSEd Tanous             "locate all certificates installed on a given service";
9787e860f15SJohn Edward Broadbent 
979d3f92ce7SJiaqing Zhao         getCertificateList(asyncResp, certs::baseObjectPath,
980d3f92ce7SJiaqing Zhao                            "/Links/Certificates"_json_pointer,
981d3f92ce7SJiaqing Zhao                            "/Links/Certificates@odata.count"_json_pointer);
9827e860f15SJohn Edward Broadbent         });
9837e860f15SJohn Edward Broadbent }
9847e860f15SJohn Edward Broadbent // requestRoutesCertificateLocations
98537cce918SMarri Devender Rao 
98637cce918SMarri Devender Rao /**
98737cce918SMarri Devender Rao  * Collection of LDAP certificates
98837cce918SMarri Devender Rao  */
9897e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificateCollection(App& app)
99037cce918SMarri Devender Rao {
9917e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
992ed398213SEd Tanous         .privileges(redfish::privileges::getCertificateCollection)
993002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
994002d39b4SEd Tanous             [&app](const crow::Request& req,
995002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
9963ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
99745ca1b86SEd Tanous         {
99845ca1b86SEd Tanous             return;
99945ca1b86SEd Tanous         }
10001476687dSEd Tanous 
10011476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
10021476687dSEd Tanous             "/redfish/v1/AccountService/LDAP/Certificates";
10031476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
10041476687dSEd Tanous             "#CertificateCollection.CertificateCollection";
10051476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = "LDAP Certificates Collection";
10061476687dSEd Tanous         asyncResp->res.jsonValue["Description"] =
10071476687dSEd Tanous             "A Collection of LDAP certificate instances";
10088d1b46d7Szhanghch05 
1009d3f92ce7SJiaqing Zhao         getCertificateList(asyncResp, certs::ldapObjectPath,
1010d3f92ce7SJiaqing Zhao                            "/Members"_json_pointer,
1011d3f92ce7SJiaqing Zhao                            "/Members@odata.count"_json_pointer);
10127e860f15SJohn Edward Broadbent         });
101337cce918SMarri Devender Rao 
10147e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
1015ed398213SEd Tanous         .privileges(redfish::privileges::postCertificateCollection)
10167e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
101745ca1b86SEd Tanous             [&app](const crow::Request& req,
10187e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
10193ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
102045ca1b86SEd Tanous         {
102145ca1b86SEd Tanous             return;
102245ca1b86SEd Tanous         }
1023002d39b4SEd Tanous         std::string certFileBody = getCertificateFromReqBody(asyncResp, req);
102458eb238fSKowalski, Kamil 
102558eb238fSKowalski, Kamil         if (certFileBody.empty())
102658eb238fSKowalski, Kamil         {
1027002d39b4SEd Tanous             BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
1028a08752f5SZbigniew Kurzynski             messages::unrecognizedRequestBody(asyncResp->res);
102958eb238fSKowalski, Kamil             return;
103058eb238fSKowalski, Kamil         }
103158eb238fSKowalski, Kamil 
103258eb238fSKowalski, Kamil         std::shared_ptr<CertificateFile> certFile =
103358eb238fSKowalski, Kamil             std::make_shared<CertificateFile>(certFileBody);
103458eb238fSKowalski, Kamil 
103537cce918SMarri Devender Rao         crow::connections::systemBus->async_method_call(
1036656ec7e3SZbigniew Kurzynski             [asyncResp, certFile](const boost::system::error_code ec,
1037656ec7e3SZbigniew Kurzynski                                   const std::string& objectPath) {
103837cce918SMarri Devender Rao             if (ec)
103937cce918SMarri Devender Rao             {
104037cce918SMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
104137cce918SMarri Devender Rao                 messages::internalError(asyncResp->res);
104237cce918SMarri Devender Rao                 return;
104337cce918SMarri Devender Rao             }
1044717b9802SJiaqing Zhao 
1045717b9802SJiaqing Zhao             sdbusplus::message::object_path path(objectPath);
1046717b9802SJiaqing Zhao             std::string certId = path.filename();
1047*1e312598SJiaqing Zhao             const boost::urls::url certURL =
1048*1e312598SJiaqing Zhao                 crow::utility::urlFromPieces("redfish", "v1", "AccountService",
1049*1e312598SJiaqing Zhao                                              "LDAP", "Certificates", certId);
1050717b9802SJiaqing Zhao             getCertificateProperties(asyncResp, objectPath,
1051717b9802SJiaqing Zhao                                      certs::ldapServiceName, certId, certURL,
1052717b9802SJiaqing Zhao                                      "LDAP Certificate");
105337cce918SMarri Devender Rao             BMCWEB_LOG_DEBUG << "LDAP certificate install file="
105437cce918SMarri Devender Rao                              << certFile->getCertFilePath();
105537cce918SMarri Devender Rao             },
105637cce918SMarri Devender Rao             certs::ldapServiceName, certs::ldapObjectPath,
1057002d39b4SEd Tanous             certs::certInstallIntf, "Install", certFile->getCertFilePath());
10587e860f15SJohn Edward Broadbent         });
10597e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificateCollection
106037cce918SMarri Devender Rao 
106137cce918SMarri Devender Rao /**
106237cce918SMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
106337cce918SMarri Devender Rao  * of a component, account or service.
106437cce918SMarri Devender Rao  */
10657e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificate(App& app)
106637cce918SMarri Devender Rao {
10677e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/")
1068ed398213SEd Tanous         .privileges(redfish::privileges::getCertificate)
10697e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
107045ca1b86SEd Tanous             [&app](const crow::Request& req,
10717e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1072717b9802SJiaqing Zhao                    const std::string& id) {
10733ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
107445ca1b86SEd Tanous         {
107545ca1b86SEd Tanous             return;
107645ca1b86SEd Tanous         }
1077717b9802SJiaqing Zhao 
1078717b9802SJiaqing Zhao         BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" << id;
1079*1e312598SJiaqing Zhao         const boost::urls::url certURL = crow::utility::urlFromPieces(
1080*1e312598SJiaqing Zhao             "redfish", "v1", "AccountService", "LDAP", "Certificates", id);
1081717b9802SJiaqing Zhao         std::string objPath =
1082717b9802SJiaqing Zhao             sdbusplus::message::object_path(certs::ldapObjectPath) / id;
1083717b9802SJiaqing Zhao         getCertificateProperties(asyncResp, objPath, certs::ldapServiceName, id,
1084717b9802SJiaqing Zhao                                  certURL, "LDAP Certificate");
10857e860f15SJohn Edward Broadbent         });
10867e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificate
1087cfcd5f6bSMarri Devender Rao /**
1088cfcd5f6bSMarri Devender Rao  * Collection of TrustStoreCertificate certificates
1089cfcd5f6bSMarri Devender Rao  */
10907e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificateCollection(App& app)
1091cfcd5f6bSMarri Devender Rao {
10927e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
1093ed398213SEd Tanous         .privileges(redfish::privileges::getCertificate)
1094002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
1095002d39b4SEd Tanous             [&app](const crow::Request& req,
1096002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
10973ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
109845ca1b86SEd Tanous         {
109945ca1b86SEd Tanous             return;
110045ca1b86SEd Tanous         }
11011476687dSEd Tanous 
11021476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
11031476687dSEd Tanous             "/redfish/v1/Managers/bmc/Truststore/Certificates/";
11041476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
11051476687dSEd Tanous             "#CertificateCollection.CertificateCollection";
1106002d39b4SEd Tanous         asyncResp->res.jsonValue["Name"] = "TrustStore Certificates Collection";
11071476687dSEd Tanous         asyncResp->res.jsonValue["Description"] =
11081476687dSEd Tanous             "A Collection of TrustStore certificate instances";
11098d1b46d7Szhanghch05 
1110d3f92ce7SJiaqing Zhao         getCertificateList(asyncResp, certs::authorityObjectPath,
1111d3f92ce7SJiaqing Zhao                            "/Members"_json_pointer,
1112d3f92ce7SJiaqing Zhao                            "/Members@odata.count"_json_pointer);
11137e860f15SJohn Edward Broadbent         });
1114cfcd5f6bSMarri Devender Rao 
11157e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
1116ed398213SEd Tanous         .privileges(redfish::privileges::postCertificateCollection)
1117002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
1118002d39b4SEd Tanous             [&app](const crow::Request& req,
11197e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
11203ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
112145ca1b86SEd Tanous         {
112245ca1b86SEd Tanous             return;
112345ca1b86SEd Tanous         }
1124002d39b4SEd Tanous         std::string certFileBody = getCertificateFromReqBody(asyncResp, req);
1125a08752f5SZbigniew Kurzynski 
1126a08752f5SZbigniew Kurzynski         if (certFileBody.empty())
1127a08752f5SZbigniew Kurzynski         {
11280fda0f12SGeorge Liu             BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
1129a08752f5SZbigniew Kurzynski             messages::unrecognizedRequestBody(asyncResp->res);
1130a08752f5SZbigniew Kurzynski             return;
1131a08752f5SZbigniew Kurzynski         }
1132a08752f5SZbigniew Kurzynski 
1133a08752f5SZbigniew Kurzynski         std::shared_ptr<CertificateFile> certFile =
1134a08752f5SZbigniew Kurzynski             std::make_shared<CertificateFile>(certFileBody);
1135cfcd5f6bSMarri Devender Rao         crow::connections::systemBus->async_method_call(
1136656ec7e3SZbigniew Kurzynski             [asyncResp, certFile](const boost::system::error_code ec,
1137656ec7e3SZbigniew Kurzynski                                   const std::string& objectPath) {
1138cfcd5f6bSMarri Devender Rao             if (ec)
1139cfcd5f6bSMarri Devender Rao             {
1140cfcd5f6bSMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
1141cfcd5f6bSMarri Devender Rao                 messages::internalError(asyncResp->res);
1142cfcd5f6bSMarri Devender Rao                 return;
1143cfcd5f6bSMarri Devender Rao             }
1144656ec7e3SZbigniew Kurzynski 
1145717b9802SJiaqing Zhao             sdbusplus::message::object_path path(objectPath);
1146717b9802SJiaqing Zhao             std::string certId = path.filename();
1147*1e312598SJiaqing Zhao             const boost::urls::url certURL = crow::utility::urlFromPieces(
1148*1e312598SJiaqing Zhao                 "redfish", "v1", "Managers", "bmc", "Truststore",
1149*1e312598SJiaqing Zhao                 "Certificates", certId);
1150717b9802SJiaqing Zhao             getCertificateProperties(asyncResp, objectPath,
1151717b9802SJiaqing Zhao                                      certs::authorityServiceName, certId,
1152717b9802SJiaqing Zhao                                      certURL, "TrustStore Certificate");
11530fda0f12SGeorge Liu             BMCWEB_LOG_DEBUG << "TrustStore certificate install file="
1154cfcd5f6bSMarri Devender Rao                              << certFile->getCertFilePath();
1155cfcd5f6bSMarri Devender Rao             },
1156cfcd5f6bSMarri Devender Rao             certs::authorityServiceName, certs::authorityObjectPath,
11570fda0f12SGeorge Liu             certs::certInstallIntf, "Install", certFile->getCertFilePath());
11587e860f15SJohn Edward Broadbent         });
11597e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificateCollection
1160cfcd5f6bSMarri Devender Rao 
1161cfcd5f6bSMarri Devender Rao /**
1162cfcd5f6bSMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
1163cfcd5f6bSMarri Devender Rao  * of a component, account or service.
1164cfcd5f6bSMarri Devender Rao  */
11657e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificate(App& app)
1166cfcd5f6bSMarri Devender Rao {
11677e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
1168ed398213SEd Tanous         .privileges(redfish::privileges::getCertificate)
11697e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
117045ca1b86SEd Tanous             [&app](const crow::Request& req,
11717e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1172717b9802SJiaqing Zhao                    const std::string& id) {
11733ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
117445ca1b86SEd Tanous         {
117545ca1b86SEd Tanous             return;
117645ca1b86SEd Tanous         }
1177717b9802SJiaqing Zhao 
1178717b9802SJiaqing Zhao         BMCWEB_LOG_DEBUG << "Truststore Certificate ID=" << id;
1179*1e312598SJiaqing Zhao         const boost::urls::url certURL =
1180*1e312598SJiaqing Zhao             crow::utility::urlFromPieces("redfish", "v1", "Managers", "bmc",
1181*1e312598SJiaqing Zhao                                          "Truststore", "Certificates", id);
1182717b9802SJiaqing Zhao         std::string objPath =
1183717b9802SJiaqing Zhao             sdbusplus::message::object_path(certs::authorityObjectPath) / id;
1184717b9802SJiaqing Zhao         getCertificateProperties(asyncResp, objPath,
1185717b9802SJiaqing Zhao                                  certs::authorityServiceName, id, certURL,
1186717b9802SJiaqing Zhao                                  "TrustStore Certificate");
11877e860f15SJohn Edward Broadbent         });
118807a60299SZbigniew Kurzynski 
11897e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
1190ed398213SEd Tanous         .privileges(redfish::privileges::deleteCertificate)
11917e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::delete_)(
119245ca1b86SEd Tanous             [&app](const crow::Request& req,
11937e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1194717b9802SJiaqing Zhao                    const std::string& id) {
11953ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
119645ca1b86SEd Tanous         {
119745ca1b86SEd Tanous             return;
119845ca1b86SEd Tanous         }
119907a60299SZbigniew Kurzynski 
1200717b9802SJiaqing Zhao         BMCWEB_LOG_DEBUG << "Delete TrustStore Certificate ID=" << id;
1201717b9802SJiaqing Zhao         std::string objPath =
1202717b9802SJiaqing Zhao             sdbusplus::message::object_path(certs::authorityObjectPath) / id;
120307a60299SZbigniew Kurzynski 
120407a60299SZbigniew Kurzynski         crow::connections::systemBus->async_method_call(
120507a60299SZbigniew Kurzynski             [asyncResp, id](const boost::system::error_code ec) {
120607a60299SZbigniew Kurzynski             if (ec)
120707a60299SZbigniew Kurzynski             {
120807a60299SZbigniew Kurzynski                 messages::resourceNotFound(asyncResp->res,
1209717b9802SJiaqing Zhao                                            "TrustStore Certificate", id);
121007a60299SZbigniew Kurzynski                 return;
121107a60299SZbigniew Kurzynski             }
121207a60299SZbigniew Kurzynski             BMCWEB_LOG_INFO << "Certificate deleted";
1213002d39b4SEd Tanous             asyncResp->res.result(boost::beast::http::status::no_content);
121407a60299SZbigniew Kurzynski             },
1215717b9802SJiaqing Zhao             certs::authorityServiceName, objPath, certs::objDeleteIntf,
121607a60299SZbigniew Kurzynski             "Delete");
12177e860f15SJohn Edward Broadbent         });
12187e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificate
12195968caeeSMarri Devender Rao } // namespace redfish
1220