xref: /openbmc/bmcweb/features/redfish/lib/certificate_service.hpp (revision d9f6c621036162e9071ce3c3a333b4544c6db870)
15968caeeSMarri Devender Rao #pragma once
25968caeeSMarri Devender Rao 
37e860f15SJohn Edward Broadbent #include <app.hpp>
4*d9f6c621SEd Tanous #include <async_resp.hpp>
590d2d1e8SJiaqing Zhao #include <boost/system/linux_error.hpp>
6168e20c1SEd Tanous #include <dbus_utility.hpp>
7*d9f6c621SEd Tanous #include <http_response.hpp>
845ca1b86SEd Tanous #include <query.hpp>
9ed398213SEd Tanous #include <registries/privilege_registry.hpp>
101214b7e7SGunnar Mills 
115968caeeSMarri Devender Rao namespace redfish
125968caeeSMarri Devender Rao {
135968caeeSMarri Devender Rao namespace certs
145968caeeSMarri Devender Rao {
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* httpsServiceName =
2237cce918SMarri Devender Rao     "xyz.openbmc_project.Certs.Manager.Server.Https";
2337cce918SMarri Devender Rao constexpr char const* ldapServiceName =
2437cce918SMarri Devender Rao     "xyz.openbmc_project.Certs.Manager.Client.Ldap";
25cfcd5f6bSMarri Devender Rao constexpr char const* authorityServiceName =
26cfcd5f6bSMarri Devender Rao     "xyz.openbmc_project.Certs.Manager.Authority.Ldap";
27c6a8dfb1SJiaqing Zhao constexpr char const* baseObjectPath = "/xyz/openbmc_project/certs";
28c6a8dfb1SJiaqing Zhao constexpr char const* httpsObjectPath =
29c6a8dfb1SJiaqing Zhao     "/xyz/openbmc_project/certs/server/https";
30c6a8dfb1SJiaqing Zhao constexpr char const* ldapObjectPath = "/xyz/openbmc_project/certs/client/ldap";
31cfcd5f6bSMarri Devender Rao constexpr char const* authorityObjectPath =
32cfcd5f6bSMarri Devender Rao     "/xyz/openbmc_project/certs/authority/ldap";
335968caeeSMarri Devender Rao } // namespace certs
345968caeeSMarri Devender Rao 
355968caeeSMarri Devender Rao /**
365968caeeSMarri Devender Rao  * The Certificate schema defines a Certificate Service which represents the
375968caeeSMarri Devender Rao  * actions available to manage certificates and links to where certificates
385968caeeSMarri Devender Rao  * are installed.
395968caeeSMarri Devender Rao  */
407e860f15SJohn Edward Broadbent 
415968caeeSMarri Devender Rao // TODO: Issue#61 No entries are available for Certificate
424e0453b1SGunnar Mills // service at https://www.dmtf.org/standards/redfish
435968caeeSMarri Devender Rao // "redfish standard registries". Need to modify after DMTF
445968caeeSMarri Devender Rao // publish Privilege details for certificate service
455968caeeSMarri Devender Rao 
467e860f15SJohn Edward Broadbent inline void requestRoutesCertificateService(App& app)
475968caeeSMarri Devender Rao {
487e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/")
49ed398213SEd Tanous         .privileges(redfish::privileges::getCertificateService)
50002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
51002d39b4SEd Tanous             [&app](const crow::Request& req,
52002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
533ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
5445ca1b86SEd Tanous         {
5545ca1b86SEd Tanous             return;
5645ca1b86SEd Tanous         }
571476687dSEd Tanous 
581476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
591476687dSEd Tanous             "#CertificateService.v1_0_0.CertificateService";
601476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
611476687dSEd Tanous             "/redfish/v1/CertificateService";
621476687dSEd Tanous         asyncResp->res.jsonValue["Id"] = "CertificateService";
631476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = "Certificate Service";
641476687dSEd Tanous         asyncResp->res.jsonValue["Description"] =
651476687dSEd Tanous             "Actions available to manage certificates";
6672048780SAbhishek Patel         // /redfish/v1/CertificateService/CertificateLocations is something
6772048780SAbhishek Patel         // only ConfigureManager can access then only display when the user
6872048780SAbhishek Patel         // has permissions ConfigureManager
6972048780SAbhishek Patel         Privileges effectiveUserPrivileges =
7072048780SAbhishek Patel             redfish::getUserPrivileges(req.userRole);
7172048780SAbhishek Patel         if (isOperationAllowedWithPrivileges({{"ConfigureManager"}},
7272048780SAbhishek Patel                                              effectiveUserPrivileges))
7372048780SAbhishek Patel         {
741476687dSEd Tanous             asyncResp->res.jsonValue["CertificateLocations"]["@odata.id"] =
751476687dSEd Tanous                 "/redfish/v1/CertificateService/CertificateLocations";
7672048780SAbhishek Patel         }
770fda0f12SGeorge Liu         asyncResp->res
78002d39b4SEd Tanous             .jsonValue["Actions"]["#CertificateService.ReplaceCertificate"] = {
790fda0f12SGeorge Liu             {"target",
800fda0f12SGeorge Liu              "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate"},
815968caeeSMarri Devender Rao             {"CertificateType@Redfish.AllowableValues", {"PEM"}}};
827e860f15SJohn Edward Broadbent         asyncResp->res
837e860f15SJohn Edward Broadbent             .jsonValue["Actions"]["#CertificateService.GenerateCSR"] = {
840fda0f12SGeorge Liu             {"target",
850fda0f12SGeorge Liu              "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR"}};
867e860f15SJohn Edward Broadbent         });
877e860f15SJohn Edward Broadbent } // requestRoutesCertificateService
8837cce918SMarri Devender Rao 
898d1b46d7Szhanghch05 inline std::string getCertificateFromReqBody(
908d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
9158eb238fSKowalski, Kamil     const crow::Request& req)
9258eb238fSKowalski, Kamil {
9358eb238fSKowalski, Kamil     nlohmann::json reqJson = nlohmann::json::parse(req.body, nullptr, false);
9458eb238fSKowalski, Kamil 
9558eb238fSKowalski, Kamil     if (reqJson.is_discarded())
9658eb238fSKowalski, Kamil     {
9758eb238fSKowalski, Kamil         // We did not receive JSON request, proceed as it is RAW data
9858eb238fSKowalski, Kamil         return req.body;
9958eb238fSKowalski, Kamil     }
10058eb238fSKowalski, Kamil 
10158eb238fSKowalski, Kamil     std::string certificate;
10258eb238fSKowalski, Kamil     std::optional<std::string> certificateType = "PEM";
10358eb238fSKowalski, Kamil 
10415ed6780SWilly Tu     if (!json_util::readJsonPatch(req, asyncResp->res, "CertificateString",
10515ed6780SWilly Tu                                   certificate, "CertificateType",
10615ed6780SWilly Tu                                   certificateType))
10758eb238fSKowalski, Kamil     {
10858eb238fSKowalski, Kamil         BMCWEB_LOG_ERROR << "Required parameters are missing";
10958eb238fSKowalski, Kamil         messages::internalError(asyncResp->res);
110abb93cddSEd Tanous         return {};
11158eb238fSKowalski, Kamil     }
11258eb238fSKowalski, Kamil 
11358eb238fSKowalski, Kamil     if (*certificateType != "PEM")
11458eb238fSKowalski, Kamil     {
11558eb238fSKowalski, Kamil         messages::propertyValueNotInList(asyncResp->res, *certificateType,
11658eb238fSKowalski, Kamil                                          "CertificateType");
117abb93cddSEd Tanous         return {};
11858eb238fSKowalski, Kamil     }
11958eb238fSKowalski, Kamil 
12058eb238fSKowalski, Kamil     return certificate;
12158eb238fSKowalski, Kamil }
12258eb238fSKowalski, Kamil 
1235968caeeSMarri Devender Rao /**
1245968caeeSMarri Devender Rao  * Class to create a temporary certificate file for uploading to system
1255968caeeSMarri Devender Rao  */
1265968caeeSMarri Devender Rao class CertificateFile
1275968caeeSMarri Devender Rao {
1285968caeeSMarri Devender Rao   public:
1295968caeeSMarri Devender Rao     CertificateFile() = delete;
1305968caeeSMarri Devender Rao     CertificateFile(const CertificateFile&) = delete;
1315968caeeSMarri Devender Rao     CertificateFile& operator=(const CertificateFile&) = delete;
1325968caeeSMarri Devender Rao     CertificateFile(CertificateFile&&) = delete;
1335968caeeSMarri Devender Rao     CertificateFile& operator=(CertificateFile&&) = delete;
1344e23a444SEd Tanous     explicit CertificateFile(const std::string& certString)
1355968caeeSMarri Devender Rao     {
13672d52d25SEd Tanous         std::array<char, 18> dirTemplate = {'/', 't', 'm', 'p', '/', 'C',
1375207438cSEd Tanous                                             'e', 'r', 't', 's', '.', 'X',
1385207438cSEd Tanous                                             'X', 'X', 'X', 'X', 'X', '\0'};
1395207438cSEd Tanous         char* tempDirectory = mkdtemp(dirTemplate.data());
140e662eae8SEd Tanous         if (tempDirectory != nullptr)
1415968caeeSMarri Devender Rao         {
1425968caeeSMarri Devender Rao             certDirectory = tempDirectory;
1435968caeeSMarri Devender Rao             certificateFile = certDirectory / "cert.pem";
1445968caeeSMarri Devender Rao             std::ofstream out(certificateFile, std::ofstream::out |
1455968caeeSMarri Devender Rao                                                    std::ofstream::binary |
1465968caeeSMarri Devender Rao                                                    std::ofstream::trunc);
1475968caeeSMarri Devender Rao             out << certString;
1485968caeeSMarri Devender Rao             out.close();
1498cc8edecSEd Tanous             BMCWEB_LOG_DEBUG << "Creating certificate file"
1508cc8edecSEd Tanous                              << certificateFile.string();
1515968caeeSMarri Devender Rao         }
1525968caeeSMarri Devender Rao     }
1535968caeeSMarri Devender Rao     ~CertificateFile()
1545968caeeSMarri Devender Rao     {
1555968caeeSMarri Devender Rao         if (std::filesystem::exists(certDirectory))
1565968caeeSMarri Devender Rao         {
1578cc8edecSEd Tanous             BMCWEB_LOG_DEBUG << "Removing certificate file"
1588cc8edecSEd Tanous                              << certificateFile.string();
15923a21a1cSEd Tanous             std::error_code ec;
16023a21a1cSEd Tanous             std::filesystem::remove_all(certDirectory, ec);
16123a21a1cSEd Tanous             if (ec)
1625968caeeSMarri Devender Rao             {
1635968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "Failed to remove temp directory"
1648cc8edecSEd Tanous                                  << certDirectory.string();
1655968caeeSMarri Devender Rao             }
1665968caeeSMarri Devender Rao         }
1675968caeeSMarri Devender Rao     }
1685968caeeSMarri Devender Rao     std::string getCertFilePath()
1695968caeeSMarri Devender Rao     {
1705968caeeSMarri Devender Rao         return certificateFile;
1715968caeeSMarri Devender Rao     }
1725968caeeSMarri Devender Rao 
1735968caeeSMarri Devender Rao   private:
1745968caeeSMarri Devender Rao     std::filesystem::path certificateFile;
1755968caeeSMarri Devender Rao     std::filesystem::path certDirectory;
1765968caeeSMarri Devender Rao };
1775968caeeSMarri Devender Rao 
17859d494eeSPatrick Williams static std::unique_ptr<sdbusplus::bus::match_t> csrMatcher;
17930215816SMarri Devender Rao /**
18030215816SMarri Devender Rao  * @brief Read data from CSR D-bus object and set to response
18130215816SMarri Devender Rao  *
18230215816SMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
18330215816SMarri Devender Rao  * @param[in] certURI Link to certifiate collection URI
18430215816SMarri Devender Rao  * @param[in] service D-Bus service name
18530215816SMarri Devender Rao  * @param[in] certObjPath certificate D-Bus object path
18630215816SMarri Devender Rao  * @param[in] csrObjPath CSR D-Bus object path
18730215816SMarri Devender Rao  * @return None
18830215816SMarri Devender Rao  */
1898d1b46d7Szhanghch05 static void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
19030215816SMarri Devender Rao                    const std::string& certURI, const std::string& service,
19130215816SMarri Devender Rao                    const std::string& certObjPath,
19230215816SMarri Devender Rao                    const std::string& csrObjPath)
19330215816SMarri Devender Rao {
19430215816SMarri Devender Rao     BMCWEB_LOG_DEBUG << "getCSR CertObjectPath" << certObjPath
19530215816SMarri Devender Rao                      << " CSRObjectPath=" << csrObjPath
19630215816SMarri Devender Rao                      << " service=" << service;
19730215816SMarri Devender Rao     crow::connections::systemBus->async_method_call(
19830215816SMarri Devender Rao         [asyncResp, certURI](const boost::system::error_code ec,
19930215816SMarri Devender Rao                              const std::string& csr) {
20030215816SMarri Devender Rao         if (ec)
20130215816SMarri Devender Rao         {
20230215816SMarri Devender Rao             BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
20330215816SMarri Devender Rao             messages::internalError(asyncResp->res);
20430215816SMarri Devender Rao             return;
20530215816SMarri Devender Rao         }
20630215816SMarri Devender Rao         if (csr.empty())
20730215816SMarri Devender Rao         {
20830215816SMarri Devender Rao             BMCWEB_LOG_ERROR << "CSR read is empty";
20930215816SMarri Devender Rao             messages::internalError(asyncResp->res);
21030215816SMarri Devender Rao             return;
21130215816SMarri Devender Rao         }
21230215816SMarri Devender Rao         asyncResp->res.jsonValue["CSRString"] = csr;
2131476687dSEd Tanous         asyncResp->res.jsonValue["CertificateCollection"]["@odata.id"] =
2141476687dSEd Tanous             certURI;
21530215816SMarri Devender Rao         },
21630215816SMarri Devender Rao         service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR");
21730215816SMarri Devender Rao }
21830215816SMarri Devender Rao 
21930215816SMarri Devender Rao /**
22030215816SMarri Devender Rao  * Action to Generate CSR
22130215816SMarri Devender Rao  */
2227e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionGenerateCSR(App& app)
22330215816SMarri Devender Rao {
2240fda0f12SGeorge Liu     BMCWEB_ROUTE(
2250fda0f12SGeorge Liu         app,
2260fda0f12SGeorge Liu         "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR/")
2275344ab8eSAbhishek Patel         .privileges(redfish::privileges::postCertificateService)
228002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
229002d39b4SEd Tanous             [&app](const crow::Request& req,
2307e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2313ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
23245ca1b86SEd Tanous         {
23345ca1b86SEd Tanous             return;
23445ca1b86SEd Tanous         }
2352c70f800SEd Tanous         static const int rsaKeyBitLength = 2048;
2368d1b46d7Szhanghch05 
23730215816SMarri Devender Rao         // Required parameters
23830215816SMarri Devender Rao         std::string city;
23930215816SMarri Devender Rao         std::string commonName;
24030215816SMarri Devender Rao         std::string country;
24130215816SMarri Devender Rao         std::string organization;
24230215816SMarri Devender Rao         std::string organizationalUnit;
24330215816SMarri Devender Rao         std::string state;
24430215816SMarri Devender Rao         nlohmann::json certificateCollection;
24530215816SMarri Devender Rao 
24630215816SMarri Devender Rao         // Optional parameters
24730215816SMarri Devender Rao         std::optional<std::vector<std::string>> optAlternativeNames =
24830215816SMarri Devender Rao             std::vector<std::string>();
24930215816SMarri Devender Rao         std::optional<std::string> optContactPerson = "";
25030215816SMarri Devender Rao         std::optional<std::string> optChallengePassword = "";
25130215816SMarri Devender Rao         std::optional<std::string> optEmail = "";
25230215816SMarri Devender Rao         std::optional<std::string> optGivenName = "";
25330215816SMarri Devender Rao         std::optional<std::string> optInitials = "";
2542c70f800SEd Tanous         std::optional<int64_t> optKeyBitLength = rsaKeyBitLength;
255aaf3206fSVernon Mauery         std::optional<std::string> optKeyCurveId = "secp384r1";
25630215816SMarri Devender Rao         std::optional<std::string> optKeyPairAlgorithm = "EC";
25730215816SMarri Devender Rao         std::optional<std::vector<std::string>> optKeyUsage =
25830215816SMarri Devender Rao             std::vector<std::string>();
25930215816SMarri Devender Rao         std::optional<std::string> optSurname = "";
26030215816SMarri Devender Rao         std::optional<std::string> optUnstructuredName = "";
26115ed6780SWilly Tu         if (!json_util::readJsonAction(
2620fda0f12SGeorge Liu                 req, asyncResp->res, "City", city, "CommonName", commonName,
2630fda0f12SGeorge Liu                 "ContactPerson", optContactPerson, "Country", country,
2640fda0f12SGeorge Liu                 "Organization", organization, "OrganizationalUnit",
2650fda0f12SGeorge Liu                 organizationalUnit, "State", state, "CertificateCollection",
266002d39b4SEd Tanous                 certificateCollection, "AlternativeNames", optAlternativeNames,
267002d39b4SEd Tanous                 "ChallengePassword", optChallengePassword, "Email", optEmail,
268002d39b4SEd Tanous                 "GivenName", optGivenName, "Initials", optInitials,
269002d39b4SEd Tanous                 "KeyBitLength", optKeyBitLength, "KeyCurveId", optKeyCurveId,
2700fda0f12SGeorge Liu                 "KeyPairAlgorithm", optKeyPairAlgorithm, "KeyUsage",
2710fda0f12SGeorge Liu                 optKeyUsage, "Surname", optSurname, "UnstructuredName",
2720fda0f12SGeorge Liu                 optUnstructuredName))
27330215816SMarri Devender Rao         {
27430215816SMarri Devender Rao             return;
27530215816SMarri Devender Rao         }
27630215816SMarri Devender Rao 
27730215816SMarri Devender Rao         // bmcweb has no way to store or decode a private key challenge
2787e860f15SJohn Edward Broadbent         // password, which will likely cause bmcweb to crash on startup
2797e860f15SJohn Edward Broadbent         // if this is not set on a post so not allowing the user to set
2807e860f15SJohn Edward Broadbent         // value
28126f6976fSEd Tanous         if (!optChallengePassword->empty())
28230215816SMarri Devender Rao         {
283002d39b4SEd Tanous             messages::actionParameterNotSupported(asyncResp->res, "GenerateCSR",
284002d39b4SEd Tanous                                                   "ChallengePassword");
28530215816SMarri Devender Rao             return;
28630215816SMarri Devender Rao         }
28730215816SMarri Devender Rao 
28830215816SMarri Devender Rao         std::string certURI;
289002d39b4SEd Tanous         if (!redfish::json_util::readJson(certificateCollection, asyncResp->res,
290002d39b4SEd Tanous                                           "@odata.id", certURI))
29130215816SMarri Devender Rao         {
29230215816SMarri Devender Rao             return;
29330215816SMarri Devender Rao         }
29430215816SMarri Devender Rao 
29530215816SMarri Devender Rao         std::string objectPath;
29630215816SMarri Devender Rao         std::string service;
29711ba3979SEd Tanous         if (certURI.starts_with(
2980fda0f12SGeorge Liu                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"))
29930215816SMarri Devender Rao         {
30030215816SMarri Devender Rao             objectPath = certs::httpsObjectPath;
30130215816SMarri Devender Rao             service = certs::httpsServiceName;
30230215816SMarri Devender Rao         }
30311ba3979SEd Tanous         else if (certURI.starts_with(
30411ba3979SEd Tanous                      "/redfish/v1/AccountService/LDAP/Certificates"))
3053b7f0149SMarri Devender Rao         {
3063b7f0149SMarri Devender Rao             objectPath = certs::ldapObjectPath;
3073b7f0149SMarri Devender Rao             service = certs::ldapServiceName;
3083b7f0149SMarri Devender Rao         }
30930215816SMarri Devender Rao         else
31030215816SMarri Devender Rao         {
31130215816SMarri Devender Rao             messages::actionParameterNotSupported(
31230215816SMarri Devender Rao                 asyncResp->res, "CertificateCollection", "GenerateCSR");
31330215816SMarri Devender Rao             return;
31430215816SMarri Devender Rao         }
31530215816SMarri Devender Rao 
31630215816SMarri Devender Rao         // supporting only EC and RSA algorithm
3170fda0f12SGeorge Liu         if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA")
31830215816SMarri Devender Rao         {
31930215816SMarri Devender Rao             messages::actionParameterNotSupported(
32030215816SMarri Devender Rao                 asyncResp->res, "KeyPairAlgorithm", "GenerateCSR");
32130215816SMarri Devender Rao             return;
32230215816SMarri Devender Rao         }
32330215816SMarri Devender Rao 
3247e860f15SJohn Edward Broadbent         // supporting only 2048 key bit length for RSA algorithm due to
3257e860f15SJohn Edward Broadbent         // time consumed in generating private key
32630215816SMarri Devender Rao         if (*optKeyPairAlgorithm == "RSA" &&
3272c70f800SEd Tanous             *optKeyBitLength != rsaKeyBitLength)
32830215816SMarri Devender Rao         {
329002d39b4SEd Tanous             messages::propertyValueNotInList(asyncResp->res,
330002d39b4SEd Tanous                                              std::to_string(*optKeyBitLength),
33130215816SMarri Devender Rao                                              "KeyBitLength");
33230215816SMarri Devender Rao             return;
33330215816SMarri Devender Rao         }
33430215816SMarri Devender Rao 
33530215816SMarri Devender Rao         // validate KeyUsage supporting only 1 type based on URL
33611ba3979SEd Tanous         if (certURI.starts_with(
3370fda0f12SGeorge Liu                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"))
33830215816SMarri Devender Rao         {
33926f6976fSEd Tanous             if (optKeyUsage->empty())
34030215816SMarri Devender Rao             {
34130215816SMarri Devender Rao                 optKeyUsage->push_back("ServerAuthentication");
34230215816SMarri Devender Rao             }
34330215816SMarri Devender Rao             else if (optKeyUsage->size() == 1)
34430215816SMarri Devender Rao             {
34530215816SMarri Devender Rao                 if ((*optKeyUsage)[0] != "ServerAuthentication")
34630215816SMarri Devender Rao                 {
34730215816SMarri Devender Rao                     messages::propertyValueNotInList(
34830215816SMarri Devender Rao                         asyncResp->res, (*optKeyUsage)[0], "KeyUsage");
34930215816SMarri Devender Rao                     return;
35030215816SMarri Devender Rao                 }
35130215816SMarri Devender Rao             }
35230215816SMarri Devender Rao             else
35330215816SMarri Devender Rao             {
35430215816SMarri Devender Rao                 messages::actionParameterNotSupported(
35530215816SMarri Devender Rao                     asyncResp->res, "KeyUsage", "GenerateCSR");
35630215816SMarri Devender Rao                 return;
35730215816SMarri Devender Rao             }
35830215816SMarri Devender Rao         }
35911ba3979SEd Tanous         else if (certURI.starts_with(
36011ba3979SEd Tanous                      "/redfish/v1/AccountService/LDAP/Certificates"))
3613b7f0149SMarri Devender Rao         {
36226f6976fSEd Tanous             if (optKeyUsage->empty())
3633b7f0149SMarri Devender Rao             {
3643b7f0149SMarri Devender Rao                 optKeyUsage->push_back("ClientAuthentication");
3653b7f0149SMarri Devender Rao             }
3663b7f0149SMarri Devender Rao             else if (optKeyUsage->size() == 1)
3673b7f0149SMarri Devender Rao             {
3683b7f0149SMarri Devender Rao                 if ((*optKeyUsage)[0] != "ClientAuthentication")
3693b7f0149SMarri Devender Rao                 {
3703b7f0149SMarri Devender Rao                     messages::propertyValueNotInList(
3713b7f0149SMarri Devender Rao                         asyncResp->res, (*optKeyUsage)[0], "KeyUsage");
3723b7f0149SMarri Devender Rao                     return;
3733b7f0149SMarri Devender Rao                 }
3743b7f0149SMarri Devender Rao             }
3753b7f0149SMarri Devender Rao             else
3763b7f0149SMarri Devender Rao             {
3773b7f0149SMarri Devender Rao                 messages::actionParameterNotSupported(
3783b7f0149SMarri Devender Rao                     asyncResp->res, "KeyUsage", "GenerateCSR");
3793b7f0149SMarri Devender Rao                 return;
3803b7f0149SMarri Devender Rao             }
3813b7f0149SMarri Devender Rao         }
38230215816SMarri Devender Rao 
3837e860f15SJohn Edward Broadbent         // Only allow one CSR matcher at a time so setting retry
3847e860f15SJohn Edward Broadbent         // time-out and timer expiry to 10 seconds for now.
3852c70f800SEd Tanous         static const int timeOut = 10;
38630215816SMarri Devender Rao         if (csrMatcher)
38730215816SMarri Devender Rao         {
388002d39b4SEd Tanous             messages::serviceTemporarilyUnavailable(asyncResp->res,
389002d39b4SEd Tanous                                                     std::to_string(timeOut));
39030215816SMarri Devender Rao             return;
39130215816SMarri Devender Rao         }
39230215816SMarri Devender Rao 
39330215816SMarri Devender Rao         // Make this static so it survives outside this method
39430215816SMarri Devender Rao         static boost::asio::steady_timer timeout(*req.ioService);
3952c70f800SEd Tanous         timeout.expires_after(std::chrono::seconds(timeOut));
396002d39b4SEd Tanous         timeout.async_wait([asyncResp](const boost::system::error_code& ec) {
39730215816SMarri Devender Rao             csrMatcher = nullptr;
39830215816SMarri Devender Rao             if (ec)
39930215816SMarri Devender Rao             {
4007e860f15SJohn Edward Broadbent                 // operation_aborted is expected if timer is canceled
4017e860f15SJohn Edward Broadbent                 // before completion.
40230215816SMarri Devender Rao                 if (ec != boost::asio::error::operation_aborted)
40330215816SMarri Devender Rao                 {
40430215816SMarri Devender Rao                     BMCWEB_LOG_ERROR << "Async_wait failed " << ec;
40530215816SMarri Devender Rao                 }
40630215816SMarri Devender Rao                 return;
40730215816SMarri Devender Rao             }
40830215816SMarri Devender Rao             BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR";
40930215816SMarri Devender Rao             messages::internalError(asyncResp->res);
41030215816SMarri Devender Rao         });
41130215816SMarri Devender Rao 
41230215816SMarri Devender Rao         // create a matcher to wait on CSR object
41330215816SMarri Devender Rao         BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath;
4140fda0f12SGeorge Liu         std::string match("type='signal',"
41530215816SMarri Devender Rao                           "interface='org.freedesktop.DBus.ObjectManager',"
41630215816SMarri Devender Rao                           "path='" +
41730215816SMarri Devender Rao                           objectPath +
41830215816SMarri Devender Rao                           "',"
41930215816SMarri Devender Rao                           "member='InterfacesAdded'");
42059d494eeSPatrick Williams         csrMatcher = std::make_unique<sdbusplus::bus::match_t>(
42130215816SMarri Devender Rao             *crow::connections::systemBus, match,
42259d494eeSPatrick Williams             [asyncResp, service, objectPath, certURI](sdbusplus::message_t& m) {
423271584abSEd Tanous             timeout.cancel();
42430215816SMarri Devender Rao             if (m.is_method_error())
42530215816SMarri Devender Rao             {
42630215816SMarri Devender Rao                 BMCWEB_LOG_ERROR << "Dbus method error!!!";
42730215816SMarri Devender Rao                 messages::internalError(asyncResp->res);
42830215816SMarri Devender Rao                 return;
42930215816SMarri Devender Rao             }
430b9d36b47SEd Tanous 
431b9d36b47SEd Tanous             dbus::utility::DBusInteracesMap interfacesProperties;
432b9d36b47SEd Tanous 
43330215816SMarri Devender Rao             sdbusplus::message::object_path csrObjectPath;
43430215816SMarri Devender Rao             m.read(csrObjectPath, interfacesProperties);
4350fda0f12SGeorge Liu             BMCWEB_LOG_DEBUG << "CSR object added" << csrObjectPath.str;
43602cad96eSEd Tanous             for (const auto& interface : interfacesProperties)
43730215816SMarri Devender Rao             {
4380fda0f12SGeorge Liu                 if (interface.first == "xyz.openbmc_project.Certs.CSR")
43930215816SMarri Devender Rao                 {
44030215816SMarri Devender Rao                     getCSR(asyncResp, certURI, service, objectPath,
44130215816SMarri Devender Rao                            csrObjectPath.str);
44230215816SMarri Devender Rao                     break;
44330215816SMarri Devender Rao                 }
44430215816SMarri Devender Rao             }
44530215816SMarri Devender Rao             });
44630215816SMarri Devender Rao         crow::connections::systemBus->async_method_call(
447914e2d5dSEd Tanous             [asyncResp](const boost::system::error_code ec,
448cb13a392SEd Tanous                         const std::string&) {
44930215816SMarri Devender Rao             if (ec)
45030215816SMarri Devender Rao             {
451002d39b4SEd Tanous                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec.message();
45230215816SMarri Devender Rao                 messages::internalError(asyncResp->res);
45330215816SMarri Devender Rao                 return;
45430215816SMarri Devender Rao             }
45530215816SMarri Devender Rao             },
45630215816SMarri Devender Rao             service, objectPath, "xyz.openbmc_project.Certs.CSR.Create",
457002d39b4SEd Tanous             "GenerateCSR", *optAlternativeNames, *optChallengePassword, city,
458002d39b4SEd Tanous             commonName, *optContactPerson, country, *optEmail, *optGivenName,
459002d39b4SEd Tanous             *optInitials, *optKeyBitLength, *optKeyCurveId,
4600fda0f12SGeorge Liu             *optKeyPairAlgorithm, *optKeyUsage, organization,
4610fda0f12SGeorge Liu             organizationalUnit, state, *optSurname, *optUnstructuredName);
4627e860f15SJohn Edward Broadbent         });
4637e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionGenerateCSR
46430215816SMarri Devender Rao 
4655968caeeSMarri Devender Rao /**
4664e0453b1SGunnar Mills  * @brief Parse and update Certificate Issue/Subject property
4675968caeeSMarri Devender Rao  *
4685968caeeSMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
4695968caeeSMarri Devender Rao  * @param[in] str  Issuer/Subject value in key=value pairs
4705968caeeSMarri Devender Rao  * @param[in] type Issuer/Subject
4715968caeeSMarri Devender Rao  * @return None
4725968caeeSMarri Devender Rao  */
4735968caeeSMarri Devender Rao static void updateCertIssuerOrSubject(nlohmann::json& out,
4745968caeeSMarri Devender Rao                                       const std::string_view value)
4755968caeeSMarri Devender Rao {
4765968caeeSMarri Devender Rao     // example: O=openbmc-project.xyz,CN=localhost
4775968caeeSMarri Devender Rao     std::string_view::iterator i = value.begin();
4785968caeeSMarri Devender Rao     while (i != value.end())
4795968caeeSMarri Devender Rao     {
4805968caeeSMarri Devender Rao         std::string_view::iterator tokenBegin = i;
4815968caeeSMarri Devender Rao         while (i != value.end() && *i != '=')
4825968caeeSMarri Devender Rao         {
48317a897dfSManojkiran Eda             ++i;
4845968caeeSMarri Devender Rao         }
4855968caeeSMarri Devender Rao         if (i == value.end())
4865968caeeSMarri Devender Rao         {
4875968caeeSMarri Devender Rao             break;
4885968caeeSMarri Devender Rao         }
489271584abSEd Tanous         const std::string_view key(tokenBegin,
490271584abSEd Tanous                                    static_cast<size_t>(i - tokenBegin));
49117a897dfSManojkiran Eda         ++i;
4925968caeeSMarri Devender Rao         tokenBegin = i;
4935968caeeSMarri Devender Rao         while (i != value.end() && *i != ',')
4945968caeeSMarri Devender Rao         {
49517a897dfSManojkiran Eda             ++i;
4965968caeeSMarri Devender Rao         }
497271584abSEd Tanous         const std::string_view val(tokenBegin,
498271584abSEd Tanous                                    static_cast<size_t>(i - tokenBegin));
4995968caeeSMarri Devender Rao         if (key == "L")
5005968caeeSMarri Devender Rao         {
5015968caeeSMarri Devender Rao             out["City"] = val;
5025968caeeSMarri Devender Rao         }
5035968caeeSMarri Devender Rao         else if (key == "CN")
5045968caeeSMarri Devender Rao         {
5055968caeeSMarri Devender Rao             out["CommonName"] = val;
5065968caeeSMarri Devender Rao         }
5075968caeeSMarri Devender Rao         else if (key == "C")
5085968caeeSMarri Devender Rao         {
5095968caeeSMarri Devender Rao             out["Country"] = val;
5105968caeeSMarri Devender Rao         }
5115968caeeSMarri Devender Rao         else if (key == "O")
5125968caeeSMarri Devender Rao         {
5135968caeeSMarri Devender Rao             out["Organization"] = val;
5145968caeeSMarri Devender Rao         }
5155968caeeSMarri Devender Rao         else if (key == "OU")
5165968caeeSMarri Devender Rao         {
5175968caeeSMarri Devender Rao             out["OrganizationalUnit"] = val;
5185968caeeSMarri Devender Rao         }
5195968caeeSMarri Devender Rao         else if (key == "ST")
5205968caeeSMarri Devender Rao         {
5215968caeeSMarri Devender Rao             out["State"] = val;
5225968caeeSMarri Devender Rao         }
5235968caeeSMarri Devender Rao         // skip comma character
5245968caeeSMarri Devender Rao         if (i != value.end())
5255968caeeSMarri Devender Rao         {
52617a897dfSManojkiran Eda             ++i;
5275968caeeSMarri Devender Rao         }
5285968caeeSMarri Devender Rao     }
5295968caeeSMarri Devender Rao }
5305968caeeSMarri Devender Rao 
5315968caeeSMarri Devender Rao /**
532d3f92ce7SJiaqing Zhao  * @brief Retrieve the installed certificate list
533d3f92ce7SJiaqing Zhao  *
534d3f92ce7SJiaqing Zhao  * @param[in] asyncResp Shared pointer to the response message
535d3f92ce7SJiaqing Zhao  * @param[in] basePath DBus object path to search
536d3f92ce7SJiaqing Zhao  * @param[in] listPtr Json pointer to the list in asyncResp
537d3f92ce7SJiaqing Zhao  * @param[in] countPtr Json pointer to the count in asyncResp
538d3f92ce7SJiaqing Zhao  * @return None
539d3f92ce7SJiaqing Zhao  */
540d3f92ce7SJiaqing Zhao static void
541d3f92ce7SJiaqing Zhao     getCertificateList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
542d3f92ce7SJiaqing Zhao                        const std::string& basePath,
543d3f92ce7SJiaqing Zhao                        const nlohmann::json::json_pointer& listPtr,
544d3f92ce7SJiaqing Zhao                        const nlohmann::json::json_pointer& countPtr)
545d3f92ce7SJiaqing Zhao {
546d3f92ce7SJiaqing Zhao     crow::connections::systemBus->async_method_call(
547d3f92ce7SJiaqing Zhao         [asyncResp, listPtr, countPtr](
548d3f92ce7SJiaqing Zhao             const boost::system::error_code ec,
549d3f92ce7SJiaqing Zhao             const dbus::utility::MapperGetSubTreePathsResponse& certPaths) {
550d3f92ce7SJiaqing Zhao         if (ec)
551d3f92ce7SJiaqing Zhao         {
552d3f92ce7SJiaqing Zhao             BMCWEB_LOG_ERROR << "Certificate collection query failed: " << ec;
553d3f92ce7SJiaqing Zhao             messages::internalError(asyncResp->res);
554d3f92ce7SJiaqing Zhao             return;
555d3f92ce7SJiaqing Zhao         }
556d3f92ce7SJiaqing Zhao 
557d3f92ce7SJiaqing Zhao         nlohmann::json& links = asyncResp->res.jsonValue[listPtr];
558d3f92ce7SJiaqing Zhao         links = nlohmann::json::array();
559d3f92ce7SJiaqing Zhao         for (const auto& certPath : certPaths)
560d3f92ce7SJiaqing Zhao         {
561d3f92ce7SJiaqing Zhao             sdbusplus::message::object_path objPath(certPath);
562d3f92ce7SJiaqing Zhao             std::string certId = objPath.filename();
563d3f92ce7SJiaqing Zhao             if (certId.empty())
564d3f92ce7SJiaqing Zhao             {
565d3f92ce7SJiaqing Zhao                 BMCWEB_LOG_ERROR << "Invalid certificate objPath " << certPath;
566d3f92ce7SJiaqing Zhao                 continue;
567d3f92ce7SJiaqing Zhao             }
568d3f92ce7SJiaqing Zhao 
569d3f92ce7SJiaqing Zhao             boost::urls::url certURL;
570d3f92ce7SJiaqing Zhao             if (objPath.parent_path() == certs::httpsObjectPath)
571d3f92ce7SJiaqing Zhao             {
572d3f92ce7SJiaqing Zhao                 certURL = crow::utility::urlFromPieces(
573d3f92ce7SJiaqing Zhao                     "redfish", "v1", "Managers", "bmc", "NetworkProtocol",
574d3f92ce7SJiaqing Zhao                     "HTTPS", "Certificates", certId);
575d3f92ce7SJiaqing Zhao             }
576d3f92ce7SJiaqing Zhao             else if (objPath.parent_path() == certs::ldapObjectPath)
577d3f92ce7SJiaqing Zhao             {
578d3f92ce7SJiaqing Zhao                 certURL = crow::utility::urlFromPieces("redfish", "v1",
579d3f92ce7SJiaqing Zhao                                                        "AccountService", "LDAP",
580d3f92ce7SJiaqing Zhao                                                        "Certificates", certId);
581d3f92ce7SJiaqing Zhao             }
582d3f92ce7SJiaqing Zhao             else if (objPath.parent_path() == certs::authorityObjectPath)
583d3f92ce7SJiaqing Zhao             {
584d3f92ce7SJiaqing Zhao                 certURL = crow::utility::urlFromPieces(
585d3f92ce7SJiaqing Zhao                     "redfish", "v1", "Managers", "bmc", "Truststore",
586d3f92ce7SJiaqing Zhao                     "Certificates", certId);
587d3f92ce7SJiaqing Zhao             }
588d3f92ce7SJiaqing Zhao             else
589d3f92ce7SJiaqing Zhao             {
590d3f92ce7SJiaqing Zhao                 continue;
591d3f92ce7SJiaqing Zhao             }
592d3f92ce7SJiaqing Zhao 
593d3f92ce7SJiaqing Zhao             nlohmann::json::object_t link;
594d3f92ce7SJiaqing Zhao             link["@odata.id"] = certURL;
595d3f92ce7SJiaqing Zhao             links.emplace_back(std::move(link));
596d3f92ce7SJiaqing Zhao         }
597d3f92ce7SJiaqing Zhao 
598d3f92ce7SJiaqing Zhao         asyncResp->res.jsonValue[countPtr] = links.size();
599d3f92ce7SJiaqing Zhao         },
600d3f92ce7SJiaqing Zhao         "xyz.openbmc_project.ObjectMapper",
601d3f92ce7SJiaqing Zhao         "/xyz/openbmc_project/object_mapper",
602d3f92ce7SJiaqing Zhao         "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", basePath, 0,
603d3f92ce7SJiaqing Zhao         std::array<const char*, 1>{certs::certPropIntf});
604d3f92ce7SJiaqing Zhao }
605d3f92ce7SJiaqing Zhao 
606d3f92ce7SJiaqing Zhao /**
6075968caeeSMarri Devender Rao  * @brief Retrieve the certificates properties and append to the response
6085968caeeSMarri Devender Rao  * message
6095968caeeSMarri Devender Rao  *
6105968caeeSMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
6115968caeeSMarri Devender Rao  * @param[in] objectPath  Path of the D-Bus service object
6125968caeeSMarri Devender Rao  * @param[in] certId  Id of the certificate
6135968caeeSMarri Devender Rao  * @param[in] certURL  URL of the certificate object
6145968caeeSMarri Devender Rao  * @param[in] name  name of the certificate
6155968caeeSMarri Devender Rao  * @return None
6165968caeeSMarri Devender Rao  */
6175968caeeSMarri Devender Rao static void getCertificateProperties(
6188d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
619e19e97e2SJiaqing Zhao     const std::string& objectPath, const std::string& service,
6201e312598SJiaqing Zhao     const std::string& certId, const boost::urls::url& certURL,
621e19e97e2SJiaqing Zhao     const std::string& name)
6225968caeeSMarri Devender Rao {
6235968caeeSMarri Devender Rao     BMCWEB_LOG_DEBUG << "getCertificateProperties Path=" << objectPath
6245968caeeSMarri Devender Rao                      << " certId=" << certId << " certURl=" << certURL;
6255968caeeSMarri Devender Rao     crow::connections::systemBus->async_method_call(
626b9d36b47SEd Tanous         [asyncResp, certURL, certId,
627b9d36b47SEd Tanous          name](const boost::system::error_code ec,
628b9d36b47SEd Tanous                const dbus::utility::DBusPropertiesMap& properties) {
6295968caeeSMarri Devender Rao         if (ec)
6305968caeeSMarri Devender Rao         {
6315968caeeSMarri Devender Rao             BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
632e19e97e2SJiaqing Zhao             messages::resourceNotFound(asyncResp->res, name, certId);
6335968caeeSMarri Devender Rao             return;
6345968caeeSMarri Devender Rao         }
6351476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] = certURL;
6361476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
6371476687dSEd Tanous             "#Certificate.v1_0_0.Certificate";
638e19e97e2SJiaqing Zhao         asyncResp->res.jsonValue["Id"] = certId;
6391476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = name;
6401476687dSEd Tanous         asyncResp->res.jsonValue["Description"] = name;
6415968caeeSMarri Devender Rao         for (const auto& property : properties)
6425968caeeSMarri Devender Rao         {
6435968caeeSMarri Devender Rao             if (property.first == "CertificateString")
6445968caeeSMarri Devender Rao             {
6455968caeeSMarri Devender Rao                 asyncResp->res.jsonValue["CertificateString"] = "";
6465968caeeSMarri Devender Rao                 const std::string* value =
6475968caeeSMarri Devender Rao                     std::get_if<std::string>(&property.second);
648e662eae8SEd Tanous                 if (value != nullptr)
6495968caeeSMarri Devender Rao                 {
65037cce918SMarri Devender Rao                     asyncResp->res.jsonValue["CertificateString"] = *value;
6515968caeeSMarri Devender Rao                 }
6525968caeeSMarri Devender Rao             }
6535968caeeSMarri Devender Rao             else if (property.first == "KeyUsage")
6545968caeeSMarri Devender Rao             {
655002d39b4SEd Tanous                 nlohmann::json& keyUsage = asyncResp->res.jsonValue["KeyUsage"];
6565968caeeSMarri Devender Rao                 keyUsage = nlohmann::json::array();
6575968caeeSMarri Devender Rao                 const std::vector<std::string>* value =
65837cce918SMarri Devender Rao                     std::get_if<std::vector<std::string>>(&property.second);
659e662eae8SEd Tanous                 if (value != nullptr)
6605968caeeSMarri Devender Rao                 {
6615968caeeSMarri Devender Rao                     for (const std::string& usage : *value)
6625968caeeSMarri Devender Rao                     {
6635968caeeSMarri Devender Rao                         keyUsage.push_back(usage);
6645968caeeSMarri Devender Rao                     }
6655968caeeSMarri Devender Rao                 }
6665968caeeSMarri Devender Rao             }
6675968caeeSMarri Devender Rao             else if (property.first == "Issuer")
6685968caeeSMarri Devender Rao             {
6695968caeeSMarri Devender Rao                 const std::string* value =
6705968caeeSMarri Devender Rao                     std::get_if<std::string>(&property.second);
671e662eae8SEd Tanous                 if (value != nullptr)
6725968caeeSMarri Devender Rao                 {
6735968caeeSMarri Devender Rao                     updateCertIssuerOrSubject(
6745968caeeSMarri Devender Rao                         asyncResp->res.jsonValue["Issuer"], *value);
6755968caeeSMarri Devender Rao                 }
6765968caeeSMarri Devender Rao             }
6775968caeeSMarri Devender Rao             else if (property.first == "Subject")
6785968caeeSMarri Devender Rao             {
6795968caeeSMarri Devender Rao                 const std::string* value =
6805968caeeSMarri Devender Rao                     std::get_if<std::string>(&property.second);
681e662eae8SEd Tanous                 if (value != nullptr)
6825968caeeSMarri Devender Rao                 {
6835968caeeSMarri Devender Rao                     updateCertIssuerOrSubject(
68437cce918SMarri Devender Rao                         asyncResp->res.jsonValue["Subject"], *value);
6855968caeeSMarri Devender Rao                 }
6865968caeeSMarri Devender Rao             }
6875968caeeSMarri Devender Rao             else if (property.first == "ValidNotAfter")
6885968caeeSMarri Devender Rao             {
689002d39b4SEd Tanous                 const uint64_t* value = std::get_if<uint64_t>(&property.second);
690e662eae8SEd Tanous                 if (value != nullptr)
6915968caeeSMarri Devender Rao                 {
6925968caeeSMarri Devender Rao                     asyncResp->res.jsonValue["ValidNotAfter"] =
6931d8782e7SNan Zhou                         crow::utility::getDateTimeUint(*value);
6945968caeeSMarri Devender Rao                 }
6955968caeeSMarri Devender Rao             }
6965968caeeSMarri Devender Rao             else if (property.first == "ValidNotBefore")
6975968caeeSMarri Devender Rao             {
698002d39b4SEd Tanous                 const uint64_t* value = std::get_if<uint64_t>(&property.second);
699e662eae8SEd Tanous                 if (value != nullptr)
7005968caeeSMarri Devender Rao                 {
7015968caeeSMarri Devender Rao                     asyncResp->res.jsonValue["ValidNotBefore"] =
7021d8782e7SNan Zhou                         crow::utility::getDateTimeUint(*value);
7035968caeeSMarri Devender Rao                 }
7045968caeeSMarri Devender Rao             }
7055968caeeSMarri Devender Rao         }
7061e312598SJiaqing Zhao         asyncResp->res.addHeader(
707*d9f6c621SEd Tanous             boost::beast::http::field::location,
708*d9f6c621SEd Tanous             std::string_view(certURL.data(), certURL.size()));
7095968caeeSMarri Devender Rao         },
7105968caeeSMarri Devender Rao         service, objectPath, certs::dbusPropIntf, "GetAll",
7115968caeeSMarri Devender Rao         certs::certPropIntf);
7125968caeeSMarri Devender Rao }
7135968caeeSMarri Devender Rao 
7145968caeeSMarri Devender Rao /**
7155968caeeSMarri Devender Rao  * Action to replace an existing certificate
7165968caeeSMarri Devender Rao  */
7177e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionsReplaceCertificate(App& app)
7185968caeeSMarri Devender Rao {
7190fda0f12SGeorge Liu     BMCWEB_ROUTE(
7200fda0f12SGeorge Liu         app,
7210fda0f12SGeorge Liu         "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate/")
722ed398213SEd Tanous         .privileges(redfish::privileges::postCertificateService)
723002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
724002d39b4SEd Tanous             [&app](const crow::Request& req,
7257e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
7263ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
72745ca1b86SEd Tanous         {
72845ca1b86SEd Tanous             return;
72945ca1b86SEd Tanous         }
7305968caeeSMarri Devender Rao         std::string certificate;
7315968caeeSMarri Devender Rao         nlohmann::json certificateUri;
7325968caeeSMarri Devender Rao         std::optional<std::string> certificateType = "PEM";
7338d1b46d7Szhanghch05 
734002d39b4SEd Tanous         if (!json_util::readJsonAction(req, asyncResp->res, "CertificateString",
735002d39b4SEd Tanous                                        certificate, "CertificateUri",
736002d39b4SEd Tanous                                        certificateUri, "CertificateType",
737002d39b4SEd Tanous                                        certificateType))
7385968caeeSMarri Devender Rao         {
7395968caeeSMarri Devender Rao             BMCWEB_LOG_ERROR << "Required parameters are missing";
7405968caeeSMarri Devender Rao             messages::internalError(asyncResp->res);
7415968caeeSMarri Devender Rao             return;
7425968caeeSMarri Devender Rao         }
7435968caeeSMarri Devender Rao 
7445968caeeSMarri Devender Rao         if (!certificateType)
7455968caeeSMarri Devender Rao         {
7465968caeeSMarri Devender Rao             // should never happen, but it never hurts to be paranoid.
7475968caeeSMarri Devender Rao             return;
7485968caeeSMarri Devender Rao         }
7495968caeeSMarri Devender Rao         if (certificateType != "PEM")
7505968caeeSMarri Devender Rao         {
7515968caeeSMarri Devender Rao             messages::actionParameterNotSupported(
7525968caeeSMarri Devender Rao                 asyncResp->res, "CertificateType", "ReplaceCertificate");
7535968caeeSMarri Devender Rao             return;
7545968caeeSMarri Devender Rao         }
7555968caeeSMarri Devender Rao 
7565968caeeSMarri Devender Rao         std::string certURI;
7575968caeeSMarri Devender Rao         if (!redfish::json_util::readJson(certificateUri, asyncResp->res,
7585968caeeSMarri Devender Rao                                           "@odata.id", certURI))
7595968caeeSMarri Devender Rao         {
7605968caeeSMarri Devender Rao             messages::actionParameterMissing(
7615968caeeSMarri Devender Rao                 asyncResp->res, "ReplaceCertificate", "CertificateUri");
7625968caeeSMarri Devender Rao             return;
7635968caeeSMarri Devender Rao         }
76475b63a2cSJiaqing Zhao         BMCWEB_LOG_INFO << "Certificate URI to replace: " << certURI;
7655968caeeSMarri Devender Rao 
76675b63a2cSJiaqing Zhao         boost::urls::result<boost::urls::url_view> parsedUrl =
76775b63a2cSJiaqing Zhao             boost::urls::parse_relative_ref(certURI);
76875b63a2cSJiaqing Zhao         if (!parsedUrl)
7695968caeeSMarri Devender Rao         {
770002d39b4SEd Tanous             messages::actionParameterValueFormatError(asyncResp->res, certURI,
771002d39b4SEd Tanous                                                       "CertificateUri",
7725968caeeSMarri Devender Rao                                                       "ReplaceCertificate");
7735968caeeSMarri Devender Rao             return;
7745968caeeSMarri Devender Rao         }
77575b63a2cSJiaqing Zhao 
77675b63a2cSJiaqing Zhao         std::string id;
77775b63a2cSJiaqing Zhao         sdbusplus::message::object_path objectPath;
7785968caeeSMarri Devender Rao         std::string name;
77937cce918SMarri Devender Rao         std::string service;
78075b63a2cSJiaqing Zhao         if (crow::utility::readUrlSegments(
78175b63a2cSJiaqing Zhao                 *parsedUrl, "redfish", "v1", "Managers", "bmc",
78275b63a2cSJiaqing Zhao                 "NetworkProtocol", "HTTPS", "Certificates", std::ref(id)))
7835968caeeSMarri Devender Rao         {
784002d39b4SEd Tanous             objectPath =
78575b63a2cSJiaqing Zhao                 sdbusplus::message::object_path(certs::httpsObjectPath) / id;
7865968caeeSMarri Devender Rao             name = "HTTPS certificate";
78737cce918SMarri Devender Rao             service = certs::httpsServiceName;
78837cce918SMarri Devender Rao         }
78975b63a2cSJiaqing Zhao         else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1",
79075b63a2cSJiaqing Zhao                                                 "AccountService", "LDAP",
79175b63a2cSJiaqing Zhao                                                 "Certificates", std::ref(id)))
79237cce918SMarri Devender Rao         {
793002d39b4SEd Tanous             objectPath =
79475b63a2cSJiaqing Zhao                 sdbusplus::message::object_path(certs::ldapObjectPath) / id;
79537cce918SMarri Devender Rao             name = "LDAP certificate";
79637cce918SMarri Devender Rao             service = certs::ldapServiceName;
7975968caeeSMarri Devender Rao         }
79875b63a2cSJiaqing Zhao         else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1",
79975b63a2cSJiaqing Zhao                                                 "Managers", "bmc", "Truststore",
80075b63a2cSJiaqing Zhao                                                 "Certificates", std::ref(id)))
801cfcd5f6bSMarri Devender Rao         {
80275b63a2cSJiaqing Zhao             objectPath =
80375b63a2cSJiaqing Zhao                 sdbusplus::message::object_path(certs::authorityObjectPath) /
80475b63a2cSJiaqing Zhao                 id;
805cfcd5f6bSMarri Devender Rao             name = "TrustStore certificate";
806cfcd5f6bSMarri Devender Rao             service = certs::authorityServiceName;
807cfcd5f6bSMarri Devender Rao         }
8085968caeeSMarri Devender Rao         else
8095968caeeSMarri Devender Rao         {
8105968caeeSMarri Devender Rao             messages::actionParameterNotSupported(
8115968caeeSMarri Devender Rao                 asyncResp->res, "CertificateUri", "ReplaceCertificate");
8125968caeeSMarri Devender Rao             return;
8135968caeeSMarri Devender Rao         }
8145968caeeSMarri Devender Rao 
8155968caeeSMarri Devender Rao         std::shared_ptr<CertificateFile> certFile =
8165968caeeSMarri Devender Rao             std::make_shared<CertificateFile>(certificate);
8175968caeeSMarri Devender Rao         crow::connections::systemBus->async_method_call(
8181e312598SJiaqing Zhao             [asyncResp, certFile, objectPath, service, url{*parsedUrl}, id,
8195968caeeSMarri Devender Rao              name](const boost::system::error_code ec) {
8205968caeeSMarri Devender Rao             if (ec)
8215968caeeSMarri Devender Rao             {
8225968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
82390d2d1e8SJiaqing Zhao                 if (ec.value() ==
82490d2d1e8SJiaqing Zhao                     boost::system::linux_error::bad_request_descriptor)
82590d2d1e8SJiaqing Zhao                 {
82675b63a2cSJiaqing Zhao                     messages::resourceNotFound(asyncResp->res, name, id);
8275968caeeSMarri Devender Rao                     return;
8285968caeeSMarri Devender Rao                 }
82990d2d1e8SJiaqing Zhao                 messages::internalError(asyncResp->res);
83090d2d1e8SJiaqing Zhao                 return;
83190d2d1e8SJiaqing Zhao             }
8321e312598SJiaqing Zhao             getCertificateProperties(asyncResp, objectPath, service, id, url,
8331e312598SJiaqing Zhao                                      name);
8345968caeeSMarri Devender Rao             BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
8355968caeeSMarri Devender Rao                              << certFile->getCertFilePath();
8365968caeeSMarri Devender Rao             },
8375968caeeSMarri Devender Rao             service, objectPath, certs::certReplaceIntf, "Replace",
8385968caeeSMarri Devender Rao             certFile->getCertFilePath());
8397e860f15SJohn Edward Broadbent         });
8407e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionsReplaceCertificate
8415968caeeSMarri Devender Rao 
8425968caeeSMarri Devender Rao /**
8435968caeeSMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
8445968caeeSMarri Devender Rao  * of a component, account or service.
8455968caeeSMarri Devender Rao  */
8465968caeeSMarri Devender Rao 
8477e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificate(App& app)
8485968caeeSMarri Devender Rao {
8497e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
8507e860f15SJohn Edward Broadbent         app,
8517e860f15SJohn Edward Broadbent         "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/<str>/")
852ed398213SEd Tanous         .privileges(redfish::privileges::getCertificate)
8531e312598SJiaqing Zhao         .methods(boost::beast::http::verb::get)(
8541e312598SJiaqing Zhao             [&app](const crow::Request& req,
8557e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
856717b9802SJiaqing Zhao                    const std::string& id) -> void {
8573ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
85845ca1b86SEd Tanous                 {
85945ca1b86SEd Tanous                     return;
86045ca1b86SEd Tanous                 }
8615968caeeSMarri Devender Rao 
862717b9802SJiaqing Zhao                 BMCWEB_LOG_DEBUG << "HTTPS Certificate ID=" << id;
8631e312598SJiaqing Zhao                 const boost::urls::url certURL = crow::utility::urlFromPieces(
8641e312598SJiaqing Zhao                     "redfish", "v1", "Managers", "bmc", "NetworkProtocol",
8651e312598SJiaqing Zhao                     "HTTPS", "Certificates", id);
866717b9802SJiaqing Zhao                 std::string objPath =
8671e312598SJiaqing Zhao                     sdbusplus::message::object_path(certs::httpsObjectPath) /
8681e312598SJiaqing Zhao                     id;
869717b9802SJiaqing Zhao                 getCertificateProperties(asyncResp, objPath,
870717b9802SJiaqing Zhao                                          certs::httpsServiceName, id, certURL,
871717b9802SJiaqing Zhao                                          "HTTPS Certificate");
8727e860f15SJohn Edward Broadbent             });
8735968caeeSMarri Devender Rao }
8745968caeeSMarri Devender Rao 
8755968caeeSMarri Devender Rao /**
8765968caeeSMarri Devender Rao  * Collection of HTTPS certificates
8775968caeeSMarri Devender Rao  */
8787e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificateCollection(App& app)
8795968caeeSMarri Devender Rao {
8807e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
8815968caeeSMarri Devender Rao                  "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
882ed398213SEd Tanous         .privileges(redfish::privileges::getCertificateCollection)
883002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
884002d39b4SEd Tanous             [&app](const crow::Request& req,
885002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
8863ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
88745ca1b86SEd Tanous         {
88845ca1b86SEd Tanous             return;
88945ca1b86SEd Tanous         }
8901476687dSEd Tanous 
8911476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
8921476687dSEd Tanous             "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates";
8931476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
8941476687dSEd Tanous             "#CertificateCollection.CertificateCollection";
8951476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = "HTTPS Certificates Collection";
8961476687dSEd Tanous         asyncResp->res.jsonValue["Description"] =
8971476687dSEd Tanous             "A Collection of HTTPS certificate instances";
8988d1b46d7Szhanghch05 
899d3f92ce7SJiaqing Zhao         getCertificateList(asyncResp, certs::httpsObjectPath,
900d3f92ce7SJiaqing Zhao                            "/Members"_json_pointer,
901d3f92ce7SJiaqing Zhao                            "/Members@odata.count"_json_pointer);
9027e860f15SJohn Edward Broadbent         });
9035968caeeSMarri Devender Rao 
9047e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
9057e860f15SJohn Edward Broadbent                  "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
906ed398213SEd Tanous         .privileges(redfish::privileges::postCertificateCollection)
907002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
908002d39b4SEd Tanous             [&app](const crow::Request& req,
9097e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
9103ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
91145ca1b86SEd Tanous         {
91245ca1b86SEd Tanous             return;
91345ca1b86SEd Tanous         }
9145968caeeSMarri Devender Rao         BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost";
9158d1b46d7Szhanghch05 
9161476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = "HTTPS Certificate";
9171476687dSEd Tanous         asyncResp->res.jsonValue["Description"] = "HTTPS Certificate";
9185968caeeSMarri Devender Rao 
919002d39b4SEd Tanous         std::string certFileBody = getCertificateFromReqBody(asyncResp, req);
92058eb238fSKowalski, Kamil 
92158eb238fSKowalski, Kamil         if (certFileBody.empty())
92258eb238fSKowalski, Kamil         {
9230fda0f12SGeorge Liu             BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
924a08752f5SZbigniew Kurzynski             messages::unrecognizedRequestBody(asyncResp->res);
92558eb238fSKowalski, Kamil             return;
92658eb238fSKowalski, Kamil         }
92758eb238fSKowalski, Kamil 
9285968caeeSMarri Devender Rao         std::shared_ptr<CertificateFile> certFile =
92958eb238fSKowalski, Kamil             std::make_shared<CertificateFile>(certFileBody);
9305968caeeSMarri Devender Rao 
9315968caeeSMarri Devender Rao         crow::connections::systemBus->async_method_call(
932656ec7e3SZbigniew Kurzynski             [asyncResp, certFile](const boost::system::error_code ec,
933656ec7e3SZbigniew Kurzynski                                   const std::string& objectPath) {
9345968caeeSMarri Devender Rao             if (ec)
9355968caeeSMarri Devender Rao             {
9365968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
9375968caeeSMarri Devender Rao                 messages::internalError(asyncResp->res);
9385968caeeSMarri Devender Rao                 return;
9395968caeeSMarri Devender Rao             }
940717b9802SJiaqing Zhao 
941717b9802SJiaqing Zhao             sdbusplus::message::object_path path(objectPath);
942717b9802SJiaqing Zhao             std::string certId = path.filename();
9431e312598SJiaqing Zhao             const boost::urls::url certURL = crow::utility::urlFromPieces(
9441e312598SJiaqing Zhao                 "redfish", "v1", "Managers", "bmc", "NetworkProtocol", "HTTPS",
9451e312598SJiaqing Zhao                 "Certificates", certId);
946717b9802SJiaqing Zhao             getCertificateProperties(asyncResp, objectPath,
947717b9802SJiaqing Zhao                                      certs::httpsServiceName, certId, certURL,
948717b9802SJiaqing Zhao                                      "HTTPS Certificate");
9495968caeeSMarri Devender Rao             BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
9505968caeeSMarri Devender Rao                              << certFile->getCertFilePath();
9515968caeeSMarri Devender Rao             },
95237cce918SMarri Devender Rao             certs::httpsServiceName, certs::httpsObjectPath,
9530fda0f12SGeorge Liu             certs::certInstallIntf, "Install", certFile->getCertFilePath());
9547e860f15SJohn Edward Broadbent         });
9557e860f15SJohn Edward Broadbent } // requestRoutesHTTPSCertificateCollection
9565968caeeSMarri Devender Rao 
9575968caeeSMarri Devender Rao /**
9587e860f15SJohn Edward Broadbent  * The certificate location schema defines a resource that an administrator
9597e860f15SJohn Edward Broadbent  * can use in order to locate all certificates installed on a given service.
9607e860f15SJohn Edward Broadbent  */
9617e860f15SJohn Edward Broadbent inline void requestRoutesCertificateLocations(App& app)
9627e860f15SJohn Edward Broadbent {
9637e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/")
964ed398213SEd Tanous         .privileges(redfish::privileges::getCertificateLocations)
965002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
966002d39b4SEd Tanous             [&app](const crow::Request& req,
967002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
9683ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
96945ca1b86SEd Tanous         {
97045ca1b86SEd Tanous             return;
97145ca1b86SEd Tanous         }
9721476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
9731476687dSEd Tanous             "/redfish/v1/CertificateService/CertificateLocations";
9741476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
9751476687dSEd Tanous             "#CertificateLocations.v1_0_0.CertificateLocations";
9761476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = "Certificate Locations";
9771476687dSEd Tanous         asyncResp->res.jsonValue["Id"] = "CertificateLocations";
9781476687dSEd Tanous         asyncResp->res.jsonValue["Description"] =
9797e860f15SJohn Edward Broadbent             "Defines a resource that an administrator can use in order to "
9801476687dSEd Tanous             "locate all certificates installed on a given service";
9817e860f15SJohn Edward Broadbent 
982d3f92ce7SJiaqing Zhao         getCertificateList(asyncResp, certs::baseObjectPath,
983d3f92ce7SJiaqing Zhao                            "/Links/Certificates"_json_pointer,
984d3f92ce7SJiaqing Zhao                            "/Links/Certificates@odata.count"_json_pointer);
9857e860f15SJohn Edward Broadbent         });
9867e860f15SJohn Edward Broadbent }
9877e860f15SJohn Edward Broadbent // requestRoutesCertificateLocations
98837cce918SMarri Devender Rao 
98937cce918SMarri Devender Rao /**
99037cce918SMarri Devender Rao  * Collection of LDAP certificates
99137cce918SMarri Devender Rao  */
9927e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificateCollection(App& app)
99337cce918SMarri Devender Rao {
9947e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
995ed398213SEd Tanous         .privileges(redfish::privileges::getCertificateCollection)
996002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
997002d39b4SEd Tanous             [&app](const crow::Request& req,
998002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
9993ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
100045ca1b86SEd Tanous         {
100145ca1b86SEd Tanous             return;
100245ca1b86SEd Tanous         }
10031476687dSEd Tanous 
10041476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
10051476687dSEd Tanous             "/redfish/v1/AccountService/LDAP/Certificates";
10061476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
10071476687dSEd Tanous             "#CertificateCollection.CertificateCollection";
10081476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = "LDAP Certificates Collection";
10091476687dSEd Tanous         asyncResp->res.jsonValue["Description"] =
10101476687dSEd Tanous             "A Collection of LDAP certificate instances";
10118d1b46d7Szhanghch05 
1012d3f92ce7SJiaqing Zhao         getCertificateList(asyncResp, certs::ldapObjectPath,
1013d3f92ce7SJiaqing Zhao                            "/Members"_json_pointer,
1014d3f92ce7SJiaqing Zhao                            "/Members@odata.count"_json_pointer);
10157e860f15SJohn Edward Broadbent         });
101637cce918SMarri Devender Rao 
10177e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
1018ed398213SEd Tanous         .privileges(redfish::privileges::postCertificateCollection)
10197e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
102045ca1b86SEd Tanous             [&app](const crow::Request& req,
10217e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
10223ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
102345ca1b86SEd Tanous         {
102445ca1b86SEd Tanous             return;
102545ca1b86SEd Tanous         }
1026002d39b4SEd Tanous         std::string certFileBody = getCertificateFromReqBody(asyncResp, req);
102758eb238fSKowalski, Kamil 
102858eb238fSKowalski, Kamil         if (certFileBody.empty())
102958eb238fSKowalski, Kamil         {
1030002d39b4SEd Tanous             BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
1031a08752f5SZbigniew Kurzynski             messages::unrecognizedRequestBody(asyncResp->res);
103258eb238fSKowalski, Kamil             return;
103358eb238fSKowalski, Kamil         }
103458eb238fSKowalski, Kamil 
103558eb238fSKowalski, Kamil         std::shared_ptr<CertificateFile> certFile =
103658eb238fSKowalski, Kamil             std::make_shared<CertificateFile>(certFileBody);
103758eb238fSKowalski, Kamil 
103837cce918SMarri Devender Rao         crow::connections::systemBus->async_method_call(
1039656ec7e3SZbigniew Kurzynski             [asyncResp, certFile](const boost::system::error_code ec,
1040656ec7e3SZbigniew Kurzynski                                   const std::string& objectPath) {
104137cce918SMarri Devender Rao             if (ec)
104237cce918SMarri Devender Rao             {
104337cce918SMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
104437cce918SMarri Devender Rao                 messages::internalError(asyncResp->res);
104537cce918SMarri Devender Rao                 return;
104637cce918SMarri Devender Rao             }
1047717b9802SJiaqing Zhao 
1048717b9802SJiaqing Zhao             sdbusplus::message::object_path path(objectPath);
1049717b9802SJiaqing Zhao             std::string certId = path.filename();
10501e312598SJiaqing Zhao             const boost::urls::url certURL =
10511e312598SJiaqing Zhao                 crow::utility::urlFromPieces("redfish", "v1", "AccountService",
10521e312598SJiaqing Zhao                                              "LDAP", "Certificates", certId);
1053717b9802SJiaqing Zhao             getCertificateProperties(asyncResp, objectPath,
1054717b9802SJiaqing Zhao                                      certs::ldapServiceName, certId, certURL,
1055717b9802SJiaqing Zhao                                      "LDAP Certificate");
105637cce918SMarri Devender Rao             BMCWEB_LOG_DEBUG << "LDAP certificate install file="
105737cce918SMarri Devender Rao                              << certFile->getCertFilePath();
105837cce918SMarri Devender Rao             },
105937cce918SMarri Devender Rao             certs::ldapServiceName, certs::ldapObjectPath,
1060002d39b4SEd Tanous             certs::certInstallIntf, "Install", certFile->getCertFilePath());
10617e860f15SJohn Edward Broadbent         });
10627e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificateCollection
106337cce918SMarri Devender Rao 
106437cce918SMarri Devender Rao /**
106537cce918SMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
106637cce918SMarri Devender Rao  * of a component, account or service.
106737cce918SMarri Devender Rao  */
10687e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificate(App& app)
106937cce918SMarri Devender Rao {
10707e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/")
1071ed398213SEd Tanous         .privileges(redfish::privileges::getCertificate)
10727e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
107345ca1b86SEd Tanous             [&app](const crow::Request& req,
10747e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1075717b9802SJiaqing Zhao                    const std::string& id) {
10763ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
107745ca1b86SEd Tanous         {
107845ca1b86SEd Tanous             return;
107945ca1b86SEd Tanous         }
1080717b9802SJiaqing Zhao 
1081717b9802SJiaqing Zhao         BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" << id;
10821e312598SJiaqing Zhao         const boost::urls::url certURL = crow::utility::urlFromPieces(
10831e312598SJiaqing Zhao             "redfish", "v1", "AccountService", "LDAP", "Certificates", id);
1084717b9802SJiaqing Zhao         std::string objPath =
1085717b9802SJiaqing Zhao             sdbusplus::message::object_path(certs::ldapObjectPath) / id;
1086717b9802SJiaqing Zhao         getCertificateProperties(asyncResp, objPath, certs::ldapServiceName, id,
1087717b9802SJiaqing Zhao                                  certURL, "LDAP Certificate");
10887e860f15SJohn Edward Broadbent         });
10897e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificate
1090cfcd5f6bSMarri Devender Rao /**
1091cfcd5f6bSMarri Devender Rao  * Collection of TrustStoreCertificate certificates
1092cfcd5f6bSMarri Devender Rao  */
10937e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificateCollection(App& app)
1094cfcd5f6bSMarri Devender Rao {
10957e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
1096ed398213SEd Tanous         .privileges(redfish::privileges::getCertificate)
1097002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
1098002d39b4SEd Tanous             [&app](const crow::Request& req,
1099002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
11003ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
110145ca1b86SEd Tanous         {
110245ca1b86SEd Tanous             return;
110345ca1b86SEd Tanous         }
11041476687dSEd Tanous 
11051476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
11061476687dSEd Tanous             "/redfish/v1/Managers/bmc/Truststore/Certificates/";
11071476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
11081476687dSEd Tanous             "#CertificateCollection.CertificateCollection";
1109002d39b4SEd Tanous         asyncResp->res.jsonValue["Name"] = "TrustStore Certificates Collection";
11101476687dSEd Tanous         asyncResp->res.jsonValue["Description"] =
11111476687dSEd Tanous             "A Collection of TrustStore certificate instances";
11128d1b46d7Szhanghch05 
1113d3f92ce7SJiaqing Zhao         getCertificateList(asyncResp, certs::authorityObjectPath,
1114d3f92ce7SJiaqing Zhao                            "/Members"_json_pointer,
1115d3f92ce7SJiaqing Zhao                            "/Members@odata.count"_json_pointer);
11167e860f15SJohn Edward Broadbent         });
1117cfcd5f6bSMarri Devender Rao 
11187e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
1119ed398213SEd Tanous         .privileges(redfish::privileges::postCertificateCollection)
1120002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
1121002d39b4SEd Tanous             [&app](const crow::Request& req,
11227e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
11233ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
112445ca1b86SEd Tanous         {
112545ca1b86SEd Tanous             return;
112645ca1b86SEd Tanous         }
1127002d39b4SEd Tanous         std::string certFileBody = getCertificateFromReqBody(asyncResp, req);
1128a08752f5SZbigniew Kurzynski 
1129a08752f5SZbigniew Kurzynski         if (certFileBody.empty())
1130a08752f5SZbigniew Kurzynski         {
11310fda0f12SGeorge Liu             BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
1132a08752f5SZbigniew Kurzynski             messages::unrecognizedRequestBody(asyncResp->res);
1133a08752f5SZbigniew Kurzynski             return;
1134a08752f5SZbigniew Kurzynski         }
1135a08752f5SZbigniew Kurzynski 
1136a08752f5SZbigniew Kurzynski         std::shared_ptr<CertificateFile> certFile =
1137a08752f5SZbigniew Kurzynski             std::make_shared<CertificateFile>(certFileBody);
1138cfcd5f6bSMarri Devender Rao         crow::connections::systemBus->async_method_call(
1139656ec7e3SZbigniew Kurzynski             [asyncResp, certFile](const boost::system::error_code ec,
1140656ec7e3SZbigniew Kurzynski                                   const std::string& objectPath) {
1141cfcd5f6bSMarri Devender Rao             if (ec)
1142cfcd5f6bSMarri Devender Rao             {
1143cfcd5f6bSMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
1144cfcd5f6bSMarri Devender Rao                 messages::internalError(asyncResp->res);
1145cfcd5f6bSMarri Devender Rao                 return;
1146cfcd5f6bSMarri Devender Rao             }
1147656ec7e3SZbigniew Kurzynski 
1148717b9802SJiaqing Zhao             sdbusplus::message::object_path path(objectPath);
1149717b9802SJiaqing Zhao             std::string certId = path.filename();
11501e312598SJiaqing Zhao             const boost::urls::url certURL = crow::utility::urlFromPieces(
11511e312598SJiaqing Zhao                 "redfish", "v1", "Managers", "bmc", "Truststore",
11521e312598SJiaqing Zhao                 "Certificates", certId);
1153717b9802SJiaqing Zhao             getCertificateProperties(asyncResp, objectPath,
1154717b9802SJiaqing Zhao                                      certs::authorityServiceName, certId,
1155717b9802SJiaqing Zhao                                      certURL, "TrustStore Certificate");
11560fda0f12SGeorge Liu             BMCWEB_LOG_DEBUG << "TrustStore certificate install file="
1157cfcd5f6bSMarri Devender Rao                              << certFile->getCertFilePath();
1158cfcd5f6bSMarri Devender Rao             },
1159cfcd5f6bSMarri Devender Rao             certs::authorityServiceName, certs::authorityObjectPath,
11600fda0f12SGeorge Liu             certs::certInstallIntf, "Install", certFile->getCertFilePath());
11617e860f15SJohn Edward Broadbent         });
11627e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificateCollection
1163cfcd5f6bSMarri Devender Rao 
1164cfcd5f6bSMarri Devender Rao /**
1165cfcd5f6bSMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
1166cfcd5f6bSMarri Devender Rao  * of a component, account or service.
1167cfcd5f6bSMarri Devender Rao  */
11687e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificate(App& app)
1169cfcd5f6bSMarri Devender Rao {
11707e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
1171ed398213SEd Tanous         .privileges(redfish::privileges::getCertificate)
11727e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
117345ca1b86SEd Tanous             [&app](const crow::Request& req,
11747e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1175717b9802SJiaqing Zhao                    const std::string& id) {
11763ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
117745ca1b86SEd Tanous         {
117845ca1b86SEd Tanous             return;
117945ca1b86SEd Tanous         }
1180717b9802SJiaqing Zhao 
1181717b9802SJiaqing Zhao         BMCWEB_LOG_DEBUG << "Truststore Certificate ID=" << id;
11821e312598SJiaqing Zhao         const boost::urls::url certURL =
11831e312598SJiaqing Zhao             crow::utility::urlFromPieces("redfish", "v1", "Managers", "bmc",
11841e312598SJiaqing Zhao                                          "Truststore", "Certificates", id);
1185717b9802SJiaqing Zhao         std::string objPath =
1186717b9802SJiaqing Zhao             sdbusplus::message::object_path(certs::authorityObjectPath) / id;
1187717b9802SJiaqing Zhao         getCertificateProperties(asyncResp, objPath,
1188717b9802SJiaqing Zhao                                  certs::authorityServiceName, id, certURL,
1189717b9802SJiaqing Zhao                                  "TrustStore Certificate");
11907e860f15SJohn Edward Broadbent         });
119107a60299SZbigniew Kurzynski 
11927e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
1193ed398213SEd Tanous         .privileges(redfish::privileges::deleteCertificate)
11947e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::delete_)(
119545ca1b86SEd Tanous             [&app](const crow::Request& req,
11967e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1197717b9802SJiaqing Zhao                    const std::string& id) {
11983ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
119945ca1b86SEd Tanous         {
120045ca1b86SEd Tanous             return;
120145ca1b86SEd Tanous         }
120207a60299SZbigniew Kurzynski 
1203717b9802SJiaqing Zhao         BMCWEB_LOG_DEBUG << "Delete TrustStore Certificate ID=" << id;
1204717b9802SJiaqing Zhao         std::string objPath =
1205717b9802SJiaqing Zhao             sdbusplus::message::object_path(certs::authorityObjectPath) / id;
120607a60299SZbigniew Kurzynski 
120707a60299SZbigniew Kurzynski         crow::connections::systemBus->async_method_call(
120807a60299SZbigniew Kurzynski             [asyncResp, id](const boost::system::error_code ec) {
120907a60299SZbigniew Kurzynski             if (ec)
121007a60299SZbigniew Kurzynski             {
121107a60299SZbigniew Kurzynski                 messages::resourceNotFound(asyncResp->res,
1212717b9802SJiaqing Zhao                                            "TrustStore Certificate", id);
121307a60299SZbigniew Kurzynski                 return;
121407a60299SZbigniew Kurzynski             }
121507a60299SZbigniew Kurzynski             BMCWEB_LOG_INFO << "Certificate deleted";
1216002d39b4SEd Tanous             asyncResp->res.result(boost::beast::http::status::no_content);
121707a60299SZbigniew Kurzynski             },
1218717b9802SJiaqing Zhao             certs::authorityServiceName, objPath, certs::objDeleteIntf,
121907a60299SZbigniew Kurzynski             "Delete");
12207e860f15SJohn Edward Broadbent         });
12217e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificate
12225968caeeSMarri Devender Rao } // namespace redfish
1223