xref: /openbmc/bmcweb/features/redfish/lib/certificate_service.hpp (revision 9b12d1f9b0cfe4f7f5cf62a3439bbd24a2c08587)
15968caeeSMarri Devender Rao #pragma once
25968caeeSMarri Devender Rao 
3*9b12d1f9SKrzysztof Grobelny #include "utils/dbus_utils.hpp"
4*9b12d1f9SKrzysztof Grobelny 
57e860f15SJohn Edward Broadbent #include <app.hpp>
6d9f6c621SEd Tanous #include <async_resp.hpp>
790d2d1e8SJiaqing Zhao #include <boost/system/linux_error.hpp>
8168e20c1SEd Tanous #include <dbus_utility.hpp>
9d9f6c621SEd Tanous #include <http_response.hpp>
1045ca1b86SEd Tanous #include <query.hpp>
11ed398213SEd Tanous #include <registries/privilege_registry.hpp>
12*9b12d1f9SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp>
13*9b12d1f9SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp>
141214b7e7SGunnar Mills 
155968caeeSMarri Devender Rao namespace redfish
165968caeeSMarri Devender Rao {
175968caeeSMarri Devender Rao namespace certs
185968caeeSMarri Devender Rao {
195968caeeSMarri Devender Rao constexpr char const* certInstallIntf = "xyz.openbmc_project.Certs.Install";
205968caeeSMarri Devender Rao constexpr char const* certReplaceIntf = "xyz.openbmc_project.Certs.Replace";
2107a60299SZbigniew Kurzynski constexpr char const* objDeleteIntf = "xyz.openbmc_project.Object.Delete";
225968caeeSMarri Devender Rao constexpr char const* certPropIntf = "xyz.openbmc_project.Certs.Certificate";
235968caeeSMarri Devender Rao constexpr char const* dbusPropIntf = "org.freedesktop.DBus.Properties";
245968caeeSMarri Devender Rao constexpr char const* dbusObjManagerIntf = "org.freedesktop.DBus.ObjectManager";
2537cce918SMarri Devender Rao constexpr char const* httpsServiceName =
2637cce918SMarri Devender Rao     "xyz.openbmc_project.Certs.Manager.Server.Https";
2737cce918SMarri Devender Rao constexpr char const* ldapServiceName =
2837cce918SMarri Devender Rao     "xyz.openbmc_project.Certs.Manager.Client.Ldap";
29cfcd5f6bSMarri Devender Rao constexpr char const* authorityServiceName =
30cfcd5f6bSMarri Devender Rao     "xyz.openbmc_project.Certs.Manager.Authority.Ldap";
31c6a8dfb1SJiaqing Zhao constexpr char const* baseObjectPath = "/xyz/openbmc_project/certs";
32c6a8dfb1SJiaqing Zhao constexpr char const* httpsObjectPath =
33c6a8dfb1SJiaqing Zhao     "/xyz/openbmc_project/certs/server/https";
34c6a8dfb1SJiaqing Zhao constexpr char const* ldapObjectPath = "/xyz/openbmc_project/certs/client/ldap";
35cfcd5f6bSMarri Devender Rao constexpr char const* authorityObjectPath =
36cfcd5f6bSMarri Devender Rao     "/xyz/openbmc_project/certs/authority/ldap";
375968caeeSMarri Devender Rao } // namespace certs
385968caeeSMarri Devender Rao 
395968caeeSMarri Devender Rao /**
405968caeeSMarri Devender Rao  * The Certificate schema defines a Certificate Service which represents the
415968caeeSMarri Devender Rao  * actions available to manage certificates and links to where certificates
425968caeeSMarri Devender Rao  * are installed.
435968caeeSMarri Devender Rao  */
447e860f15SJohn Edward Broadbent 
455968caeeSMarri Devender Rao // TODO: Issue#61 No entries are available for Certificate
464e0453b1SGunnar Mills // service at https://www.dmtf.org/standards/redfish
475968caeeSMarri Devender Rao // "redfish standard registries". Need to modify after DMTF
485968caeeSMarri Devender Rao // publish Privilege details for certificate service
495968caeeSMarri Devender Rao 
507e860f15SJohn Edward Broadbent inline void requestRoutesCertificateService(App& app)
515968caeeSMarri Devender Rao {
527e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/")
53ed398213SEd Tanous         .privileges(redfish::privileges::getCertificateService)
54002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
55002d39b4SEd Tanous             [&app](const crow::Request& req,
56002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
573ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
5845ca1b86SEd Tanous         {
5945ca1b86SEd Tanous             return;
6045ca1b86SEd Tanous         }
611476687dSEd Tanous 
621476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
631476687dSEd Tanous             "#CertificateService.v1_0_0.CertificateService";
641476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
651476687dSEd Tanous             "/redfish/v1/CertificateService";
661476687dSEd Tanous         asyncResp->res.jsonValue["Id"] = "CertificateService";
671476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = "Certificate Service";
681476687dSEd Tanous         asyncResp->res.jsonValue["Description"] =
691476687dSEd Tanous             "Actions available to manage certificates";
7072048780SAbhishek Patel         // /redfish/v1/CertificateService/CertificateLocations is something
7172048780SAbhishek Patel         // only ConfigureManager can access then only display when the user
7272048780SAbhishek Patel         // has permissions ConfigureManager
7372048780SAbhishek Patel         Privileges effectiveUserPrivileges =
7472048780SAbhishek Patel             redfish::getUserPrivileges(req.userRole);
7572048780SAbhishek Patel         if (isOperationAllowedWithPrivileges({{"ConfigureManager"}},
7672048780SAbhishek Patel                                              effectiveUserPrivileges))
7772048780SAbhishek Patel         {
781476687dSEd Tanous             asyncResp->res.jsonValue["CertificateLocations"]["@odata.id"] =
791476687dSEd Tanous                 "/redfish/v1/CertificateService/CertificateLocations";
8072048780SAbhishek Patel         }
810fda0f12SGeorge Liu         asyncResp->res
82002d39b4SEd Tanous             .jsonValue["Actions"]["#CertificateService.ReplaceCertificate"] = {
830fda0f12SGeorge Liu             {"target",
840fda0f12SGeorge Liu              "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate"},
855968caeeSMarri Devender Rao             {"CertificateType@Redfish.AllowableValues", {"PEM"}}};
867e860f15SJohn Edward Broadbent         asyncResp->res
877e860f15SJohn Edward Broadbent             .jsonValue["Actions"]["#CertificateService.GenerateCSR"] = {
880fda0f12SGeorge Liu             {"target",
890fda0f12SGeorge Liu              "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR"}};
907e860f15SJohn Edward Broadbent         });
917e860f15SJohn Edward Broadbent } // requestRoutesCertificateService
9237cce918SMarri Devender Rao 
938d1b46d7Szhanghch05 inline std::string getCertificateFromReqBody(
948d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
9558eb238fSKowalski, Kamil     const crow::Request& req)
9658eb238fSKowalski, Kamil {
9758eb238fSKowalski, Kamil     nlohmann::json reqJson = nlohmann::json::parse(req.body, nullptr, false);
9858eb238fSKowalski, Kamil 
9958eb238fSKowalski, Kamil     if (reqJson.is_discarded())
10058eb238fSKowalski, Kamil     {
10158eb238fSKowalski, Kamil         // We did not receive JSON request, proceed as it is RAW data
10258eb238fSKowalski, Kamil         return req.body;
10358eb238fSKowalski, Kamil     }
10458eb238fSKowalski, Kamil 
10558eb238fSKowalski, Kamil     std::string certificate;
10658eb238fSKowalski, Kamil     std::optional<std::string> certificateType = "PEM";
10758eb238fSKowalski, Kamil 
10815ed6780SWilly Tu     if (!json_util::readJsonPatch(req, asyncResp->res, "CertificateString",
10915ed6780SWilly Tu                                   certificate, "CertificateType",
11015ed6780SWilly Tu                                   certificateType))
11158eb238fSKowalski, Kamil     {
11258eb238fSKowalski, Kamil         BMCWEB_LOG_ERROR << "Required parameters are missing";
11358eb238fSKowalski, Kamil         messages::internalError(asyncResp->res);
114abb93cddSEd Tanous         return {};
11558eb238fSKowalski, Kamil     }
11658eb238fSKowalski, Kamil 
11758eb238fSKowalski, Kamil     if (*certificateType != "PEM")
11858eb238fSKowalski, Kamil     {
11958eb238fSKowalski, Kamil         messages::propertyValueNotInList(asyncResp->res, *certificateType,
12058eb238fSKowalski, Kamil                                          "CertificateType");
121abb93cddSEd Tanous         return {};
12258eb238fSKowalski, Kamil     }
12358eb238fSKowalski, Kamil 
12458eb238fSKowalski, Kamil     return certificate;
12558eb238fSKowalski, Kamil }
12658eb238fSKowalski, Kamil 
1275968caeeSMarri Devender Rao /**
1285968caeeSMarri Devender Rao  * Class to create a temporary certificate file for uploading to system
1295968caeeSMarri Devender Rao  */
1305968caeeSMarri Devender Rao class CertificateFile
1315968caeeSMarri Devender Rao {
1325968caeeSMarri Devender Rao   public:
1335968caeeSMarri Devender Rao     CertificateFile() = delete;
1345968caeeSMarri Devender Rao     CertificateFile(const CertificateFile&) = delete;
1355968caeeSMarri Devender Rao     CertificateFile& operator=(const CertificateFile&) = delete;
1365968caeeSMarri Devender Rao     CertificateFile(CertificateFile&&) = delete;
1375968caeeSMarri Devender Rao     CertificateFile& operator=(CertificateFile&&) = delete;
1384e23a444SEd Tanous     explicit CertificateFile(const std::string& certString)
1395968caeeSMarri Devender Rao     {
14072d52d25SEd Tanous         std::array<char, 18> dirTemplate = {'/', 't', 'm', 'p', '/', 'C',
1415207438cSEd Tanous                                             'e', 'r', 't', 's', '.', 'X',
1425207438cSEd Tanous                                             'X', 'X', 'X', 'X', 'X', '\0'};
1435207438cSEd Tanous         char* tempDirectory = mkdtemp(dirTemplate.data());
144e662eae8SEd Tanous         if (tempDirectory != nullptr)
1455968caeeSMarri Devender Rao         {
1465968caeeSMarri Devender Rao             certDirectory = tempDirectory;
1475968caeeSMarri Devender Rao             certificateFile = certDirectory / "cert.pem";
1485968caeeSMarri Devender Rao             std::ofstream out(certificateFile, std::ofstream::out |
1495968caeeSMarri Devender Rao                                                    std::ofstream::binary |
1505968caeeSMarri Devender Rao                                                    std::ofstream::trunc);
1515968caeeSMarri Devender Rao             out << certString;
1525968caeeSMarri Devender Rao             out.close();
1538cc8edecSEd Tanous             BMCWEB_LOG_DEBUG << "Creating certificate file"
1548cc8edecSEd Tanous                              << certificateFile.string();
1555968caeeSMarri Devender Rao         }
1565968caeeSMarri Devender Rao     }
1575968caeeSMarri Devender Rao     ~CertificateFile()
1585968caeeSMarri Devender Rao     {
1595968caeeSMarri Devender Rao         if (std::filesystem::exists(certDirectory))
1605968caeeSMarri Devender Rao         {
1618cc8edecSEd Tanous             BMCWEB_LOG_DEBUG << "Removing certificate file"
1628cc8edecSEd Tanous                              << certificateFile.string();
16323a21a1cSEd Tanous             std::error_code ec;
16423a21a1cSEd Tanous             std::filesystem::remove_all(certDirectory, ec);
16523a21a1cSEd Tanous             if (ec)
1665968caeeSMarri Devender Rao             {
1675968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "Failed to remove temp directory"
1688cc8edecSEd Tanous                                  << certDirectory.string();
1695968caeeSMarri Devender Rao             }
1705968caeeSMarri Devender Rao         }
1715968caeeSMarri Devender Rao     }
1725968caeeSMarri Devender Rao     std::string getCertFilePath()
1735968caeeSMarri Devender Rao     {
1745968caeeSMarri Devender Rao         return certificateFile;
1755968caeeSMarri Devender Rao     }
1765968caeeSMarri Devender Rao 
1775968caeeSMarri Devender Rao   private:
1785968caeeSMarri Devender Rao     std::filesystem::path certificateFile;
1795968caeeSMarri Devender Rao     std::filesystem::path certDirectory;
1805968caeeSMarri Devender Rao };
1815968caeeSMarri Devender Rao 
18259d494eeSPatrick Williams static std::unique_ptr<sdbusplus::bus::match_t> csrMatcher;
18330215816SMarri Devender Rao /**
18430215816SMarri Devender Rao  * @brief Read data from CSR D-bus object and set to response
18530215816SMarri Devender Rao  *
18630215816SMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
18730215816SMarri Devender Rao  * @param[in] certURI Link to certifiate collection URI
18830215816SMarri Devender Rao  * @param[in] service D-Bus service name
18930215816SMarri Devender Rao  * @param[in] certObjPath certificate D-Bus object path
19030215816SMarri Devender Rao  * @param[in] csrObjPath CSR D-Bus object path
19130215816SMarri Devender Rao  * @return None
19230215816SMarri Devender Rao  */
1938d1b46d7Szhanghch05 static void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
19430215816SMarri Devender Rao                    const std::string& certURI, const std::string& service,
19530215816SMarri Devender Rao                    const std::string& certObjPath,
19630215816SMarri Devender Rao                    const std::string& csrObjPath)
19730215816SMarri Devender Rao {
19830215816SMarri Devender Rao     BMCWEB_LOG_DEBUG << "getCSR CertObjectPath" << certObjPath
19930215816SMarri Devender Rao                      << " CSRObjectPath=" << csrObjPath
20030215816SMarri Devender Rao                      << " service=" << service;
20130215816SMarri Devender Rao     crow::connections::systemBus->async_method_call(
20230215816SMarri Devender Rao         [asyncResp, certURI](const boost::system::error_code ec,
20330215816SMarri Devender Rao                              const std::string& csr) {
20430215816SMarri Devender Rao         if (ec)
20530215816SMarri Devender Rao         {
20630215816SMarri Devender Rao             BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
20730215816SMarri Devender Rao             messages::internalError(asyncResp->res);
20830215816SMarri Devender Rao             return;
20930215816SMarri Devender Rao         }
21030215816SMarri Devender Rao         if (csr.empty())
21130215816SMarri Devender Rao         {
21230215816SMarri Devender Rao             BMCWEB_LOG_ERROR << "CSR read is empty";
21330215816SMarri Devender Rao             messages::internalError(asyncResp->res);
21430215816SMarri Devender Rao             return;
21530215816SMarri Devender Rao         }
21630215816SMarri Devender Rao         asyncResp->res.jsonValue["CSRString"] = csr;
2171476687dSEd Tanous         asyncResp->res.jsonValue["CertificateCollection"]["@odata.id"] =
2181476687dSEd Tanous             certURI;
21930215816SMarri Devender Rao         },
22030215816SMarri Devender Rao         service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR");
22130215816SMarri Devender Rao }
22230215816SMarri Devender Rao 
22330215816SMarri Devender Rao /**
22430215816SMarri Devender Rao  * Action to Generate CSR
22530215816SMarri Devender Rao  */
2267e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionGenerateCSR(App& app)
22730215816SMarri Devender Rao {
2280fda0f12SGeorge Liu     BMCWEB_ROUTE(
2290fda0f12SGeorge Liu         app,
2300fda0f12SGeorge Liu         "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR/")
2315344ab8eSAbhishek Patel         .privileges(redfish::privileges::postCertificateService)
232002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
233002d39b4SEd Tanous             [&app](const crow::Request& req,
2347e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2353ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
23645ca1b86SEd Tanous         {
23745ca1b86SEd Tanous             return;
23845ca1b86SEd Tanous         }
2392c70f800SEd Tanous         static const int rsaKeyBitLength = 2048;
2408d1b46d7Szhanghch05 
24130215816SMarri Devender Rao         // Required parameters
24230215816SMarri Devender Rao         std::string city;
24330215816SMarri Devender Rao         std::string commonName;
24430215816SMarri Devender Rao         std::string country;
24530215816SMarri Devender Rao         std::string organization;
24630215816SMarri Devender Rao         std::string organizationalUnit;
24730215816SMarri Devender Rao         std::string state;
24830215816SMarri Devender Rao         nlohmann::json certificateCollection;
24930215816SMarri Devender Rao 
25030215816SMarri Devender Rao         // Optional parameters
25130215816SMarri Devender Rao         std::optional<std::vector<std::string>> optAlternativeNames =
25230215816SMarri Devender Rao             std::vector<std::string>();
25330215816SMarri Devender Rao         std::optional<std::string> optContactPerson = "";
25430215816SMarri Devender Rao         std::optional<std::string> optChallengePassword = "";
25530215816SMarri Devender Rao         std::optional<std::string> optEmail = "";
25630215816SMarri Devender Rao         std::optional<std::string> optGivenName = "";
25730215816SMarri Devender Rao         std::optional<std::string> optInitials = "";
2582c70f800SEd Tanous         std::optional<int64_t> optKeyBitLength = rsaKeyBitLength;
259aaf3206fSVernon Mauery         std::optional<std::string> optKeyCurveId = "secp384r1";
26030215816SMarri Devender Rao         std::optional<std::string> optKeyPairAlgorithm = "EC";
26130215816SMarri Devender Rao         std::optional<std::vector<std::string>> optKeyUsage =
26230215816SMarri Devender Rao             std::vector<std::string>();
26330215816SMarri Devender Rao         std::optional<std::string> optSurname = "";
26430215816SMarri Devender Rao         std::optional<std::string> optUnstructuredName = "";
26515ed6780SWilly Tu         if (!json_util::readJsonAction(
2660fda0f12SGeorge Liu                 req, asyncResp->res, "City", city, "CommonName", commonName,
2670fda0f12SGeorge Liu                 "ContactPerson", optContactPerson, "Country", country,
2680fda0f12SGeorge Liu                 "Organization", organization, "OrganizationalUnit",
2690fda0f12SGeorge Liu                 organizationalUnit, "State", state, "CertificateCollection",
270002d39b4SEd Tanous                 certificateCollection, "AlternativeNames", optAlternativeNames,
271002d39b4SEd Tanous                 "ChallengePassword", optChallengePassword, "Email", optEmail,
272002d39b4SEd Tanous                 "GivenName", optGivenName, "Initials", optInitials,
273002d39b4SEd Tanous                 "KeyBitLength", optKeyBitLength, "KeyCurveId", optKeyCurveId,
2740fda0f12SGeorge Liu                 "KeyPairAlgorithm", optKeyPairAlgorithm, "KeyUsage",
2750fda0f12SGeorge Liu                 optKeyUsage, "Surname", optSurname, "UnstructuredName",
2760fda0f12SGeorge Liu                 optUnstructuredName))
27730215816SMarri Devender Rao         {
27830215816SMarri Devender Rao             return;
27930215816SMarri Devender Rao         }
28030215816SMarri Devender Rao 
28130215816SMarri Devender Rao         // bmcweb has no way to store or decode a private key challenge
2827e860f15SJohn Edward Broadbent         // password, which will likely cause bmcweb to crash on startup
2837e860f15SJohn Edward Broadbent         // if this is not set on a post so not allowing the user to set
2847e860f15SJohn Edward Broadbent         // value
28526f6976fSEd Tanous         if (!optChallengePassword->empty())
28630215816SMarri Devender Rao         {
287002d39b4SEd Tanous             messages::actionParameterNotSupported(asyncResp->res, "GenerateCSR",
288002d39b4SEd Tanous                                                   "ChallengePassword");
28930215816SMarri Devender Rao             return;
29030215816SMarri Devender Rao         }
29130215816SMarri Devender Rao 
29230215816SMarri Devender Rao         std::string certURI;
293002d39b4SEd Tanous         if (!redfish::json_util::readJson(certificateCollection, asyncResp->res,
294002d39b4SEd Tanous                                           "@odata.id", certURI))
29530215816SMarri Devender Rao         {
29630215816SMarri Devender Rao             return;
29730215816SMarri Devender Rao         }
29830215816SMarri Devender Rao 
29930215816SMarri Devender Rao         std::string objectPath;
30030215816SMarri Devender Rao         std::string service;
30111ba3979SEd Tanous         if (certURI.starts_with(
3020fda0f12SGeorge Liu                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"))
30330215816SMarri Devender Rao         {
30430215816SMarri Devender Rao             objectPath = certs::httpsObjectPath;
30530215816SMarri Devender Rao             service = certs::httpsServiceName;
30630215816SMarri Devender Rao         }
30711ba3979SEd Tanous         else if (certURI.starts_with(
30811ba3979SEd Tanous                      "/redfish/v1/AccountService/LDAP/Certificates"))
3093b7f0149SMarri Devender Rao         {
3103b7f0149SMarri Devender Rao             objectPath = certs::ldapObjectPath;
3113b7f0149SMarri Devender Rao             service = certs::ldapServiceName;
3123b7f0149SMarri Devender Rao         }
31330215816SMarri Devender Rao         else
31430215816SMarri Devender Rao         {
31530215816SMarri Devender Rao             messages::actionParameterNotSupported(
31630215816SMarri Devender Rao                 asyncResp->res, "CertificateCollection", "GenerateCSR");
31730215816SMarri Devender Rao             return;
31830215816SMarri Devender Rao         }
31930215816SMarri Devender Rao 
32030215816SMarri Devender Rao         // supporting only EC and RSA algorithm
3210fda0f12SGeorge Liu         if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA")
32230215816SMarri Devender Rao         {
32330215816SMarri Devender Rao             messages::actionParameterNotSupported(
32430215816SMarri Devender Rao                 asyncResp->res, "KeyPairAlgorithm", "GenerateCSR");
32530215816SMarri Devender Rao             return;
32630215816SMarri Devender Rao         }
32730215816SMarri Devender Rao 
3287e860f15SJohn Edward Broadbent         // supporting only 2048 key bit length for RSA algorithm due to
3297e860f15SJohn Edward Broadbent         // time consumed in generating private key
33030215816SMarri Devender Rao         if (*optKeyPairAlgorithm == "RSA" &&
3312c70f800SEd Tanous             *optKeyBitLength != rsaKeyBitLength)
33230215816SMarri Devender Rao         {
333002d39b4SEd Tanous             messages::propertyValueNotInList(asyncResp->res,
334002d39b4SEd Tanous                                              std::to_string(*optKeyBitLength),
33530215816SMarri Devender Rao                                              "KeyBitLength");
33630215816SMarri Devender Rao             return;
33730215816SMarri Devender Rao         }
33830215816SMarri Devender Rao 
33930215816SMarri Devender Rao         // validate KeyUsage supporting only 1 type based on URL
34011ba3979SEd Tanous         if (certURI.starts_with(
3410fda0f12SGeorge Liu                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"))
34230215816SMarri Devender Rao         {
34326f6976fSEd Tanous             if (optKeyUsage->empty())
34430215816SMarri Devender Rao             {
34530215816SMarri Devender Rao                 optKeyUsage->push_back("ServerAuthentication");
34630215816SMarri Devender Rao             }
34730215816SMarri Devender Rao             else if (optKeyUsage->size() == 1)
34830215816SMarri Devender Rao             {
34930215816SMarri Devender Rao                 if ((*optKeyUsage)[0] != "ServerAuthentication")
35030215816SMarri Devender Rao                 {
35130215816SMarri Devender Rao                     messages::propertyValueNotInList(
35230215816SMarri Devender Rao                         asyncResp->res, (*optKeyUsage)[0], "KeyUsage");
35330215816SMarri Devender Rao                     return;
35430215816SMarri Devender Rao                 }
35530215816SMarri Devender Rao             }
35630215816SMarri Devender Rao             else
35730215816SMarri Devender Rao             {
35830215816SMarri Devender Rao                 messages::actionParameterNotSupported(
35930215816SMarri Devender Rao                     asyncResp->res, "KeyUsage", "GenerateCSR");
36030215816SMarri Devender Rao                 return;
36130215816SMarri Devender Rao             }
36230215816SMarri Devender Rao         }
36311ba3979SEd Tanous         else if (certURI.starts_with(
36411ba3979SEd Tanous                      "/redfish/v1/AccountService/LDAP/Certificates"))
3653b7f0149SMarri Devender Rao         {
36626f6976fSEd Tanous             if (optKeyUsage->empty())
3673b7f0149SMarri Devender Rao             {
3683b7f0149SMarri Devender Rao                 optKeyUsage->push_back("ClientAuthentication");
3693b7f0149SMarri Devender Rao             }
3703b7f0149SMarri Devender Rao             else if (optKeyUsage->size() == 1)
3713b7f0149SMarri Devender Rao             {
3723b7f0149SMarri Devender Rao                 if ((*optKeyUsage)[0] != "ClientAuthentication")
3733b7f0149SMarri Devender Rao                 {
3743b7f0149SMarri Devender Rao                     messages::propertyValueNotInList(
3753b7f0149SMarri Devender Rao                         asyncResp->res, (*optKeyUsage)[0], "KeyUsage");
3763b7f0149SMarri Devender Rao                     return;
3773b7f0149SMarri Devender Rao                 }
3783b7f0149SMarri Devender Rao             }
3793b7f0149SMarri Devender Rao             else
3803b7f0149SMarri Devender Rao             {
3813b7f0149SMarri Devender Rao                 messages::actionParameterNotSupported(
3823b7f0149SMarri Devender Rao                     asyncResp->res, "KeyUsage", "GenerateCSR");
3833b7f0149SMarri Devender Rao                 return;
3843b7f0149SMarri Devender Rao             }
3853b7f0149SMarri Devender Rao         }
38630215816SMarri Devender Rao 
3877e860f15SJohn Edward Broadbent         // Only allow one CSR matcher at a time so setting retry
3887e860f15SJohn Edward Broadbent         // time-out and timer expiry to 10 seconds for now.
3892c70f800SEd Tanous         static const int timeOut = 10;
39030215816SMarri Devender Rao         if (csrMatcher)
39130215816SMarri Devender Rao         {
392002d39b4SEd Tanous             messages::serviceTemporarilyUnavailable(asyncResp->res,
393002d39b4SEd Tanous                                                     std::to_string(timeOut));
39430215816SMarri Devender Rao             return;
39530215816SMarri Devender Rao         }
39630215816SMarri Devender Rao 
39730215816SMarri Devender Rao         // Make this static so it survives outside this method
39830215816SMarri Devender Rao         static boost::asio::steady_timer timeout(*req.ioService);
3992c70f800SEd Tanous         timeout.expires_after(std::chrono::seconds(timeOut));
400002d39b4SEd Tanous         timeout.async_wait([asyncResp](const boost::system::error_code& ec) {
40130215816SMarri Devender Rao             csrMatcher = nullptr;
40230215816SMarri Devender Rao             if (ec)
40330215816SMarri Devender Rao             {
4047e860f15SJohn Edward Broadbent                 // operation_aborted is expected if timer is canceled
4057e860f15SJohn Edward Broadbent                 // before completion.
40630215816SMarri Devender Rao                 if (ec != boost::asio::error::operation_aborted)
40730215816SMarri Devender Rao                 {
40830215816SMarri Devender Rao                     BMCWEB_LOG_ERROR << "Async_wait failed " << ec;
40930215816SMarri Devender Rao                 }
41030215816SMarri Devender Rao                 return;
41130215816SMarri Devender Rao             }
41230215816SMarri Devender Rao             BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR";
41330215816SMarri Devender Rao             messages::internalError(asyncResp->res);
41430215816SMarri Devender Rao         });
41530215816SMarri Devender Rao 
41630215816SMarri Devender Rao         // create a matcher to wait on CSR object
41730215816SMarri Devender Rao         BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath;
4180fda0f12SGeorge Liu         std::string match("type='signal',"
41930215816SMarri Devender Rao                           "interface='org.freedesktop.DBus.ObjectManager',"
42030215816SMarri Devender Rao                           "path='" +
42130215816SMarri Devender Rao                           objectPath +
42230215816SMarri Devender Rao                           "',"
42330215816SMarri Devender Rao                           "member='InterfacesAdded'");
42459d494eeSPatrick Williams         csrMatcher = std::make_unique<sdbusplus::bus::match_t>(
42530215816SMarri Devender Rao             *crow::connections::systemBus, match,
42659d494eeSPatrick Williams             [asyncResp, service, objectPath, certURI](sdbusplus::message_t& m) {
427271584abSEd Tanous             timeout.cancel();
42830215816SMarri Devender Rao             if (m.is_method_error())
42930215816SMarri Devender Rao             {
43030215816SMarri Devender Rao                 BMCWEB_LOG_ERROR << "Dbus method error!!!";
43130215816SMarri Devender Rao                 messages::internalError(asyncResp->res);
43230215816SMarri Devender Rao                 return;
43330215816SMarri Devender Rao             }
434b9d36b47SEd Tanous 
435b9d36b47SEd Tanous             dbus::utility::DBusInteracesMap interfacesProperties;
436b9d36b47SEd Tanous 
43730215816SMarri Devender Rao             sdbusplus::message::object_path csrObjectPath;
43830215816SMarri Devender Rao             m.read(csrObjectPath, interfacesProperties);
4390fda0f12SGeorge Liu             BMCWEB_LOG_DEBUG << "CSR object added" << csrObjectPath.str;
44002cad96eSEd Tanous             for (const auto& interface : interfacesProperties)
44130215816SMarri Devender Rao             {
4420fda0f12SGeorge Liu                 if (interface.first == "xyz.openbmc_project.Certs.CSR")
44330215816SMarri Devender Rao                 {
44430215816SMarri Devender Rao                     getCSR(asyncResp, certURI, service, objectPath,
44530215816SMarri Devender Rao                            csrObjectPath.str);
44630215816SMarri Devender Rao                     break;
44730215816SMarri Devender Rao                 }
44830215816SMarri Devender Rao             }
44930215816SMarri Devender Rao             });
45030215816SMarri Devender Rao         crow::connections::systemBus->async_method_call(
451914e2d5dSEd Tanous             [asyncResp](const boost::system::error_code ec,
452cb13a392SEd Tanous                         const std::string&) {
45330215816SMarri Devender Rao             if (ec)
45430215816SMarri Devender Rao             {
455002d39b4SEd Tanous                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec.message();
45630215816SMarri Devender Rao                 messages::internalError(asyncResp->res);
45730215816SMarri Devender Rao                 return;
45830215816SMarri Devender Rao             }
45930215816SMarri Devender Rao             },
46030215816SMarri Devender Rao             service, objectPath, "xyz.openbmc_project.Certs.CSR.Create",
461002d39b4SEd Tanous             "GenerateCSR", *optAlternativeNames, *optChallengePassword, city,
462002d39b4SEd Tanous             commonName, *optContactPerson, country, *optEmail, *optGivenName,
463002d39b4SEd Tanous             *optInitials, *optKeyBitLength, *optKeyCurveId,
4640fda0f12SGeorge Liu             *optKeyPairAlgorithm, *optKeyUsage, organization,
4650fda0f12SGeorge Liu             organizationalUnit, state, *optSurname, *optUnstructuredName);
4667e860f15SJohn Edward Broadbent         });
4677e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionGenerateCSR
46830215816SMarri Devender Rao 
4695968caeeSMarri Devender Rao /**
4704e0453b1SGunnar Mills  * @brief Parse and update Certificate Issue/Subject property
4715968caeeSMarri Devender Rao  *
4725968caeeSMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
4735968caeeSMarri Devender Rao  * @param[in] str  Issuer/Subject value in key=value pairs
4745968caeeSMarri Devender Rao  * @param[in] type Issuer/Subject
4755968caeeSMarri Devender Rao  * @return None
4765968caeeSMarri Devender Rao  */
4775968caeeSMarri Devender Rao static void updateCertIssuerOrSubject(nlohmann::json& out,
4785968caeeSMarri Devender Rao                                       const std::string_view value)
4795968caeeSMarri Devender Rao {
4805968caeeSMarri Devender Rao     // example: O=openbmc-project.xyz,CN=localhost
4815968caeeSMarri Devender Rao     std::string_view::iterator i = value.begin();
4825968caeeSMarri Devender Rao     while (i != value.end())
4835968caeeSMarri Devender Rao     {
4845968caeeSMarri Devender Rao         std::string_view::iterator tokenBegin = i;
4855968caeeSMarri Devender Rao         while (i != value.end() && *i != '=')
4865968caeeSMarri Devender Rao         {
48717a897dfSManojkiran Eda             ++i;
4885968caeeSMarri Devender Rao         }
4895968caeeSMarri Devender Rao         if (i == value.end())
4905968caeeSMarri Devender Rao         {
4915968caeeSMarri Devender Rao             break;
4925968caeeSMarri Devender Rao         }
493271584abSEd Tanous         const std::string_view key(tokenBegin,
494271584abSEd Tanous                                    static_cast<size_t>(i - tokenBegin));
49517a897dfSManojkiran Eda         ++i;
4965968caeeSMarri Devender Rao         tokenBegin = i;
4975968caeeSMarri Devender Rao         while (i != value.end() && *i != ',')
4985968caeeSMarri Devender Rao         {
49917a897dfSManojkiran Eda             ++i;
5005968caeeSMarri Devender Rao         }
501271584abSEd Tanous         const std::string_view val(tokenBegin,
502271584abSEd Tanous                                    static_cast<size_t>(i - tokenBegin));
5035968caeeSMarri Devender Rao         if (key == "L")
5045968caeeSMarri Devender Rao         {
5055968caeeSMarri Devender Rao             out["City"] = val;
5065968caeeSMarri Devender Rao         }
5075968caeeSMarri Devender Rao         else if (key == "CN")
5085968caeeSMarri Devender Rao         {
5095968caeeSMarri Devender Rao             out["CommonName"] = val;
5105968caeeSMarri Devender Rao         }
5115968caeeSMarri Devender Rao         else if (key == "C")
5125968caeeSMarri Devender Rao         {
5135968caeeSMarri Devender Rao             out["Country"] = val;
5145968caeeSMarri Devender Rao         }
5155968caeeSMarri Devender Rao         else if (key == "O")
5165968caeeSMarri Devender Rao         {
5175968caeeSMarri Devender Rao             out["Organization"] = val;
5185968caeeSMarri Devender Rao         }
5195968caeeSMarri Devender Rao         else if (key == "OU")
5205968caeeSMarri Devender Rao         {
5215968caeeSMarri Devender Rao             out["OrganizationalUnit"] = val;
5225968caeeSMarri Devender Rao         }
5235968caeeSMarri Devender Rao         else if (key == "ST")
5245968caeeSMarri Devender Rao         {
5255968caeeSMarri Devender Rao             out["State"] = val;
5265968caeeSMarri Devender Rao         }
5275968caeeSMarri Devender Rao         // skip comma character
5285968caeeSMarri Devender Rao         if (i != value.end())
5295968caeeSMarri Devender Rao         {
53017a897dfSManojkiran Eda             ++i;
5315968caeeSMarri Devender Rao         }
5325968caeeSMarri Devender Rao     }
5335968caeeSMarri Devender Rao }
5345968caeeSMarri Devender Rao 
5355968caeeSMarri Devender Rao /**
536d3f92ce7SJiaqing Zhao  * @brief Retrieve the installed certificate list
537d3f92ce7SJiaqing Zhao  *
538d3f92ce7SJiaqing Zhao  * @param[in] asyncResp Shared pointer to the response message
539d3f92ce7SJiaqing Zhao  * @param[in] basePath DBus object path to search
540d3f92ce7SJiaqing Zhao  * @param[in] listPtr Json pointer to the list in asyncResp
541d3f92ce7SJiaqing Zhao  * @param[in] countPtr Json pointer to the count in asyncResp
542d3f92ce7SJiaqing Zhao  * @return None
543d3f92ce7SJiaqing Zhao  */
544d3f92ce7SJiaqing Zhao static void
545d3f92ce7SJiaqing Zhao     getCertificateList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
546d3f92ce7SJiaqing Zhao                        const std::string& basePath,
547d3f92ce7SJiaqing Zhao                        const nlohmann::json::json_pointer& listPtr,
548d3f92ce7SJiaqing Zhao                        const nlohmann::json::json_pointer& countPtr)
549d3f92ce7SJiaqing Zhao {
550d3f92ce7SJiaqing Zhao     crow::connections::systemBus->async_method_call(
551d3f92ce7SJiaqing Zhao         [asyncResp, listPtr, countPtr](
552d3f92ce7SJiaqing Zhao             const boost::system::error_code ec,
553d3f92ce7SJiaqing Zhao             const dbus::utility::MapperGetSubTreePathsResponse& certPaths) {
554d3f92ce7SJiaqing Zhao         if (ec)
555d3f92ce7SJiaqing Zhao         {
556d3f92ce7SJiaqing Zhao             BMCWEB_LOG_ERROR << "Certificate collection query failed: " << ec;
557d3f92ce7SJiaqing Zhao             messages::internalError(asyncResp->res);
558d3f92ce7SJiaqing Zhao             return;
559d3f92ce7SJiaqing Zhao         }
560d3f92ce7SJiaqing Zhao 
561d3f92ce7SJiaqing Zhao         nlohmann::json& links = asyncResp->res.jsonValue[listPtr];
562d3f92ce7SJiaqing Zhao         links = nlohmann::json::array();
563d3f92ce7SJiaqing Zhao         for (const auto& certPath : certPaths)
564d3f92ce7SJiaqing Zhao         {
565d3f92ce7SJiaqing Zhao             sdbusplus::message::object_path objPath(certPath);
566d3f92ce7SJiaqing Zhao             std::string certId = objPath.filename();
567d3f92ce7SJiaqing Zhao             if (certId.empty())
568d3f92ce7SJiaqing Zhao             {
569d3f92ce7SJiaqing Zhao                 BMCWEB_LOG_ERROR << "Invalid certificate objPath " << certPath;
570d3f92ce7SJiaqing Zhao                 continue;
571d3f92ce7SJiaqing Zhao             }
572d3f92ce7SJiaqing Zhao 
573d3f92ce7SJiaqing Zhao             boost::urls::url certURL;
574d3f92ce7SJiaqing Zhao             if (objPath.parent_path() == certs::httpsObjectPath)
575d3f92ce7SJiaqing Zhao             {
576d3f92ce7SJiaqing Zhao                 certURL = crow::utility::urlFromPieces(
577d3f92ce7SJiaqing Zhao                     "redfish", "v1", "Managers", "bmc", "NetworkProtocol",
578d3f92ce7SJiaqing Zhao                     "HTTPS", "Certificates", certId);
579d3f92ce7SJiaqing Zhao             }
580d3f92ce7SJiaqing Zhao             else if (objPath.parent_path() == certs::ldapObjectPath)
581d3f92ce7SJiaqing Zhao             {
582d3f92ce7SJiaqing Zhao                 certURL = crow::utility::urlFromPieces("redfish", "v1",
583d3f92ce7SJiaqing Zhao                                                        "AccountService", "LDAP",
584d3f92ce7SJiaqing Zhao                                                        "Certificates", certId);
585d3f92ce7SJiaqing Zhao             }
586d3f92ce7SJiaqing Zhao             else if (objPath.parent_path() == certs::authorityObjectPath)
587d3f92ce7SJiaqing Zhao             {
588d3f92ce7SJiaqing Zhao                 certURL = crow::utility::urlFromPieces(
589d3f92ce7SJiaqing Zhao                     "redfish", "v1", "Managers", "bmc", "Truststore",
590d3f92ce7SJiaqing Zhao                     "Certificates", certId);
591d3f92ce7SJiaqing Zhao             }
592d3f92ce7SJiaqing Zhao             else
593d3f92ce7SJiaqing Zhao             {
594d3f92ce7SJiaqing Zhao                 continue;
595d3f92ce7SJiaqing Zhao             }
596d3f92ce7SJiaqing Zhao 
597d3f92ce7SJiaqing Zhao             nlohmann::json::object_t link;
598d3f92ce7SJiaqing Zhao             link["@odata.id"] = certURL;
599d3f92ce7SJiaqing Zhao             links.emplace_back(std::move(link));
600d3f92ce7SJiaqing Zhao         }
601d3f92ce7SJiaqing Zhao 
602d3f92ce7SJiaqing Zhao         asyncResp->res.jsonValue[countPtr] = links.size();
603d3f92ce7SJiaqing Zhao         },
604d3f92ce7SJiaqing Zhao         "xyz.openbmc_project.ObjectMapper",
605d3f92ce7SJiaqing Zhao         "/xyz/openbmc_project/object_mapper",
606d3f92ce7SJiaqing Zhao         "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", basePath, 0,
607d3f92ce7SJiaqing Zhao         std::array<const char*, 1>{certs::certPropIntf});
608d3f92ce7SJiaqing Zhao }
609d3f92ce7SJiaqing Zhao 
610d3f92ce7SJiaqing Zhao /**
6115968caeeSMarri Devender Rao  * @brief Retrieve the certificates properties and append to the response
6125968caeeSMarri Devender Rao  * message
6135968caeeSMarri Devender Rao  *
6145968caeeSMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
6155968caeeSMarri Devender Rao  * @param[in] objectPath  Path of the D-Bus service object
6165968caeeSMarri Devender Rao  * @param[in] certId  Id of the certificate
6175968caeeSMarri Devender Rao  * @param[in] certURL  URL of the certificate object
6185968caeeSMarri Devender Rao  * @param[in] name  name of the certificate
6195968caeeSMarri Devender Rao  * @return None
6205968caeeSMarri Devender Rao  */
6215968caeeSMarri Devender Rao static void getCertificateProperties(
6228d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
623e19e97e2SJiaqing Zhao     const std::string& objectPath, const std::string& service,
6241e312598SJiaqing Zhao     const std::string& certId, const boost::urls::url& certURL,
625e19e97e2SJiaqing Zhao     const std::string& name)
6265968caeeSMarri Devender Rao {
6275968caeeSMarri Devender Rao     BMCWEB_LOG_DEBUG << "getCertificateProperties Path=" << objectPath
6285968caeeSMarri Devender Rao                      << " certId=" << certId << " certURl=" << certURL;
629*9b12d1f9SKrzysztof Grobelny     sdbusplus::asio::getAllProperties(
630*9b12d1f9SKrzysztof Grobelny         *crow::connections::systemBus, service, objectPath, certs::certPropIntf,
631b9d36b47SEd Tanous         [asyncResp, certURL, certId,
632b9d36b47SEd Tanous          name](const boost::system::error_code ec,
633b9d36b47SEd Tanous                const dbus::utility::DBusPropertiesMap& properties) {
6345968caeeSMarri Devender Rao         if (ec)
6355968caeeSMarri Devender Rao         {
6365968caeeSMarri Devender Rao             BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
637e19e97e2SJiaqing Zhao             messages::resourceNotFound(asyncResp->res, name, certId);
6385968caeeSMarri Devender Rao             return;
6395968caeeSMarri Devender Rao         }
640*9b12d1f9SKrzysztof Grobelny 
641*9b12d1f9SKrzysztof Grobelny         const std::string* certificateString = nullptr;
642*9b12d1f9SKrzysztof Grobelny         const std::vector<std::string>* keyUsage = nullptr;
643*9b12d1f9SKrzysztof Grobelny         const std::string* issuer = nullptr;
644*9b12d1f9SKrzysztof Grobelny         const std::string* subject = nullptr;
645*9b12d1f9SKrzysztof Grobelny         const uint64_t* validNotAfter = nullptr;
646*9b12d1f9SKrzysztof Grobelny         const uint64_t* validNotBefore = nullptr;
647*9b12d1f9SKrzysztof Grobelny 
648*9b12d1f9SKrzysztof Grobelny         const bool success = sdbusplus::unpackPropertiesNoThrow(
649*9b12d1f9SKrzysztof Grobelny             dbus_utils::UnpackErrorPrinter(), properties, "CertificateString",
650*9b12d1f9SKrzysztof Grobelny             certificateString, "KeyUsage", keyUsage, "Issuer", issuer,
651*9b12d1f9SKrzysztof Grobelny             "Subject", subject, "ValidNotAfter", validNotAfter,
652*9b12d1f9SKrzysztof Grobelny             "ValidNotBefore", validNotBefore);
653*9b12d1f9SKrzysztof Grobelny 
654*9b12d1f9SKrzysztof Grobelny         if (!success)
655*9b12d1f9SKrzysztof Grobelny         {
656*9b12d1f9SKrzysztof Grobelny             messages::internalError(asyncResp->res);
657*9b12d1f9SKrzysztof Grobelny             return;
658*9b12d1f9SKrzysztof Grobelny         }
659*9b12d1f9SKrzysztof Grobelny 
6601476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] = certURL;
6611476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
6621476687dSEd Tanous             "#Certificate.v1_0_0.Certificate";
663e19e97e2SJiaqing Zhao         asyncResp->res.jsonValue["Id"] = certId;
6641476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = name;
6651476687dSEd Tanous         asyncResp->res.jsonValue["Description"] = name;
6665968caeeSMarri Devender Rao         asyncResp->res.jsonValue["CertificateString"] = "";
667*9b12d1f9SKrzysztof Grobelny         asyncResp->res.jsonValue["KeyUsage"] = nlohmann::json::array();
668*9b12d1f9SKrzysztof Grobelny 
669*9b12d1f9SKrzysztof Grobelny         if (certificateString != nullptr)
6705968caeeSMarri Devender Rao         {
671*9b12d1f9SKrzysztof Grobelny             asyncResp->res.jsonValue["CertificateString"] = *certificateString;
6725968caeeSMarri Devender Rao         }
673*9b12d1f9SKrzysztof Grobelny 
674*9b12d1f9SKrzysztof Grobelny         if (keyUsage != nullptr)
6755968caeeSMarri Devender Rao         {
676*9b12d1f9SKrzysztof Grobelny             asyncResp->res.jsonValue["KeyUsage"] = *keyUsage;
6775968caeeSMarri Devender Rao         }
678*9b12d1f9SKrzysztof Grobelny 
679*9b12d1f9SKrzysztof Grobelny         if (issuer != nullptr)
6805968caeeSMarri Devender Rao         {
681*9b12d1f9SKrzysztof Grobelny             updateCertIssuerOrSubject(asyncResp->res.jsonValue["Issuer"],
682*9b12d1f9SKrzysztof Grobelny                                       *issuer);
6835968caeeSMarri Devender Rao         }
684*9b12d1f9SKrzysztof Grobelny 
685*9b12d1f9SKrzysztof Grobelny         if (subject != nullptr)
6865968caeeSMarri Devender Rao         {
687*9b12d1f9SKrzysztof Grobelny             updateCertIssuerOrSubject(asyncResp->res.jsonValue["Subject"],
688*9b12d1f9SKrzysztof Grobelny                                       *subject);
6895968caeeSMarri Devender Rao         }
690*9b12d1f9SKrzysztof Grobelny 
691*9b12d1f9SKrzysztof Grobelny         if (validNotAfter != nullptr)
6925968caeeSMarri Devender Rao         {
6935968caeeSMarri Devender Rao             asyncResp->res.jsonValue["ValidNotAfter"] =
694*9b12d1f9SKrzysztof Grobelny                 redfish::time_utils::getDateTimeUint(*validNotAfter);
6955968caeeSMarri Devender Rao         }
696*9b12d1f9SKrzysztof Grobelny 
697*9b12d1f9SKrzysztof Grobelny         if (validNotBefore != nullptr)
6985968caeeSMarri Devender Rao         {
6995968caeeSMarri Devender Rao             asyncResp->res.jsonValue["ValidNotBefore"] =
700*9b12d1f9SKrzysztof Grobelny                 redfish::time_utils::getDateTimeUint(*validNotBefore);
7015968caeeSMarri Devender Rao         }
702*9b12d1f9SKrzysztof Grobelny 
7031e312598SJiaqing Zhao         asyncResp->res.addHeader(
704d9f6c621SEd Tanous             boost::beast::http::field::location,
705d9f6c621SEd Tanous             std::string_view(certURL.data(), certURL.size()));
706*9b12d1f9SKrzysztof Grobelny         });
7075968caeeSMarri Devender Rao }
7085968caeeSMarri Devender Rao 
7095968caeeSMarri Devender Rao /**
7105968caeeSMarri Devender Rao  * Action to replace an existing certificate
7115968caeeSMarri Devender Rao  */
7127e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionsReplaceCertificate(App& app)
7135968caeeSMarri Devender Rao {
7140fda0f12SGeorge Liu     BMCWEB_ROUTE(
7150fda0f12SGeorge Liu         app,
7160fda0f12SGeorge Liu         "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate/")
717ed398213SEd Tanous         .privileges(redfish::privileges::postCertificateService)
718002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
719002d39b4SEd Tanous             [&app](const crow::Request& req,
7207e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
7213ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
72245ca1b86SEd Tanous         {
72345ca1b86SEd Tanous             return;
72445ca1b86SEd Tanous         }
7255968caeeSMarri Devender Rao         std::string certificate;
7265968caeeSMarri Devender Rao         nlohmann::json certificateUri;
7275968caeeSMarri Devender Rao         std::optional<std::string> certificateType = "PEM";
7288d1b46d7Szhanghch05 
729002d39b4SEd Tanous         if (!json_util::readJsonAction(req, asyncResp->res, "CertificateString",
730002d39b4SEd Tanous                                        certificate, "CertificateUri",
731002d39b4SEd Tanous                                        certificateUri, "CertificateType",
732002d39b4SEd Tanous                                        certificateType))
7335968caeeSMarri Devender Rao         {
7345968caeeSMarri Devender Rao             BMCWEB_LOG_ERROR << "Required parameters are missing";
7355968caeeSMarri Devender Rao             messages::internalError(asyncResp->res);
7365968caeeSMarri Devender Rao             return;
7375968caeeSMarri Devender Rao         }
7385968caeeSMarri Devender Rao 
7395968caeeSMarri Devender Rao         if (!certificateType)
7405968caeeSMarri Devender Rao         {
7415968caeeSMarri Devender Rao             // should never happen, but it never hurts to be paranoid.
7425968caeeSMarri Devender Rao             return;
7435968caeeSMarri Devender Rao         }
7445968caeeSMarri Devender Rao         if (certificateType != "PEM")
7455968caeeSMarri Devender Rao         {
7465968caeeSMarri Devender Rao             messages::actionParameterNotSupported(
7475968caeeSMarri Devender Rao                 asyncResp->res, "CertificateType", "ReplaceCertificate");
7485968caeeSMarri Devender Rao             return;
7495968caeeSMarri Devender Rao         }
7505968caeeSMarri Devender Rao 
7515968caeeSMarri Devender Rao         std::string certURI;
7525968caeeSMarri Devender Rao         if (!redfish::json_util::readJson(certificateUri, asyncResp->res,
7535968caeeSMarri Devender Rao                                           "@odata.id", certURI))
7545968caeeSMarri Devender Rao         {
7555968caeeSMarri Devender Rao             messages::actionParameterMissing(
7565968caeeSMarri Devender Rao                 asyncResp->res, "ReplaceCertificate", "CertificateUri");
7575968caeeSMarri Devender Rao             return;
7585968caeeSMarri Devender Rao         }
75975b63a2cSJiaqing Zhao         BMCWEB_LOG_INFO << "Certificate URI to replace: " << certURI;
7605968caeeSMarri Devender Rao 
76175b63a2cSJiaqing Zhao         boost::urls::result<boost::urls::url_view> parsedUrl =
76275b63a2cSJiaqing Zhao             boost::urls::parse_relative_ref(certURI);
76375b63a2cSJiaqing Zhao         if (!parsedUrl)
7645968caeeSMarri Devender Rao         {
765002d39b4SEd Tanous             messages::actionParameterValueFormatError(asyncResp->res, certURI,
766002d39b4SEd Tanous                                                       "CertificateUri",
7675968caeeSMarri Devender Rao                                                       "ReplaceCertificate");
7685968caeeSMarri Devender Rao             return;
7695968caeeSMarri Devender Rao         }
77075b63a2cSJiaqing Zhao 
77175b63a2cSJiaqing Zhao         std::string id;
77275b63a2cSJiaqing Zhao         sdbusplus::message::object_path objectPath;
7735968caeeSMarri Devender Rao         std::string name;
77437cce918SMarri Devender Rao         std::string service;
77575b63a2cSJiaqing Zhao         if (crow::utility::readUrlSegments(
77675b63a2cSJiaqing Zhao                 *parsedUrl, "redfish", "v1", "Managers", "bmc",
77775b63a2cSJiaqing Zhao                 "NetworkProtocol", "HTTPS", "Certificates", std::ref(id)))
7785968caeeSMarri Devender Rao         {
779002d39b4SEd Tanous             objectPath =
78075b63a2cSJiaqing Zhao                 sdbusplus::message::object_path(certs::httpsObjectPath) / id;
7815968caeeSMarri Devender Rao             name = "HTTPS certificate";
78237cce918SMarri Devender Rao             service = certs::httpsServiceName;
78337cce918SMarri Devender Rao         }
78475b63a2cSJiaqing Zhao         else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1",
78575b63a2cSJiaqing Zhao                                                 "AccountService", "LDAP",
78675b63a2cSJiaqing Zhao                                                 "Certificates", std::ref(id)))
78737cce918SMarri Devender Rao         {
788002d39b4SEd Tanous             objectPath =
78975b63a2cSJiaqing Zhao                 sdbusplus::message::object_path(certs::ldapObjectPath) / id;
79037cce918SMarri Devender Rao             name = "LDAP certificate";
79137cce918SMarri Devender Rao             service = certs::ldapServiceName;
7925968caeeSMarri Devender Rao         }
79375b63a2cSJiaqing Zhao         else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1",
79475b63a2cSJiaqing Zhao                                                 "Managers", "bmc", "Truststore",
79575b63a2cSJiaqing Zhao                                                 "Certificates", std::ref(id)))
796cfcd5f6bSMarri Devender Rao         {
79775b63a2cSJiaqing Zhao             objectPath =
79875b63a2cSJiaqing Zhao                 sdbusplus::message::object_path(certs::authorityObjectPath) /
79975b63a2cSJiaqing Zhao                 id;
800cfcd5f6bSMarri Devender Rao             name = "TrustStore certificate";
801cfcd5f6bSMarri Devender Rao             service = certs::authorityServiceName;
802cfcd5f6bSMarri Devender Rao         }
8035968caeeSMarri Devender Rao         else
8045968caeeSMarri Devender Rao         {
8055968caeeSMarri Devender Rao             messages::actionParameterNotSupported(
8065968caeeSMarri Devender Rao                 asyncResp->res, "CertificateUri", "ReplaceCertificate");
8075968caeeSMarri Devender Rao             return;
8085968caeeSMarri Devender Rao         }
8095968caeeSMarri Devender Rao 
8105968caeeSMarri Devender Rao         std::shared_ptr<CertificateFile> certFile =
8115968caeeSMarri Devender Rao             std::make_shared<CertificateFile>(certificate);
8125968caeeSMarri Devender Rao         crow::connections::systemBus->async_method_call(
8131e312598SJiaqing Zhao             [asyncResp, certFile, objectPath, service, url{*parsedUrl}, id,
8145968caeeSMarri Devender Rao              name](const boost::system::error_code ec) {
8155968caeeSMarri Devender Rao             if (ec)
8165968caeeSMarri Devender Rao             {
8175968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
81890d2d1e8SJiaqing Zhao                 if (ec.value() ==
81990d2d1e8SJiaqing Zhao                     boost::system::linux_error::bad_request_descriptor)
82090d2d1e8SJiaqing Zhao                 {
82175b63a2cSJiaqing Zhao                     messages::resourceNotFound(asyncResp->res, name, id);
8225968caeeSMarri Devender Rao                     return;
8235968caeeSMarri Devender Rao                 }
82490d2d1e8SJiaqing Zhao                 messages::internalError(asyncResp->res);
82590d2d1e8SJiaqing Zhao                 return;
82690d2d1e8SJiaqing Zhao             }
8271e312598SJiaqing Zhao             getCertificateProperties(asyncResp, objectPath, service, id, url,
8281e312598SJiaqing Zhao                                      name);
8295968caeeSMarri Devender Rao             BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
8305968caeeSMarri Devender Rao                              << certFile->getCertFilePath();
8315968caeeSMarri Devender Rao             },
8325968caeeSMarri Devender Rao             service, objectPath, certs::certReplaceIntf, "Replace",
8335968caeeSMarri Devender Rao             certFile->getCertFilePath());
8347e860f15SJohn Edward Broadbent         });
8357e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionsReplaceCertificate
8365968caeeSMarri Devender Rao 
8375968caeeSMarri Devender Rao /**
8385968caeeSMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
8395968caeeSMarri Devender Rao  * of a component, account or service.
8405968caeeSMarri Devender Rao  */
8415968caeeSMarri Devender Rao 
8427e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificate(App& app)
8435968caeeSMarri Devender Rao {
8447e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
8457e860f15SJohn Edward Broadbent         app,
8467e860f15SJohn Edward Broadbent         "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/<str>/")
847ed398213SEd Tanous         .privileges(redfish::privileges::getCertificate)
8481e312598SJiaqing Zhao         .methods(boost::beast::http::verb::get)(
8491e312598SJiaqing Zhao             [&app](const crow::Request& req,
8507e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
851717b9802SJiaqing Zhao                    const std::string& id) -> void {
8523ba00073SCarson Labrado                 if (!redfish::setUpRedfishRoute(app, req, asyncResp))
85345ca1b86SEd Tanous                 {
85445ca1b86SEd Tanous                     return;
85545ca1b86SEd Tanous                 }
8565968caeeSMarri Devender Rao 
857717b9802SJiaqing Zhao                 BMCWEB_LOG_DEBUG << "HTTPS Certificate ID=" << id;
8581e312598SJiaqing Zhao                 const boost::urls::url certURL = crow::utility::urlFromPieces(
8591e312598SJiaqing Zhao                     "redfish", "v1", "Managers", "bmc", "NetworkProtocol",
8601e312598SJiaqing Zhao                     "HTTPS", "Certificates", id);
861717b9802SJiaqing Zhao                 std::string objPath =
8621e312598SJiaqing Zhao                     sdbusplus::message::object_path(certs::httpsObjectPath) /
8631e312598SJiaqing Zhao                     id;
864717b9802SJiaqing Zhao                 getCertificateProperties(asyncResp, objPath,
865717b9802SJiaqing Zhao                                          certs::httpsServiceName, id, certURL,
866717b9802SJiaqing Zhao                                          "HTTPS Certificate");
8677e860f15SJohn Edward Broadbent             });
8685968caeeSMarri Devender Rao }
8695968caeeSMarri Devender Rao 
8705968caeeSMarri Devender Rao /**
8715968caeeSMarri Devender Rao  * Collection of HTTPS certificates
8725968caeeSMarri Devender Rao  */
8737e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificateCollection(App& app)
8745968caeeSMarri Devender Rao {
8757e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
8765968caeeSMarri Devender Rao                  "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
877ed398213SEd Tanous         .privileges(redfish::privileges::getCertificateCollection)
878002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
879002d39b4SEd Tanous             [&app](const crow::Request& req,
880002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
8813ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
88245ca1b86SEd Tanous         {
88345ca1b86SEd Tanous             return;
88445ca1b86SEd Tanous         }
8851476687dSEd Tanous 
8861476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
8871476687dSEd Tanous             "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates";
8881476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
8891476687dSEd Tanous             "#CertificateCollection.CertificateCollection";
8901476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = "HTTPS Certificates Collection";
8911476687dSEd Tanous         asyncResp->res.jsonValue["Description"] =
8921476687dSEd Tanous             "A Collection of HTTPS certificate instances";
8938d1b46d7Szhanghch05 
894d3f92ce7SJiaqing Zhao         getCertificateList(asyncResp, certs::httpsObjectPath,
895d3f92ce7SJiaqing Zhao                            "/Members"_json_pointer,
896d3f92ce7SJiaqing Zhao                            "/Members@odata.count"_json_pointer);
8977e860f15SJohn Edward Broadbent         });
8985968caeeSMarri Devender Rao 
8997e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
9007e860f15SJohn Edward Broadbent                  "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
901ed398213SEd Tanous         .privileges(redfish::privileges::postCertificateCollection)
902002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
903002d39b4SEd Tanous             [&app](const crow::Request& req,
9047e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
9053ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
90645ca1b86SEd Tanous         {
90745ca1b86SEd Tanous             return;
90845ca1b86SEd Tanous         }
9095968caeeSMarri Devender Rao         BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost";
9108d1b46d7Szhanghch05 
9111476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = "HTTPS Certificate";
9121476687dSEd Tanous         asyncResp->res.jsonValue["Description"] = "HTTPS Certificate";
9135968caeeSMarri Devender Rao 
914002d39b4SEd Tanous         std::string certFileBody = getCertificateFromReqBody(asyncResp, req);
91558eb238fSKowalski, Kamil 
91658eb238fSKowalski, Kamil         if (certFileBody.empty())
91758eb238fSKowalski, Kamil         {
9180fda0f12SGeorge Liu             BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
919a08752f5SZbigniew Kurzynski             messages::unrecognizedRequestBody(asyncResp->res);
92058eb238fSKowalski, Kamil             return;
92158eb238fSKowalski, Kamil         }
92258eb238fSKowalski, Kamil 
9235968caeeSMarri Devender Rao         std::shared_ptr<CertificateFile> certFile =
92458eb238fSKowalski, Kamil             std::make_shared<CertificateFile>(certFileBody);
9255968caeeSMarri Devender Rao 
9265968caeeSMarri Devender Rao         crow::connections::systemBus->async_method_call(
927656ec7e3SZbigniew Kurzynski             [asyncResp, certFile](const boost::system::error_code ec,
928656ec7e3SZbigniew Kurzynski                                   const std::string& objectPath) {
9295968caeeSMarri Devender Rao             if (ec)
9305968caeeSMarri Devender Rao             {
9315968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
9325968caeeSMarri Devender Rao                 messages::internalError(asyncResp->res);
9335968caeeSMarri Devender Rao                 return;
9345968caeeSMarri Devender Rao             }
935717b9802SJiaqing Zhao 
936717b9802SJiaqing Zhao             sdbusplus::message::object_path path(objectPath);
937717b9802SJiaqing Zhao             std::string certId = path.filename();
9381e312598SJiaqing Zhao             const boost::urls::url certURL = crow::utility::urlFromPieces(
9391e312598SJiaqing Zhao                 "redfish", "v1", "Managers", "bmc", "NetworkProtocol", "HTTPS",
9401e312598SJiaqing Zhao                 "Certificates", certId);
941717b9802SJiaqing Zhao             getCertificateProperties(asyncResp, objectPath,
942717b9802SJiaqing Zhao                                      certs::httpsServiceName, certId, certURL,
943717b9802SJiaqing Zhao                                      "HTTPS Certificate");
9445968caeeSMarri Devender Rao             BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
9455968caeeSMarri Devender Rao                              << certFile->getCertFilePath();
9465968caeeSMarri Devender Rao             },
94737cce918SMarri Devender Rao             certs::httpsServiceName, certs::httpsObjectPath,
9480fda0f12SGeorge Liu             certs::certInstallIntf, "Install", certFile->getCertFilePath());
9497e860f15SJohn Edward Broadbent         });
9507e860f15SJohn Edward Broadbent } // requestRoutesHTTPSCertificateCollection
9515968caeeSMarri Devender Rao 
9525968caeeSMarri Devender Rao /**
9537e860f15SJohn Edward Broadbent  * The certificate location schema defines a resource that an administrator
9547e860f15SJohn Edward Broadbent  * can use in order to locate all certificates installed on a given service.
9557e860f15SJohn Edward Broadbent  */
9567e860f15SJohn Edward Broadbent inline void requestRoutesCertificateLocations(App& app)
9577e860f15SJohn Edward Broadbent {
9587e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/")
959ed398213SEd Tanous         .privileges(redfish::privileges::getCertificateLocations)
960002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
961002d39b4SEd Tanous             [&app](const crow::Request& req,
962002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
9633ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
96445ca1b86SEd Tanous         {
96545ca1b86SEd Tanous             return;
96645ca1b86SEd Tanous         }
9671476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
9681476687dSEd Tanous             "/redfish/v1/CertificateService/CertificateLocations";
9691476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
9701476687dSEd Tanous             "#CertificateLocations.v1_0_0.CertificateLocations";
9711476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = "Certificate Locations";
9721476687dSEd Tanous         asyncResp->res.jsonValue["Id"] = "CertificateLocations";
9731476687dSEd Tanous         asyncResp->res.jsonValue["Description"] =
9747e860f15SJohn Edward Broadbent             "Defines a resource that an administrator can use in order to "
9751476687dSEd Tanous             "locate all certificates installed on a given service";
9767e860f15SJohn Edward Broadbent 
977d3f92ce7SJiaqing Zhao         getCertificateList(asyncResp, certs::baseObjectPath,
978d3f92ce7SJiaqing Zhao                            "/Links/Certificates"_json_pointer,
979d3f92ce7SJiaqing Zhao                            "/Links/Certificates@odata.count"_json_pointer);
9807e860f15SJohn Edward Broadbent         });
9817e860f15SJohn Edward Broadbent }
9827e860f15SJohn Edward Broadbent // requestRoutesCertificateLocations
98337cce918SMarri Devender Rao 
98437cce918SMarri Devender Rao /**
98537cce918SMarri Devender Rao  * Collection of LDAP certificates
98637cce918SMarri Devender Rao  */
9877e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificateCollection(App& app)
98837cce918SMarri Devender Rao {
9897e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
990ed398213SEd Tanous         .privileges(redfish::privileges::getCertificateCollection)
991002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
992002d39b4SEd Tanous             [&app](const crow::Request& req,
993002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
9943ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
99545ca1b86SEd Tanous         {
99645ca1b86SEd Tanous             return;
99745ca1b86SEd Tanous         }
9981476687dSEd Tanous 
9991476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
10001476687dSEd Tanous             "/redfish/v1/AccountService/LDAP/Certificates";
10011476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
10021476687dSEd Tanous             "#CertificateCollection.CertificateCollection";
10031476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = "LDAP Certificates Collection";
10041476687dSEd Tanous         asyncResp->res.jsonValue["Description"] =
10051476687dSEd Tanous             "A Collection of LDAP certificate instances";
10068d1b46d7Szhanghch05 
1007d3f92ce7SJiaqing Zhao         getCertificateList(asyncResp, certs::ldapObjectPath,
1008d3f92ce7SJiaqing Zhao                            "/Members"_json_pointer,
1009d3f92ce7SJiaqing Zhao                            "/Members@odata.count"_json_pointer);
10107e860f15SJohn Edward Broadbent         });
101137cce918SMarri Devender Rao 
10127e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
1013ed398213SEd Tanous         .privileges(redfish::privileges::postCertificateCollection)
10147e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
101545ca1b86SEd Tanous             [&app](const crow::Request& req,
10167e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
10173ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
101845ca1b86SEd Tanous         {
101945ca1b86SEd Tanous             return;
102045ca1b86SEd Tanous         }
1021002d39b4SEd Tanous         std::string certFileBody = getCertificateFromReqBody(asyncResp, req);
102258eb238fSKowalski, Kamil 
102358eb238fSKowalski, Kamil         if (certFileBody.empty())
102458eb238fSKowalski, Kamil         {
1025002d39b4SEd Tanous             BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
1026a08752f5SZbigniew Kurzynski             messages::unrecognizedRequestBody(asyncResp->res);
102758eb238fSKowalski, Kamil             return;
102858eb238fSKowalski, Kamil         }
102958eb238fSKowalski, Kamil 
103058eb238fSKowalski, Kamil         std::shared_ptr<CertificateFile> certFile =
103158eb238fSKowalski, Kamil             std::make_shared<CertificateFile>(certFileBody);
103258eb238fSKowalski, Kamil 
103337cce918SMarri Devender Rao         crow::connections::systemBus->async_method_call(
1034656ec7e3SZbigniew Kurzynski             [asyncResp, certFile](const boost::system::error_code ec,
1035656ec7e3SZbigniew Kurzynski                                   const std::string& objectPath) {
103637cce918SMarri Devender Rao             if (ec)
103737cce918SMarri Devender Rao             {
103837cce918SMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
103937cce918SMarri Devender Rao                 messages::internalError(asyncResp->res);
104037cce918SMarri Devender Rao                 return;
104137cce918SMarri Devender Rao             }
1042717b9802SJiaqing Zhao 
1043717b9802SJiaqing Zhao             sdbusplus::message::object_path path(objectPath);
1044717b9802SJiaqing Zhao             std::string certId = path.filename();
10451e312598SJiaqing Zhao             const boost::urls::url certURL =
10461e312598SJiaqing Zhao                 crow::utility::urlFromPieces("redfish", "v1", "AccountService",
10471e312598SJiaqing Zhao                                              "LDAP", "Certificates", certId);
1048717b9802SJiaqing Zhao             getCertificateProperties(asyncResp, objectPath,
1049717b9802SJiaqing Zhao                                      certs::ldapServiceName, certId, certURL,
1050717b9802SJiaqing Zhao                                      "LDAP Certificate");
105137cce918SMarri Devender Rao             BMCWEB_LOG_DEBUG << "LDAP certificate install file="
105237cce918SMarri Devender Rao                              << certFile->getCertFilePath();
105337cce918SMarri Devender Rao             },
105437cce918SMarri Devender Rao             certs::ldapServiceName, certs::ldapObjectPath,
1055002d39b4SEd Tanous             certs::certInstallIntf, "Install", certFile->getCertFilePath());
10567e860f15SJohn Edward Broadbent         });
10577e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificateCollection
105837cce918SMarri Devender Rao 
105937cce918SMarri Devender Rao /**
106037cce918SMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
106137cce918SMarri Devender Rao  * of a component, account or service.
106237cce918SMarri Devender Rao  */
10637e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificate(App& app)
106437cce918SMarri Devender Rao {
10657e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/")
1066ed398213SEd Tanous         .privileges(redfish::privileges::getCertificate)
10677e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
106845ca1b86SEd Tanous             [&app](const crow::Request& req,
10697e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1070717b9802SJiaqing Zhao                    const std::string& id) {
10713ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
107245ca1b86SEd Tanous         {
107345ca1b86SEd Tanous             return;
107445ca1b86SEd Tanous         }
1075717b9802SJiaqing Zhao 
1076717b9802SJiaqing Zhao         BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" << id;
10771e312598SJiaqing Zhao         const boost::urls::url certURL = crow::utility::urlFromPieces(
10781e312598SJiaqing Zhao             "redfish", "v1", "AccountService", "LDAP", "Certificates", id);
1079717b9802SJiaqing Zhao         std::string objPath =
1080717b9802SJiaqing Zhao             sdbusplus::message::object_path(certs::ldapObjectPath) / id;
1081717b9802SJiaqing Zhao         getCertificateProperties(asyncResp, objPath, certs::ldapServiceName, id,
1082717b9802SJiaqing Zhao                                  certURL, "LDAP Certificate");
10837e860f15SJohn Edward Broadbent         });
10847e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificate
1085cfcd5f6bSMarri Devender Rao /**
1086cfcd5f6bSMarri Devender Rao  * Collection of TrustStoreCertificate certificates
1087cfcd5f6bSMarri Devender Rao  */
10887e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificateCollection(App& app)
1089cfcd5f6bSMarri Devender Rao {
10907e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
1091ed398213SEd Tanous         .privileges(redfish::privileges::getCertificate)
1092002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
1093002d39b4SEd Tanous             [&app](const crow::Request& req,
1094002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
10953ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
109645ca1b86SEd Tanous         {
109745ca1b86SEd Tanous             return;
109845ca1b86SEd Tanous         }
10991476687dSEd Tanous 
11001476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
11011476687dSEd Tanous             "/redfish/v1/Managers/bmc/Truststore/Certificates/";
11021476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
11031476687dSEd Tanous             "#CertificateCollection.CertificateCollection";
1104002d39b4SEd Tanous         asyncResp->res.jsonValue["Name"] = "TrustStore Certificates Collection";
11051476687dSEd Tanous         asyncResp->res.jsonValue["Description"] =
11061476687dSEd Tanous             "A Collection of TrustStore certificate instances";
11078d1b46d7Szhanghch05 
1108d3f92ce7SJiaqing Zhao         getCertificateList(asyncResp, certs::authorityObjectPath,
1109d3f92ce7SJiaqing Zhao                            "/Members"_json_pointer,
1110d3f92ce7SJiaqing Zhao                            "/Members@odata.count"_json_pointer);
11117e860f15SJohn Edward Broadbent         });
1112cfcd5f6bSMarri Devender Rao 
11137e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
1114ed398213SEd Tanous         .privileges(redfish::privileges::postCertificateCollection)
1115002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
1116002d39b4SEd Tanous             [&app](const crow::Request& req,
11177e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
11183ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
111945ca1b86SEd Tanous         {
112045ca1b86SEd Tanous             return;
112145ca1b86SEd Tanous         }
1122002d39b4SEd Tanous         std::string certFileBody = getCertificateFromReqBody(asyncResp, req);
1123a08752f5SZbigniew Kurzynski 
1124a08752f5SZbigniew Kurzynski         if (certFileBody.empty())
1125a08752f5SZbigniew Kurzynski         {
11260fda0f12SGeorge Liu             BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
1127a08752f5SZbigniew Kurzynski             messages::unrecognizedRequestBody(asyncResp->res);
1128a08752f5SZbigniew Kurzynski             return;
1129a08752f5SZbigniew Kurzynski         }
1130a08752f5SZbigniew Kurzynski 
1131a08752f5SZbigniew Kurzynski         std::shared_ptr<CertificateFile> certFile =
1132a08752f5SZbigniew Kurzynski             std::make_shared<CertificateFile>(certFileBody);
1133cfcd5f6bSMarri Devender Rao         crow::connections::systemBus->async_method_call(
1134656ec7e3SZbigniew Kurzynski             [asyncResp, certFile](const boost::system::error_code ec,
1135656ec7e3SZbigniew Kurzynski                                   const std::string& objectPath) {
1136cfcd5f6bSMarri Devender Rao             if (ec)
1137cfcd5f6bSMarri Devender Rao             {
1138cfcd5f6bSMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
1139cfcd5f6bSMarri Devender Rao                 messages::internalError(asyncResp->res);
1140cfcd5f6bSMarri Devender Rao                 return;
1141cfcd5f6bSMarri Devender Rao             }
1142656ec7e3SZbigniew Kurzynski 
1143717b9802SJiaqing Zhao             sdbusplus::message::object_path path(objectPath);
1144717b9802SJiaqing Zhao             std::string certId = path.filename();
11451e312598SJiaqing Zhao             const boost::urls::url certURL = crow::utility::urlFromPieces(
11461e312598SJiaqing Zhao                 "redfish", "v1", "Managers", "bmc", "Truststore",
11471e312598SJiaqing Zhao                 "Certificates", certId);
1148717b9802SJiaqing Zhao             getCertificateProperties(asyncResp, objectPath,
1149717b9802SJiaqing Zhao                                      certs::authorityServiceName, certId,
1150717b9802SJiaqing Zhao                                      certURL, "TrustStore Certificate");
11510fda0f12SGeorge Liu             BMCWEB_LOG_DEBUG << "TrustStore certificate install file="
1152cfcd5f6bSMarri Devender Rao                              << certFile->getCertFilePath();
1153cfcd5f6bSMarri Devender Rao             },
1154cfcd5f6bSMarri Devender Rao             certs::authorityServiceName, certs::authorityObjectPath,
11550fda0f12SGeorge Liu             certs::certInstallIntf, "Install", certFile->getCertFilePath());
11567e860f15SJohn Edward Broadbent         });
11577e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificateCollection
1158cfcd5f6bSMarri Devender Rao 
1159cfcd5f6bSMarri Devender Rao /**
1160cfcd5f6bSMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
1161cfcd5f6bSMarri Devender Rao  * of a component, account or service.
1162cfcd5f6bSMarri Devender Rao  */
11637e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificate(App& app)
1164cfcd5f6bSMarri Devender Rao {
11657e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
1166ed398213SEd Tanous         .privileges(redfish::privileges::getCertificate)
11677e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
116845ca1b86SEd Tanous             [&app](const crow::Request& req,
11697e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1170717b9802SJiaqing Zhao                    const std::string& id) {
11713ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
117245ca1b86SEd Tanous         {
117345ca1b86SEd Tanous             return;
117445ca1b86SEd Tanous         }
1175717b9802SJiaqing Zhao 
1176717b9802SJiaqing Zhao         BMCWEB_LOG_DEBUG << "Truststore Certificate ID=" << id;
11771e312598SJiaqing Zhao         const boost::urls::url certURL =
11781e312598SJiaqing Zhao             crow::utility::urlFromPieces("redfish", "v1", "Managers", "bmc",
11791e312598SJiaqing Zhao                                          "Truststore", "Certificates", id);
1180717b9802SJiaqing Zhao         std::string objPath =
1181717b9802SJiaqing Zhao             sdbusplus::message::object_path(certs::authorityObjectPath) / id;
1182717b9802SJiaqing Zhao         getCertificateProperties(asyncResp, objPath,
1183717b9802SJiaqing Zhao                                  certs::authorityServiceName, id, certURL,
1184717b9802SJiaqing Zhao                                  "TrustStore Certificate");
11857e860f15SJohn Edward Broadbent         });
118607a60299SZbigniew Kurzynski 
11877e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
1188ed398213SEd Tanous         .privileges(redfish::privileges::deleteCertificate)
11897e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::delete_)(
119045ca1b86SEd Tanous             [&app](const crow::Request& req,
11917e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1192717b9802SJiaqing Zhao                    const std::string& id) {
11933ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
119445ca1b86SEd Tanous         {
119545ca1b86SEd Tanous             return;
119645ca1b86SEd Tanous         }
119707a60299SZbigniew Kurzynski 
1198717b9802SJiaqing Zhao         BMCWEB_LOG_DEBUG << "Delete TrustStore Certificate ID=" << id;
1199717b9802SJiaqing Zhao         std::string objPath =
1200717b9802SJiaqing Zhao             sdbusplus::message::object_path(certs::authorityObjectPath) / id;
120107a60299SZbigniew Kurzynski 
120207a60299SZbigniew Kurzynski         crow::connections::systemBus->async_method_call(
120307a60299SZbigniew Kurzynski             [asyncResp, id](const boost::system::error_code ec) {
120407a60299SZbigniew Kurzynski             if (ec)
120507a60299SZbigniew Kurzynski             {
120607a60299SZbigniew Kurzynski                 messages::resourceNotFound(asyncResp->res,
1207717b9802SJiaqing Zhao                                            "TrustStore Certificate", id);
120807a60299SZbigniew Kurzynski                 return;
120907a60299SZbigniew Kurzynski             }
121007a60299SZbigniew Kurzynski             BMCWEB_LOG_INFO << "Certificate deleted";
1211002d39b4SEd Tanous             asyncResp->res.result(boost::beast::http::status::no_content);
121207a60299SZbigniew Kurzynski             },
1213717b9802SJiaqing Zhao             certs::authorityServiceName, objPath, certs::objDeleteIntf,
121407a60299SZbigniew Kurzynski             "Delete");
12157e860f15SJohn Edward Broadbent         });
12167e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificate
12175968caeeSMarri Devender Rao } // namespace redfish
1218