xref: /openbmc/bmcweb/features/redfish/lib/certificate_service.hpp (revision 432a890cfca335e565b770b1604ed4e547c5a732)
15968caeeSMarri Devender Rao #pragma once
25968caeeSMarri Devender Rao 
37e860f15SJohn Edward Broadbent #include <app.hpp>
4e6604b11SIwona Klimaszewska #include <boost/convert.hpp>
5e6604b11SIwona Klimaszewska #include <boost/convert/strtol.hpp>
61214b7e7SGunnar Mills 
75968caeeSMarri Devender Rao #include <variant>
85968caeeSMarri Devender Rao namespace redfish
95968caeeSMarri Devender Rao {
105968caeeSMarri Devender Rao namespace certs
115968caeeSMarri Devender Rao {
125968caeeSMarri Devender Rao constexpr char const* httpsObjectPath =
135968caeeSMarri Devender Rao     "/xyz/openbmc_project/certs/server/https";
145968caeeSMarri Devender Rao constexpr char const* certInstallIntf = "xyz.openbmc_project.Certs.Install";
155968caeeSMarri Devender Rao constexpr char const* certReplaceIntf = "xyz.openbmc_project.Certs.Replace";
1607a60299SZbigniew Kurzynski constexpr char const* objDeleteIntf = "xyz.openbmc_project.Object.Delete";
175968caeeSMarri Devender Rao constexpr char const* certPropIntf = "xyz.openbmc_project.Certs.Certificate";
185968caeeSMarri Devender Rao constexpr char const* dbusPropIntf = "org.freedesktop.DBus.Properties";
195968caeeSMarri Devender Rao constexpr char const* dbusObjManagerIntf = "org.freedesktop.DBus.ObjectManager";
2037cce918SMarri Devender Rao constexpr char const* ldapObjectPath = "/xyz/openbmc_project/certs/client/ldap";
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";
27cfcd5f6bSMarri Devender Rao constexpr char const* authorityObjectPath =
28cfcd5f6bSMarri Devender Rao     "/xyz/openbmc_project/certs/authority/ldap";
295968caeeSMarri Devender Rao } // namespace certs
305968caeeSMarri Devender Rao 
315968caeeSMarri Devender Rao /**
325968caeeSMarri Devender Rao  * The Certificate schema defines a Certificate Service which represents the
335968caeeSMarri Devender Rao  * actions available to manage certificates and links to where certificates
345968caeeSMarri Devender Rao  * are installed.
355968caeeSMarri Devender Rao  */
367e860f15SJohn Edward Broadbent 
375968caeeSMarri Devender Rao // TODO: Issue#61 No entries are available for Certificate
384e0453b1SGunnar Mills // service at https://www.dmtf.org/standards/redfish
395968caeeSMarri Devender Rao // "redfish standard registries". Need to modify after DMTF
405968caeeSMarri Devender Rao // publish Privilege details for certificate service
415968caeeSMarri Devender Rao 
427e860f15SJohn Edward Broadbent inline void requestRoutesCertificateService(App& app)
435968caeeSMarri Devender Rao {
447e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/")
45*432a890cSEd Tanous         .privileges({{"Login"}})
467e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
477e860f15SJohn Edward Broadbent             [](const crow::Request&,
487e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
498d1b46d7Szhanghch05                 asyncResp->res.jsonValue = {
507e860f15SJohn Edward Broadbent                     {"@odata.type",
517e860f15SJohn Edward Broadbent                      "#CertificateService.v1_0_0.CertificateService"},
525968caeeSMarri Devender Rao                     {"@odata.id", "/redfish/v1/CertificateService"},
535968caeeSMarri Devender Rao                     {"Id", "CertificateService"},
545968caeeSMarri Devender Rao                     {"Name", "Certificate Service"},
557e860f15SJohn Edward Broadbent                     {"Description",
567e860f15SJohn Edward Broadbent                      "Actions available to manage certificates"}};
578d1b46d7Szhanghch05                 asyncResp->res.jsonValue["CertificateLocations"] = {
585968caeeSMarri Devender Rao                     {"@odata.id",
595968caeeSMarri Devender Rao                      "/redfish/v1/CertificateService/CertificateLocations"}};
608d1b46d7Szhanghch05                 asyncResp->res
617e860f15SJohn Edward Broadbent                     .jsonValue["Actions"]
627e860f15SJohn Edward Broadbent                               ["#CertificateService.ReplaceCertificate"] = {
635968caeeSMarri Devender Rao                     {"target", "/redfish/v1/CertificateService/Actions/"
645968caeeSMarri Devender Rao                                "CertificateService.ReplaceCertificate"},
655968caeeSMarri Devender Rao                     {"CertificateType@Redfish.AllowableValues", {"PEM"}}};
667e860f15SJohn Edward Broadbent                 asyncResp->res
677e860f15SJohn Edward Broadbent                     .jsonValue["Actions"]["#CertificateService.GenerateCSR"] = {
687e860f15SJohn Edward Broadbent                     {"target", "/redfish/v1/CertificateService/Actions/"
6930215816SMarri Devender Rao                                "CertificateService.GenerateCSR"}};
707e860f15SJohn Edward Broadbent             });
717e860f15SJohn Edward Broadbent } // requestRoutesCertificateService
7237cce918SMarri Devender Rao 
735968caeeSMarri Devender Rao /**
745968caeeSMarri Devender Rao  * @brief Find the ID specified in the URL
755968caeeSMarri Devender Rao  * Finds the numbers specified after the last "/" in the URL and returns.
765968caeeSMarri Devender Rao  * @param[in] path URL
775968caeeSMarri Devender Rao  * @return -1 on failure and number on success
785968caeeSMarri Devender Rao  */
7923a21a1cSEd Tanous inline long getIDFromURL(const std::string_view url)
805968caeeSMarri Devender Rao {
81f23b7296SEd Tanous     std::size_t found = url.rfind('/');
825968caeeSMarri Devender Rao     if (found == std::string::npos)
835968caeeSMarri Devender Rao     {
845968caeeSMarri Devender Rao         return -1;
855968caeeSMarri Devender Rao     }
86e6604b11SIwona Klimaszewska 
875968caeeSMarri Devender Rao     if ((found + 1) < url.length())
885968caeeSMarri Devender Rao     {
895968caeeSMarri Devender Rao         std::string_view str = url.substr(found + 1);
90e6604b11SIwona Klimaszewska 
91e6604b11SIwona Klimaszewska         return boost::convert<long>(str, boost::cnv::strtol()).value_or(-1);
925968caeeSMarri Devender Rao     }
93e6604b11SIwona Klimaszewska 
945968caeeSMarri Devender Rao     return -1;
955968caeeSMarri Devender Rao }
965968caeeSMarri Devender Rao 
978d1b46d7Szhanghch05 inline std::string getCertificateFromReqBody(
988d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
9958eb238fSKowalski, Kamil     const crow::Request& req)
10058eb238fSKowalski, Kamil {
10158eb238fSKowalski, Kamil     nlohmann::json reqJson = nlohmann::json::parse(req.body, nullptr, false);
10258eb238fSKowalski, Kamil 
10358eb238fSKowalski, Kamil     if (reqJson.is_discarded())
10458eb238fSKowalski, Kamil     {
10558eb238fSKowalski, Kamil         // We did not receive JSON request, proceed as it is RAW data
10658eb238fSKowalski, Kamil         return req.body;
10758eb238fSKowalski, Kamil     }
10858eb238fSKowalski, Kamil 
10958eb238fSKowalski, Kamil     std::string certificate;
11058eb238fSKowalski, Kamil     std::optional<std::string> certificateType = "PEM";
11158eb238fSKowalski, Kamil 
11258eb238fSKowalski, Kamil     if (!json_util::readJson(reqJson, asyncResp->res, "CertificateString",
11358eb238fSKowalski, Kamil                              certificate, "CertificateType", certificateType))
11458eb238fSKowalski, Kamil     {
11558eb238fSKowalski, Kamil         BMCWEB_LOG_ERROR << "Required parameters are missing";
11658eb238fSKowalski, Kamil         messages::internalError(asyncResp->res);
11758eb238fSKowalski, Kamil         return std::string();
11858eb238fSKowalski, Kamil     }
11958eb238fSKowalski, Kamil 
12058eb238fSKowalski, Kamil     if (*certificateType != "PEM")
12158eb238fSKowalski, Kamil     {
12258eb238fSKowalski, Kamil         messages::propertyValueNotInList(asyncResp->res, *certificateType,
12358eb238fSKowalski, Kamil                                          "CertificateType");
12458eb238fSKowalski, Kamil         return std::string();
12558eb238fSKowalski, Kamil     }
12658eb238fSKowalski, Kamil 
12758eb238fSKowalski, Kamil     return certificate;
12858eb238fSKowalski, Kamil }
12958eb238fSKowalski, Kamil 
1305968caeeSMarri Devender Rao /**
1315968caeeSMarri Devender Rao  * Class to create a temporary certificate file for uploading to system
1325968caeeSMarri Devender Rao  */
1335968caeeSMarri Devender Rao class CertificateFile
1345968caeeSMarri Devender Rao {
1355968caeeSMarri Devender Rao   public:
1365968caeeSMarri Devender Rao     CertificateFile() = delete;
1375968caeeSMarri Devender Rao     CertificateFile(const CertificateFile&) = delete;
1385968caeeSMarri Devender Rao     CertificateFile& operator=(const CertificateFile&) = delete;
1395968caeeSMarri Devender Rao     CertificateFile(CertificateFile&&) = delete;
1405968caeeSMarri Devender Rao     CertificateFile& operator=(CertificateFile&&) = delete;
1415968caeeSMarri Devender Rao     CertificateFile(const std::string& certString)
1425968caeeSMarri Devender Rao     {
14372d52d25SEd Tanous         std::array<char, 18> dirTemplate = {'/', 't', 'm', 'p', '/', 'C',
1445207438cSEd Tanous                                             'e', 'r', 't', 's', '.', 'X',
1455207438cSEd Tanous                                             'X', 'X', 'X', 'X', 'X', '\0'};
1465207438cSEd Tanous         char* tempDirectory = mkdtemp(dirTemplate.data());
1475968caeeSMarri Devender Rao         if (tempDirectory)
1485968caeeSMarri Devender Rao         {
1495968caeeSMarri Devender Rao             certDirectory = tempDirectory;
1505968caeeSMarri Devender Rao             certificateFile = certDirectory / "cert.pem";
1515968caeeSMarri Devender Rao             std::ofstream out(certificateFile, std::ofstream::out |
1525968caeeSMarri Devender Rao                                                    std::ofstream::binary |
1535968caeeSMarri Devender Rao                                                    std::ofstream::trunc);
1545968caeeSMarri Devender Rao             out << certString;
1555968caeeSMarri Devender Rao             out.close();
1565968caeeSMarri Devender Rao             BMCWEB_LOG_DEBUG << "Creating certificate file" << certificateFile;
1575968caeeSMarri Devender Rao         }
1585968caeeSMarri Devender Rao     }
1595968caeeSMarri Devender Rao     ~CertificateFile()
1605968caeeSMarri Devender Rao     {
1615968caeeSMarri Devender Rao         if (std::filesystem::exists(certDirectory))
1625968caeeSMarri Devender Rao         {
1635968caeeSMarri Devender Rao             BMCWEB_LOG_DEBUG << "Removing certificate file" << certificateFile;
16423a21a1cSEd Tanous             std::error_code ec;
16523a21a1cSEd Tanous             std::filesystem::remove_all(certDirectory, ec);
16623a21a1cSEd Tanous             if (ec)
1675968caeeSMarri Devender Rao             {
1685968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "Failed to remove temp directory"
1695968caeeSMarri Devender Rao                                  << certDirectory;
1705968caeeSMarri Devender Rao             }
1715968caeeSMarri Devender Rao         }
1725968caeeSMarri Devender Rao     }
1735968caeeSMarri Devender Rao     std::string getCertFilePath()
1745968caeeSMarri Devender Rao     {
1755968caeeSMarri Devender Rao         return certificateFile;
1765968caeeSMarri Devender Rao     }
1775968caeeSMarri Devender Rao 
1785968caeeSMarri Devender Rao   private:
1795968caeeSMarri Devender Rao     std::filesystem::path certificateFile;
1805968caeeSMarri Devender Rao     std::filesystem::path certDirectory;
1815968caeeSMarri Devender Rao };
1825968caeeSMarri Devender Rao 
18330215816SMarri Devender Rao static std::unique_ptr<sdbusplus::bus::match::match> csrMatcher;
18430215816SMarri Devender Rao /**
18530215816SMarri Devender Rao  * @brief Read data from CSR D-bus object and set to response
18630215816SMarri Devender Rao  *
18730215816SMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
18830215816SMarri Devender Rao  * @param[in] certURI Link to certifiate collection URI
18930215816SMarri Devender Rao  * @param[in] service D-Bus service name
19030215816SMarri Devender Rao  * @param[in] certObjPath certificate D-Bus object path
19130215816SMarri Devender Rao  * @param[in] csrObjPath CSR D-Bus object path
19230215816SMarri Devender Rao  * @return None
19330215816SMarri Devender Rao  */
1948d1b46d7Szhanghch05 static void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
19530215816SMarri Devender Rao                    const std::string& certURI, const std::string& service,
19630215816SMarri Devender Rao                    const std::string& certObjPath,
19730215816SMarri Devender Rao                    const std::string& csrObjPath)
19830215816SMarri Devender Rao {
19930215816SMarri Devender Rao     BMCWEB_LOG_DEBUG << "getCSR CertObjectPath" << certObjPath
20030215816SMarri Devender Rao                      << " CSRObjectPath=" << csrObjPath
20130215816SMarri Devender Rao                      << " service=" << service;
20230215816SMarri Devender Rao     crow::connections::systemBus->async_method_call(
20330215816SMarri Devender Rao         [asyncResp, certURI](const boost::system::error_code ec,
20430215816SMarri Devender Rao                              const std::string& csr) {
20530215816SMarri Devender Rao             if (ec)
20630215816SMarri Devender Rao             {
20730215816SMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
20830215816SMarri Devender Rao                 messages::internalError(asyncResp->res);
20930215816SMarri Devender Rao                 return;
21030215816SMarri Devender Rao             }
21130215816SMarri Devender Rao             if (csr.empty())
21230215816SMarri Devender Rao             {
21330215816SMarri Devender Rao                 BMCWEB_LOG_ERROR << "CSR read is empty";
21430215816SMarri Devender Rao                 messages::internalError(asyncResp->res);
21530215816SMarri Devender Rao                 return;
21630215816SMarri Devender Rao             }
21730215816SMarri Devender Rao             asyncResp->res.jsonValue["CSRString"] = csr;
21830215816SMarri Devender Rao             asyncResp->res.jsonValue["CertificateCollection"] = {
21930215816SMarri Devender Rao                 {"@odata.id", certURI}};
22030215816SMarri Devender Rao         },
22130215816SMarri Devender Rao         service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR");
22230215816SMarri Devender Rao }
22330215816SMarri Devender Rao 
22430215816SMarri Devender Rao /**
22530215816SMarri Devender Rao  * Action to Generate CSR
22630215816SMarri Devender Rao  */
2277e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionGenerateCSR(App& app)
22830215816SMarri Devender Rao {
2297e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/Actions/"
23030215816SMarri Devender Rao                       "CertificateService.GenerateCSR/")
231*432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
2327e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
2337e860f15SJohn Edward Broadbent             [](const crow::Request& req,
2347e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
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 = "";
26130215816SMarri Devender Rao                 if (!json_util::readJson(
2627e860f15SJohn Edward Broadbent                         req, asyncResp->res, "City", city, "CommonName",
2637e860f15SJohn Edward Broadbent                         commonName, "ContactPerson", optContactPerson,
2647e860f15SJohn Edward Broadbent                         "Country", country, "Organization", organization,
2657e860f15SJohn Edward Broadbent                         "OrganizationalUnit", organizationalUnit, "State",
2667e860f15SJohn Edward Broadbent                         state, "CertificateCollection", certificateCollection,
2677e860f15SJohn Edward Broadbent                         "AlternativeNames", optAlternativeNames,
2687e860f15SJohn Edward Broadbent                         "ChallengePassword", optChallengePassword, "Email",
2697e860f15SJohn Edward Broadbent                         optEmail, "GivenName", optGivenName, "Initials",
2707e860f15SJohn Edward Broadbent                         optInitials, "KeyBitLength", optKeyBitLength,
2717e860f15SJohn Edward Broadbent                         "KeyCurveId", optKeyCurveId, "KeyPairAlgorithm",
2727e860f15SJohn Edward Broadbent                         optKeyPairAlgorithm, "KeyUsage", optKeyUsage, "Surname",
2737e860f15SJohn Edward Broadbent                         optSurname, "UnstructuredName", optUnstructuredName))
27430215816SMarri Devender Rao                 {
27530215816SMarri Devender Rao                     return;
27630215816SMarri Devender Rao                 }
27730215816SMarri Devender Rao 
27830215816SMarri Devender Rao                 // bmcweb has no way to store or decode a private key challenge
2797e860f15SJohn Edward Broadbent                 // password, which will likely cause bmcweb to crash on startup
2807e860f15SJohn Edward Broadbent                 // if this is not set on a post so not allowing the user to set
2817e860f15SJohn Edward Broadbent                 // value
28230215816SMarri Devender Rao                 if (*optChallengePassword != "")
28330215816SMarri Devender Rao                 {
2847e860f15SJohn Edward Broadbent                     messages::actionParameterNotSupported(
2857e860f15SJohn Edward Broadbent                         asyncResp->res, "GenerateCSR", "ChallengePassword");
28630215816SMarri Devender Rao                     return;
28730215816SMarri Devender Rao                 }
28830215816SMarri Devender Rao 
28930215816SMarri Devender Rao                 std::string certURI;
2907e860f15SJohn Edward Broadbent                 if (!redfish::json_util::readJson(certificateCollection,
2917e860f15SJohn Edward Broadbent                                                   asyncResp->res, "@odata.id",
2927e860f15SJohn Edward Broadbent                                                   certURI))
29330215816SMarri Devender Rao                 {
29430215816SMarri Devender Rao                     return;
29530215816SMarri Devender Rao                 }
29630215816SMarri Devender Rao 
29730215816SMarri Devender Rao                 std::string objectPath;
29830215816SMarri Devender Rao                 std::string service;
2997e860f15SJohn Edward Broadbent                 if (boost::starts_with(certURI,
3007e860f15SJohn Edward Broadbent                                        "/redfish/v1/Managers/bmc/"
3017e860f15SJohn Edward Broadbent                                        "NetworkProtocol/HTTPS/Certificates"))
30230215816SMarri Devender Rao                 {
30330215816SMarri Devender Rao                     objectPath = certs::httpsObjectPath;
30430215816SMarri Devender Rao                     service = certs::httpsServiceName;
30530215816SMarri Devender Rao                 }
3063b7f0149SMarri Devender Rao                 else if (boost::starts_with(
3077e860f15SJohn Edward Broadbent                              certURI,
3087e860f15SJohn Edward Broadbent                              "/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
3217e860f15SJohn Edward Broadbent                 if (*optKeyPairAlgorithm != "EC" &&
3227e860f15SJohn Edward Broadbent                     *optKeyPairAlgorithm != "RSA")
32330215816SMarri Devender Rao                 {
32430215816SMarri Devender Rao                     messages::actionParameterNotSupported(
32530215816SMarri Devender Rao                         asyncResp->res, "KeyPairAlgorithm", "GenerateCSR");
32630215816SMarri Devender Rao                     return;
32730215816SMarri Devender Rao                 }
32830215816SMarri Devender Rao 
3297e860f15SJohn Edward Broadbent                 // supporting only 2048 key bit length for RSA algorithm due to
3307e860f15SJohn Edward Broadbent                 // time consumed in generating private key
33130215816SMarri Devender Rao                 if (*optKeyPairAlgorithm == "RSA" &&
3322c70f800SEd Tanous                     *optKeyBitLength != rsaKeyBitLength)
33330215816SMarri Devender Rao                 {
3347e860f15SJohn Edward Broadbent                     messages::propertyValueNotInList(
3357e860f15SJohn Edward Broadbent                         asyncResp->res, std::to_string(*optKeyBitLength),
33630215816SMarri Devender Rao                         "KeyBitLength");
33730215816SMarri Devender Rao                     return;
33830215816SMarri Devender Rao                 }
33930215816SMarri Devender Rao 
34030215816SMarri Devender Rao                 // validate KeyUsage supporting only 1 type based on URL
3417e860f15SJohn Edward Broadbent                 if (boost::starts_with(certURI,
3427e860f15SJohn Edward Broadbent                                        "/redfish/v1/Managers/bmc/"
3437e860f15SJohn Edward Broadbent                                        "NetworkProtocol/HTTPS/Certificates"))
34430215816SMarri Devender Rao                 {
34530215816SMarri Devender Rao                     if (optKeyUsage->size() == 0)
34630215816SMarri Devender Rao                     {
34730215816SMarri Devender Rao                         optKeyUsage->push_back("ServerAuthentication");
34830215816SMarri Devender Rao                     }
34930215816SMarri Devender Rao                     else if (optKeyUsage->size() == 1)
35030215816SMarri Devender Rao                     {
35130215816SMarri Devender Rao                         if ((*optKeyUsage)[0] != "ServerAuthentication")
35230215816SMarri Devender Rao                         {
35330215816SMarri Devender Rao                             messages::propertyValueNotInList(
35430215816SMarri Devender Rao                                 asyncResp->res, (*optKeyUsage)[0], "KeyUsage");
35530215816SMarri Devender Rao                             return;
35630215816SMarri Devender Rao                         }
35730215816SMarri Devender Rao                     }
35830215816SMarri Devender Rao                     else
35930215816SMarri Devender Rao                     {
36030215816SMarri Devender Rao                         messages::actionParameterNotSupported(
36130215816SMarri Devender Rao                             asyncResp->res, "KeyUsage", "GenerateCSR");
36230215816SMarri Devender Rao                         return;
36330215816SMarri Devender Rao                     }
36430215816SMarri Devender Rao                 }
3653b7f0149SMarri Devender Rao                 else if (boost::starts_with(
3667e860f15SJohn Edward Broadbent                              certURI,
3677e860f15SJohn Edward Broadbent                              "/redfish/v1/AccountService/LDAP/Certificates"))
3683b7f0149SMarri Devender Rao                 {
3693b7f0149SMarri Devender Rao                     if (optKeyUsage->size() == 0)
3703b7f0149SMarri Devender Rao                     {
3713b7f0149SMarri Devender Rao                         optKeyUsage->push_back("ClientAuthentication");
3723b7f0149SMarri Devender Rao                     }
3733b7f0149SMarri Devender Rao                     else if (optKeyUsage->size() == 1)
3743b7f0149SMarri Devender Rao                     {
3753b7f0149SMarri Devender Rao                         if ((*optKeyUsage)[0] != "ClientAuthentication")
3763b7f0149SMarri Devender Rao                         {
3773b7f0149SMarri Devender Rao                             messages::propertyValueNotInList(
3783b7f0149SMarri Devender Rao                                 asyncResp->res, (*optKeyUsage)[0], "KeyUsage");
3793b7f0149SMarri Devender Rao                             return;
3803b7f0149SMarri Devender Rao                         }
3813b7f0149SMarri Devender Rao                     }
3823b7f0149SMarri Devender Rao                     else
3833b7f0149SMarri Devender Rao                     {
3843b7f0149SMarri Devender Rao                         messages::actionParameterNotSupported(
3853b7f0149SMarri Devender Rao                             asyncResp->res, "KeyUsage", "GenerateCSR");
3863b7f0149SMarri Devender Rao                         return;
3873b7f0149SMarri Devender Rao                     }
3883b7f0149SMarri Devender Rao                 }
38930215816SMarri Devender Rao 
3907e860f15SJohn Edward Broadbent                 // Only allow one CSR matcher at a time so setting retry
3917e860f15SJohn Edward Broadbent                 // time-out and timer expiry to 10 seconds for now.
3922c70f800SEd Tanous                 static const int timeOut = 10;
39330215816SMarri Devender Rao                 if (csrMatcher)
39430215816SMarri Devender Rao                 {
3957e860f15SJohn Edward Broadbent                     messages::serviceTemporarilyUnavailable(
3967e860f15SJohn Edward Broadbent                         asyncResp->res, std::to_string(timeOut));
39730215816SMarri Devender Rao                     return;
39830215816SMarri Devender Rao                 }
39930215816SMarri Devender Rao 
40030215816SMarri Devender Rao                 // Make this static so it survives outside this method
40130215816SMarri Devender Rao                 static boost::asio::steady_timer timeout(*req.ioService);
4022c70f800SEd Tanous                 timeout.expires_after(std::chrono::seconds(timeOut));
4037e860f15SJohn Edward Broadbent                 timeout.async_wait([asyncResp](
4047e860f15SJohn Edward Broadbent                                        const boost::system::error_code& ec) {
40530215816SMarri Devender Rao                     csrMatcher = nullptr;
40630215816SMarri Devender Rao                     if (ec)
40730215816SMarri Devender Rao                     {
4087e860f15SJohn Edward Broadbent                         // operation_aborted is expected if timer is canceled
4097e860f15SJohn Edward Broadbent                         // before completion.
41030215816SMarri Devender Rao                         if (ec != boost::asio::error::operation_aborted)
41130215816SMarri Devender Rao                         {
41230215816SMarri Devender Rao                             BMCWEB_LOG_ERROR << "Async_wait failed " << ec;
41330215816SMarri Devender Rao                         }
41430215816SMarri Devender Rao                         return;
41530215816SMarri Devender Rao                     }
41630215816SMarri Devender Rao                     BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR";
41730215816SMarri Devender Rao                     messages::internalError(asyncResp->res);
41830215816SMarri Devender Rao                 });
41930215816SMarri Devender Rao 
42030215816SMarri Devender Rao                 // create a matcher to wait on CSR object
42130215816SMarri Devender Rao                 BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath;
4227e860f15SJohn Edward Broadbent                 std::string match(
4237e860f15SJohn Edward Broadbent                     "type='signal',"
42430215816SMarri Devender Rao                     "interface='org.freedesktop.DBus.ObjectManager',"
42530215816SMarri Devender Rao                     "path='" +
42630215816SMarri Devender Rao                     objectPath +
42730215816SMarri Devender Rao                     "',"
42830215816SMarri Devender Rao                     "member='InterfacesAdded'");
42930215816SMarri Devender Rao                 csrMatcher = std::make_unique<sdbusplus::bus::match::match>(
43030215816SMarri Devender Rao                     *crow::connections::systemBus, match,
43130215816SMarri Devender Rao                     [asyncResp, service, objectPath,
43230215816SMarri Devender Rao                      certURI](sdbusplus::message::message& m) {
433271584abSEd Tanous                         timeout.cancel();
43430215816SMarri Devender Rao                         if (m.is_method_error())
43530215816SMarri Devender Rao                         {
43630215816SMarri Devender Rao                             BMCWEB_LOG_ERROR << "Dbus method error!!!";
43730215816SMarri Devender Rao                             messages::internalError(asyncResp->res);
43830215816SMarri Devender Rao                             return;
43930215816SMarri Devender Rao                         }
44030215816SMarri Devender Rao                         std::vector<std::pair<
4417e860f15SJohn Edward Broadbent                             std::string,
4427e860f15SJohn Edward Broadbent                             std::vector<std::pair<std::string,
4437e860f15SJohn Edward Broadbent                                                   std::variant<std::string>>>>>
44430215816SMarri Devender Rao                             interfacesProperties;
44530215816SMarri Devender Rao                         sdbusplus::message::object_path csrObjectPath;
44630215816SMarri Devender Rao                         m.read(csrObjectPath, interfacesProperties);
4477e860f15SJohn Edward Broadbent                         BMCWEB_LOG_DEBUG << "CSR object added"
4487e860f15SJohn Edward Broadbent                                          << csrObjectPath.str;
44930215816SMarri Devender Rao                         for (auto& interface : interfacesProperties)
45030215816SMarri Devender Rao                         {
4517e860f15SJohn Edward Broadbent                             if (interface.first ==
4527e860f15SJohn Edward Broadbent                                 "xyz.openbmc_project.Certs.CSR")
45330215816SMarri Devender Rao                             {
45430215816SMarri Devender Rao                                 getCSR(asyncResp, certURI, service, objectPath,
45530215816SMarri Devender Rao                                        csrObjectPath.str);
45630215816SMarri Devender Rao                                 break;
45730215816SMarri Devender Rao                             }
45830215816SMarri Devender Rao                         }
45930215816SMarri Devender Rao                     });
46030215816SMarri Devender Rao                 crow::connections::systemBus->async_method_call(
461271584abSEd Tanous                     [asyncResp](const boost::system::error_code& ec,
462cb13a392SEd Tanous                                 const std::string&) {
46330215816SMarri Devender Rao                         if (ec)
46430215816SMarri Devender Rao                         {
4657e860f15SJohn Edward Broadbent                             BMCWEB_LOG_ERROR << "DBUS response error: "
4667e860f15SJohn Edward Broadbent                                              << ec.message();
46730215816SMarri Devender Rao                             messages::internalError(asyncResp->res);
46830215816SMarri Devender Rao                             return;
46930215816SMarri Devender Rao                         }
47030215816SMarri Devender Rao                     },
47130215816SMarri Devender Rao                     service, objectPath, "xyz.openbmc_project.Certs.CSR.Create",
4727e860f15SJohn Edward Broadbent                     "GenerateCSR", *optAlternativeNames, *optChallengePassword,
4737e860f15SJohn Edward Broadbent                     city, commonName, *optContactPerson, country, *optEmail,
4747e860f15SJohn Edward Broadbent                     *optGivenName, *optInitials, *optKeyBitLength,
4757e860f15SJohn Edward Broadbent                     *optKeyCurveId, *optKeyPairAlgorithm, *optKeyUsage,
4767e860f15SJohn Edward Broadbent                     organization, organizationalUnit, state, *optSurname,
4777e860f15SJohn Edward Broadbent                     *optUnstructuredName);
4787e860f15SJohn Edward Broadbent             });
4797e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionGenerateCSR
48030215816SMarri Devender Rao 
4815968caeeSMarri Devender Rao /**
4824e0453b1SGunnar Mills  * @brief Parse and update Certificate Issue/Subject property
4835968caeeSMarri Devender Rao  *
4845968caeeSMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
4855968caeeSMarri Devender Rao  * @param[in] str  Issuer/Subject value in key=value pairs
4865968caeeSMarri Devender Rao  * @param[in] type Issuer/Subject
4875968caeeSMarri Devender Rao  * @return None
4885968caeeSMarri Devender Rao  */
4895968caeeSMarri Devender Rao static void updateCertIssuerOrSubject(nlohmann::json& out,
4905968caeeSMarri Devender Rao                                       const std::string_view value)
4915968caeeSMarri Devender Rao {
4925968caeeSMarri Devender Rao     // example: O=openbmc-project.xyz,CN=localhost
4935968caeeSMarri Devender Rao     std::string_view::iterator i = value.begin();
4945968caeeSMarri Devender Rao     while (i != value.end())
4955968caeeSMarri Devender Rao     {
4965968caeeSMarri Devender Rao         std::string_view::iterator tokenBegin = i;
4975968caeeSMarri Devender Rao         while (i != value.end() && *i != '=')
4985968caeeSMarri Devender Rao         {
49917a897dfSManojkiran Eda             ++i;
5005968caeeSMarri Devender Rao         }
5015968caeeSMarri Devender Rao         if (i == value.end())
5025968caeeSMarri Devender Rao         {
5035968caeeSMarri Devender Rao             break;
5045968caeeSMarri Devender Rao         }
505271584abSEd Tanous         const std::string_view key(tokenBegin,
506271584abSEd Tanous                                    static_cast<size_t>(i - tokenBegin));
50717a897dfSManojkiran Eda         ++i;
5085968caeeSMarri Devender Rao         tokenBegin = i;
5095968caeeSMarri Devender Rao         while (i != value.end() && *i != ',')
5105968caeeSMarri Devender Rao         {
51117a897dfSManojkiran Eda             ++i;
5125968caeeSMarri Devender Rao         }
513271584abSEd Tanous         const std::string_view val(tokenBegin,
514271584abSEd Tanous                                    static_cast<size_t>(i - tokenBegin));
5155968caeeSMarri Devender Rao         if (key == "L")
5165968caeeSMarri Devender Rao         {
5175968caeeSMarri Devender Rao             out["City"] = val;
5185968caeeSMarri Devender Rao         }
5195968caeeSMarri Devender Rao         else if (key == "CN")
5205968caeeSMarri Devender Rao         {
5215968caeeSMarri Devender Rao             out["CommonName"] = val;
5225968caeeSMarri Devender Rao         }
5235968caeeSMarri Devender Rao         else if (key == "C")
5245968caeeSMarri Devender Rao         {
5255968caeeSMarri Devender Rao             out["Country"] = val;
5265968caeeSMarri Devender Rao         }
5275968caeeSMarri Devender Rao         else if (key == "O")
5285968caeeSMarri Devender Rao         {
5295968caeeSMarri Devender Rao             out["Organization"] = val;
5305968caeeSMarri Devender Rao         }
5315968caeeSMarri Devender Rao         else if (key == "OU")
5325968caeeSMarri Devender Rao         {
5335968caeeSMarri Devender Rao             out["OrganizationalUnit"] = val;
5345968caeeSMarri Devender Rao         }
5355968caeeSMarri Devender Rao         else if (key == "ST")
5365968caeeSMarri Devender Rao         {
5375968caeeSMarri Devender Rao             out["State"] = val;
5385968caeeSMarri Devender Rao         }
5395968caeeSMarri Devender Rao         // skip comma character
5405968caeeSMarri Devender Rao         if (i != value.end())
5415968caeeSMarri Devender Rao         {
54217a897dfSManojkiran Eda             ++i;
5435968caeeSMarri Devender Rao         }
5445968caeeSMarri Devender Rao     }
5455968caeeSMarri Devender Rao }
5465968caeeSMarri Devender Rao 
5475968caeeSMarri Devender Rao /**
5485968caeeSMarri Devender Rao  * @brief Retrieve the certificates properties and append to the response
5495968caeeSMarri Devender Rao  * message
5505968caeeSMarri Devender Rao  *
5515968caeeSMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
5525968caeeSMarri Devender Rao  * @param[in] objectPath  Path of the D-Bus service object
5535968caeeSMarri Devender Rao  * @param[in] certId  Id of the certificate
5545968caeeSMarri Devender Rao  * @param[in] certURL  URL of the certificate object
5555968caeeSMarri Devender Rao  * @param[in] name  name of the certificate
5565968caeeSMarri Devender Rao  * @return None
5575968caeeSMarri Devender Rao  */
5585968caeeSMarri Devender Rao static void getCertificateProperties(
5598d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
5608d1b46d7Szhanghch05     const std::string& objectPath, const std::string& service, long certId,
5618d1b46d7Szhanghch05     const std::string& certURL, const std::string& name)
5625968caeeSMarri Devender Rao {
5635968caeeSMarri Devender Rao     using PropertyType =
5645968caeeSMarri Devender Rao         std::variant<std::string, uint64_t, std::vector<std::string>>;
5655968caeeSMarri Devender Rao     using PropertiesMap = boost::container::flat_map<std::string, PropertyType>;
5665968caeeSMarri Devender Rao     BMCWEB_LOG_DEBUG << "getCertificateProperties Path=" << objectPath
5675968caeeSMarri Devender Rao                      << " certId=" << certId << " certURl=" << certURL;
5685968caeeSMarri Devender Rao     crow::connections::systemBus->async_method_call(
56937cce918SMarri Devender Rao         [asyncResp, certURL, certId, name](const boost::system::error_code ec,
5705968caeeSMarri Devender Rao                                            const PropertiesMap& properties) {
5715968caeeSMarri Devender Rao             if (ec)
5725968caeeSMarri Devender Rao             {
5735968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
5748aae75adSMarri Devender Rao                 messages::resourceNotFound(asyncResp->res, name,
5758aae75adSMarri Devender Rao                                            std::to_string(certId));
5765968caeeSMarri Devender Rao                 return;
5775968caeeSMarri Devender Rao             }
5785968caeeSMarri Devender Rao             asyncResp->res.jsonValue = {
5795968caeeSMarri Devender Rao                 {"@odata.id", certURL},
5805968caeeSMarri Devender Rao                 {"@odata.type", "#Certificate.v1_0_0.Certificate"},
5815968caeeSMarri Devender Rao                 {"Id", std::to_string(certId)},
5825968caeeSMarri Devender Rao                 {"Name", name},
5835968caeeSMarri Devender Rao                 {"Description", name}};
5845968caeeSMarri Devender Rao             for (const auto& property : properties)
5855968caeeSMarri Devender Rao             {
5865968caeeSMarri Devender Rao                 if (property.first == "CertificateString")
5875968caeeSMarri Devender Rao                 {
5885968caeeSMarri Devender Rao                     asyncResp->res.jsonValue["CertificateString"] = "";
5895968caeeSMarri Devender Rao                     const std::string* value =
5905968caeeSMarri Devender Rao                         std::get_if<std::string>(&property.second);
5915968caeeSMarri Devender Rao                     if (value)
5925968caeeSMarri Devender Rao                     {
59337cce918SMarri Devender Rao                         asyncResp->res.jsonValue["CertificateString"] = *value;
5945968caeeSMarri Devender Rao                     }
5955968caeeSMarri Devender Rao                 }
5965968caeeSMarri Devender Rao                 else if (property.first == "KeyUsage")
5975968caeeSMarri Devender Rao                 {
5985968caeeSMarri Devender Rao                     nlohmann::json& keyUsage =
5995968caeeSMarri Devender Rao                         asyncResp->res.jsonValue["KeyUsage"];
6005968caeeSMarri Devender Rao                     keyUsage = nlohmann::json::array();
6015968caeeSMarri Devender Rao                     const std::vector<std::string>* value =
60237cce918SMarri Devender Rao                         std::get_if<std::vector<std::string>>(&property.second);
6035968caeeSMarri Devender Rao                     if (value)
6045968caeeSMarri Devender Rao                     {
6055968caeeSMarri Devender Rao                         for (const std::string& usage : *value)
6065968caeeSMarri Devender Rao                         {
6075968caeeSMarri Devender Rao                             keyUsage.push_back(usage);
6085968caeeSMarri Devender Rao                         }
6095968caeeSMarri Devender Rao                     }
6105968caeeSMarri Devender Rao                 }
6115968caeeSMarri Devender Rao                 else if (property.first == "Issuer")
6125968caeeSMarri Devender Rao                 {
6135968caeeSMarri Devender Rao                     const std::string* value =
6145968caeeSMarri Devender Rao                         std::get_if<std::string>(&property.second);
6155968caeeSMarri Devender Rao                     if (value)
6165968caeeSMarri Devender Rao                     {
6175968caeeSMarri Devender Rao                         updateCertIssuerOrSubject(
6185968caeeSMarri Devender Rao                             asyncResp->res.jsonValue["Issuer"], *value);
6195968caeeSMarri Devender Rao                     }
6205968caeeSMarri Devender Rao                 }
6215968caeeSMarri Devender Rao                 else if (property.first == "Subject")
6225968caeeSMarri Devender Rao                 {
6235968caeeSMarri Devender Rao                     const std::string* value =
6245968caeeSMarri Devender Rao                         std::get_if<std::string>(&property.second);
6255968caeeSMarri Devender Rao                     if (value)
6265968caeeSMarri Devender Rao                     {
6275968caeeSMarri Devender Rao                         updateCertIssuerOrSubject(
62837cce918SMarri Devender Rao                             asyncResp->res.jsonValue["Subject"], *value);
6295968caeeSMarri Devender Rao                     }
6305968caeeSMarri Devender Rao                 }
6315968caeeSMarri Devender Rao                 else if (property.first == "ValidNotAfter")
6325968caeeSMarri Devender Rao                 {
6335968caeeSMarri Devender Rao                     const uint64_t* value =
6345968caeeSMarri Devender Rao                         std::get_if<uint64_t>(&property.second);
6355968caeeSMarri Devender Rao                     if (value)
6365968caeeSMarri Devender Rao                     {
63737cce918SMarri Devender Rao                         std::time_t time = static_cast<std::time_t>(*value);
6385968caeeSMarri Devender Rao                         asyncResp->res.jsonValue["ValidNotAfter"] =
6395968caeeSMarri Devender Rao                             crow::utility::getDateTime(time);
6405968caeeSMarri Devender Rao                     }
6415968caeeSMarri Devender Rao                 }
6425968caeeSMarri Devender Rao                 else if (property.first == "ValidNotBefore")
6435968caeeSMarri Devender Rao                 {
6445968caeeSMarri Devender Rao                     const uint64_t* value =
6455968caeeSMarri Devender Rao                         std::get_if<uint64_t>(&property.second);
6465968caeeSMarri Devender Rao                     if (value)
6475968caeeSMarri Devender Rao                     {
64837cce918SMarri Devender Rao                         std::time_t time = static_cast<std::time_t>(*value);
6495968caeeSMarri Devender Rao                         asyncResp->res.jsonValue["ValidNotBefore"] =
6505968caeeSMarri Devender Rao                             crow::utility::getDateTime(time);
6515968caeeSMarri Devender Rao                     }
6525968caeeSMarri Devender Rao                 }
6535968caeeSMarri Devender Rao             }
6545968caeeSMarri Devender Rao             asyncResp->res.addHeader("Location", certURL);
6555968caeeSMarri Devender Rao         },
6565968caeeSMarri Devender Rao         service, objectPath, certs::dbusPropIntf, "GetAll",
6575968caeeSMarri Devender Rao         certs::certPropIntf);
6585968caeeSMarri Devender Rao }
6595968caeeSMarri Devender Rao 
6605968caeeSMarri Devender Rao using GetObjectType =
6615968caeeSMarri Devender Rao     std::vector<std::pair<std::string, std::vector<std::string>>>;
6625968caeeSMarri Devender Rao 
6635968caeeSMarri Devender Rao /**
6645968caeeSMarri Devender Rao  * Action to replace an existing certificate
6655968caeeSMarri Devender Rao  */
6667e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionsReplaceCertificate(App& app)
6675968caeeSMarri Devender Rao {
6687e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/Actions/"
6695968caeeSMarri Devender Rao                       "CertificateService.ReplaceCertificate/")
670*432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
6717e860f15SJohn Edward Broadbent         .methods(
6727e860f15SJohn Edward Broadbent             boost::beast::http::verb::
6737e860f15SJohn Edward Broadbent                 post)([](const crow::Request& req,
6747e860f15SJohn Edward Broadbent                          const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
6755968caeeSMarri Devender Rao             std::string certificate;
6765968caeeSMarri Devender Rao             nlohmann::json certificateUri;
6775968caeeSMarri Devender Rao             std::optional<std::string> certificateType = "PEM";
6788d1b46d7Szhanghch05 
6795968caeeSMarri Devender Rao             if (!json_util::readJson(req, asyncResp->res, "CertificateString",
6807e860f15SJohn Edward Broadbent                                      certificate, "CertificateUri",
6817e860f15SJohn Edward Broadbent                                      certificateUri, "CertificateType",
6827e860f15SJohn Edward Broadbent                                      certificateType))
6835968caeeSMarri Devender Rao             {
6845968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "Required parameters are missing";
6855968caeeSMarri Devender Rao                 messages::internalError(asyncResp->res);
6865968caeeSMarri Devender Rao                 return;
6875968caeeSMarri Devender Rao             }
6885968caeeSMarri Devender Rao 
6895968caeeSMarri Devender Rao             if (!certificateType)
6905968caeeSMarri Devender Rao             {
6915968caeeSMarri Devender Rao                 // should never happen, but it never hurts to be paranoid.
6925968caeeSMarri Devender Rao                 return;
6935968caeeSMarri Devender Rao             }
6945968caeeSMarri Devender Rao             if (certificateType != "PEM")
6955968caeeSMarri Devender Rao             {
6965968caeeSMarri Devender Rao                 messages::actionParameterNotSupported(
6975968caeeSMarri Devender Rao                     asyncResp->res, "CertificateType", "ReplaceCertificate");
6985968caeeSMarri Devender Rao                 return;
6995968caeeSMarri Devender Rao             }
7005968caeeSMarri Devender Rao 
7015968caeeSMarri Devender Rao             std::string certURI;
7025968caeeSMarri Devender Rao             if (!redfish::json_util::readJson(certificateUri, asyncResp->res,
7035968caeeSMarri Devender Rao                                               "@odata.id", certURI))
7045968caeeSMarri Devender Rao             {
7055968caeeSMarri Devender Rao                 messages::actionParameterMissing(
7065968caeeSMarri Devender Rao                     asyncResp->res, "ReplaceCertificate", "CertificateUri");
7075968caeeSMarri Devender Rao                 return;
7085968caeeSMarri Devender Rao             }
7095968caeeSMarri Devender Rao 
7105968caeeSMarri Devender Rao             BMCWEB_LOG_INFO << "Certificate URI to replace" << certURI;
7115968caeeSMarri Devender Rao             long id = getIDFromURL(certURI);
7125968caeeSMarri Devender Rao             if (id < 0)
7135968caeeSMarri Devender Rao             {
7147e860f15SJohn Edward Broadbent                 messages::actionParameterValueFormatError(
7157e860f15SJohn Edward Broadbent                     asyncResp->res, certURI, "CertificateUri",
7165968caeeSMarri Devender Rao                     "ReplaceCertificate");
7175968caeeSMarri Devender Rao                 return;
7185968caeeSMarri Devender Rao             }
7195968caeeSMarri Devender Rao             std::string objectPath;
7205968caeeSMarri Devender Rao             std::string name;
72137cce918SMarri Devender Rao             std::string service;
7227e860f15SJohn Edward Broadbent             if (boost::starts_with(certURI,
7237e860f15SJohn Edward Broadbent                                    "/redfish/v1/Managers/bmc/NetworkProtocol/"
7247e860f15SJohn Edward Broadbent                                    "HTTPS/Certificates/"))
7255968caeeSMarri Devender Rao             {
7267e860f15SJohn Edward Broadbent                 objectPath = std::string(certs::httpsObjectPath) + "/" +
7277e860f15SJohn Edward Broadbent                              std::to_string(id);
7285968caeeSMarri Devender Rao                 name = "HTTPS certificate";
72937cce918SMarri Devender Rao                 service = certs::httpsServiceName;
73037cce918SMarri Devender Rao             }
73137cce918SMarri Devender Rao             else if (boost::starts_with(
7327e860f15SJohn Edward Broadbent                          certURI,
7337e860f15SJohn Edward Broadbent                          "/redfish/v1/AccountService/LDAP/Certificates/"))
73437cce918SMarri Devender Rao             {
7357e860f15SJohn Edward Broadbent                 objectPath = std::string(certs::ldapObjectPath) + "/" +
7367e860f15SJohn Edward Broadbent                              std::to_string(id);
73737cce918SMarri Devender Rao                 name = "LDAP certificate";
73837cce918SMarri Devender Rao                 service = certs::ldapServiceName;
7395968caeeSMarri Devender Rao             }
740cfcd5f6bSMarri Devender Rao             else if (boost::starts_with(
741cfcd5f6bSMarri Devender Rao                          certURI,
742cfcd5f6bSMarri Devender Rao                          "/redfish/v1/Managers/bmc/Truststore/Certificates/"))
743cfcd5f6bSMarri Devender Rao             {
744cfcd5f6bSMarri Devender Rao                 objectPath = std::string(certs::authorityObjectPath) + "/" +
745cfcd5f6bSMarri Devender Rao                              std::to_string(id);
746cfcd5f6bSMarri Devender Rao                 name = "TrustStore certificate";
747cfcd5f6bSMarri Devender Rao                 service = certs::authorityServiceName;
748cfcd5f6bSMarri Devender Rao             }
7495968caeeSMarri Devender Rao             else
7505968caeeSMarri Devender Rao             {
7515968caeeSMarri Devender Rao                 messages::actionParameterNotSupported(
7525968caeeSMarri Devender Rao                     asyncResp->res, "CertificateUri", "ReplaceCertificate");
7535968caeeSMarri Devender Rao                 return;
7545968caeeSMarri Devender Rao             }
7555968caeeSMarri Devender Rao 
7565968caeeSMarri Devender Rao             std::shared_ptr<CertificateFile> certFile =
7575968caeeSMarri Devender Rao                 std::make_shared<CertificateFile>(certificate);
7585968caeeSMarri Devender Rao             crow::connections::systemBus->async_method_call(
75937cce918SMarri Devender Rao                 [asyncResp, certFile, objectPath, service, certURI, id,
7605968caeeSMarri Devender Rao                  name](const boost::system::error_code ec) {
7615968caeeSMarri Devender Rao                     if (ec)
7625968caeeSMarri Devender Rao                     {
7635968caeeSMarri Devender Rao                         BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
7648aae75adSMarri Devender Rao                         messages::resourceNotFound(asyncResp->res, name,
7658aae75adSMarri Devender Rao                                                    std::to_string(id));
7665968caeeSMarri Devender Rao                         return;
7675968caeeSMarri Devender Rao                     }
76837cce918SMarri Devender Rao                     getCertificateProperties(asyncResp, objectPath, service, id,
7695968caeeSMarri Devender Rao                                              certURI, name);
7705968caeeSMarri Devender Rao                     BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
7715968caeeSMarri Devender Rao                                      << certFile->getCertFilePath();
7725968caeeSMarri Devender Rao                 },
7735968caeeSMarri Devender Rao                 service, objectPath, certs::certReplaceIntf, "Replace",
7745968caeeSMarri Devender Rao                 certFile->getCertFilePath());
7757e860f15SJohn Edward Broadbent         });
7767e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionsReplaceCertificate
7775968caeeSMarri Devender Rao 
7785968caeeSMarri Devender Rao /**
7795968caeeSMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
7805968caeeSMarri Devender Rao  * of a component, account or service.
7815968caeeSMarri Devender Rao  */
7825968caeeSMarri Devender Rao 
7837e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificate(App& app)
7845968caeeSMarri Devender Rao {
7857e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
7867e860f15SJohn Edward Broadbent         app,
7877e860f15SJohn Edward Broadbent         "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/<str>/")
788*432a890cSEd Tanous         .privileges({{"Login"}})
7897e860f15SJohn Edward Broadbent         .methods(
7907e860f15SJohn Edward Broadbent             boost::beast::http::verb::
7917e860f15SJohn Edward Broadbent                 get)([](const crow::Request& req,
7927e860f15SJohn Edward Broadbent                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
7937e860f15SJohn Edward Broadbent                         const std::string& param) -> void {
7947e860f15SJohn Edward Broadbent             if (param.empty())
7955968caeeSMarri Devender Rao             {
7965968caeeSMarri Devender Rao                 messages::internalError(asyncResp->res);
7975968caeeSMarri Devender Rao                 return;
7985968caeeSMarri Devender Rao             }
7995968caeeSMarri Devender Rao             long id = getIDFromURL(req.url);
8005968caeeSMarri Devender Rao 
8017e860f15SJohn Edward Broadbent             BMCWEB_LOG_DEBUG << "HTTPSCertificate::doGet ID="
8027e860f15SJohn Edward Broadbent                              << std::to_string(id);
8035968caeeSMarri Devender Rao             std::string certURL =
8045968caeeSMarri Devender Rao                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" +
8055968caeeSMarri Devender Rao                 std::to_string(id);
8065968caeeSMarri Devender Rao             std::string objectPath = certs::httpsObjectPath;
8075968caeeSMarri Devender Rao             objectPath += "/";
8085968caeeSMarri Devender Rao             objectPath += std::to_string(id);
8097e860f15SJohn Edward Broadbent             getCertificateProperties(asyncResp, objectPath,
8107e860f15SJohn Edward Broadbent                                      certs::httpsServiceName, id, certURL,
8117e860f15SJohn Edward Broadbent                                      "HTTPS Certificate");
8127e860f15SJohn Edward Broadbent         });
8135968caeeSMarri Devender Rao }
8145968caeeSMarri Devender Rao 
8155968caeeSMarri Devender Rao /**
8165968caeeSMarri Devender Rao  * Collection of HTTPS certificates
8175968caeeSMarri Devender Rao  */
8187e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificateCollection(App& app)
8195968caeeSMarri Devender Rao {
8207e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
8215968caeeSMarri Devender Rao                  "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
822*432a890cSEd Tanous         .privileges({{"Login"}})
8237e860f15SJohn Edward Broadbent         .methods(
8247e860f15SJohn Edward Broadbent             boost::beast::http::verb::
8257e860f15SJohn Edward Broadbent                 get)([](const crow::Request&,
8267e860f15SJohn Edward Broadbent                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
8278d1b46d7Szhanghch05             asyncResp->res.jsonValue = {
8285968caeeSMarri Devender Rao                 {"@odata.id",
8295968caeeSMarri Devender Rao                  "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"},
8305968caeeSMarri Devender Rao                 {"@odata.type", "#CertificateCollection.CertificateCollection"},
8315968caeeSMarri Devender Rao                 {"Name", "HTTPS Certificates Collection"},
8325968caeeSMarri Devender Rao                 {"Description", "A Collection of HTTPS certificate instances"}};
8338d1b46d7Szhanghch05 
8345968caeeSMarri Devender Rao             crow::connections::systemBus->async_method_call(
8355968caeeSMarri Devender Rao                 [asyncResp](const boost::system::error_code ec,
8365968caeeSMarri Devender Rao                             const ManagedObjectType& certs) {
8375968caeeSMarri Devender Rao                     if (ec)
8385968caeeSMarri Devender Rao                     {
8395968caeeSMarri Devender Rao                         BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
8405968caeeSMarri Devender Rao                         messages::internalError(asyncResp->res);
8415968caeeSMarri Devender Rao                         return;
8425968caeeSMarri Devender Rao                     }
8437e860f15SJohn Edward Broadbent                     nlohmann::json& members =
8447e860f15SJohn Edward Broadbent                         asyncResp->res.jsonValue["Members"];
8455968caeeSMarri Devender Rao                     members = nlohmann::json::array();
8465968caeeSMarri Devender Rao                     for (const auto& cert : certs)
8475968caeeSMarri Devender Rao                     {
8485968caeeSMarri Devender Rao                         long id = getIDFromURL(cert.first.str);
84937cce918SMarri Devender Rao                         if (id >= 0)
8505968caeeSMarri Devender Rao                         {
8515968caeeSMarri Devender Rao                             members.push_back(
8525968caeeSMarri Devender Rao                                 {{"@odata.id",
8535968caeeSMarri Devender Rao                                   "/redfish/v1/Managers/bmc/"
8545968caeeSMarri Devender Rao                                   "NetworkProtocol/HTTPS/Certificates/" +
8555968caeeSMarri Devender Rao                                       std::to_string(id)}});
8565968caeeSMarri Devender Rao                         }
8575968caeeSMarri Devender Rao                     }
8585968caeeSMarri Devender Rao                     asyncResp->res.jsonValue["Members@odata.count"] =
8595968caeeSMarri Devender Rao                         members.size();
8605968caeeSMarri Devender Rao                 },
86137cce918SMarri Devender Rao                 certs::httpsServiceName, certs::httpsObjectPath,
86237cce918SMarri Devender Rao                 certs::dbusObjManagerIntf, "GetManagedObjects");
8637e860f15SJohn Edward Broadbent         });
8645968caeeSMarri Devender Rao 
8657e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
8667e860f15SJohn Edward Broadbent                  "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
867*432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
8687e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
8697e860f15SJohn Edward Broadbent             [](const crow::Request& req,
8707e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
8715968caeeSMarri Devender Rao                 BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost";
8728d1b46d7Szhanghch05 
8737e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue = {
8747e860f15SJohn Edward Broadbent                     {"Name", "HTTPS Certificate"},
8755968caeeSMarri Devender Rao                     {"Description", "HTTPS Certificate"}};
8765968caeeSMarri Devender Rao 
8777e860f15SJohn Edward Broadbent                 std::string certFileBody =
8787e860f15SJohn Edward Broadbent                     getCertificateFromReqBody(asyncResp, req);
87958eb238fSKowalski, Kamil 
88058eb238fSKowalski, Kamil                 if (certFileBody.empty())
88158eb238fSKowalski, Kamil                 {
8827e860f15SJohn Edward Broadbent                     BMCWEB_LOG_ERROR
8837e860f15SJohn Edward Broadbent                         << "Cannot get certificate from request body.";
884a08752f5SZbigniew Kurzynski                     messages::unrecognizedRequestBody(asyncResp->res);
88558eb238fSKowalski, Kamil                     return;
88658eb238fSKowalski, Kamil                 }
88758eb238fSKowalski, Kamil 
8885968caeeSMarri Devender Rao                 std::shared_ptr<CertificateFile> certFile =
88958eb238fSKowalski, Kamil                     std::make_shared<CertificateFile>(certFileBody);
8905968caeeSMarri Devender Rao 
8915968caeeSMarri Devender Rao                 crow::connections::systemBus->async_method_call(
892656ec7e3SZbigniew Kurzynski                     [asyncResp, certFile](const boost::system::error_code ec,
893656ec7e3SZbigniew Kurzynski                                           const std::string& objectPath) {
8945968caeeSMarri Devender Rao                         if (ec)
8955968caeeSMarri Devender Rao                         {
8965968caeeSMarri Devender Rao                             BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
8975968caeeSMarri Devender Rao                             messages::internalError(asyncResp->res);
8985968caeeSMarri Devender Rao                             return;
8995968caeeSMarri Devender Rao                         }
900656ec7e3SZbigniew Kurzynski                         long certId = getIDFromURL(objectPath);
901656ec7e3SZbigniew Kurzynski                         if (certId < 0)
902656ec7e3SZbigniew Kurzynski                         {
903656ec7e3SZbigniew Kurzynski                             BMCWEB_LOG_ERROR << "Invalid objectPath value"
904656ec7e3SZbigniew Kurzynski                                              << objectPath;
905656ec7e3SZbigniew Kurzynski                             messages::internalError(asyncResp->res);
906656ec7e3SZbigniew Kurzynski                             return;
907656ec7e3SZbigniew Kurzynski                         }
9085968caeeSMarri Devender Rao                         std::string certURL =
9095968caeeSMarri Devender Rao                             "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/"
9105968caeeSMarri Devender Rao                             "Certificates/" +
9115968caeeSMarri Devender Rao                             std::to_string(certId);
9127e860f15SJohn Edward Broadbent                         getCertificateProperties(
9137e860f15SJohn Edward Broadbent                             asyncResp, objectPath, certs::httpsServiceName,
9147e860f15SJohn Edward Broadbent                             certId, certURL, "HTTPS Certificate");
9155968caeeSMarri Devender Rao                         BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
9165968caeeSMarri Devender Rao                                          << certFile->getCertFilePath();
9175968caeeSMarri Devender Rao                     },
91837cce918SMarri Devender Rao                     certs::httpsServiceName, certs::httpsObjectPath,
9197e860f15SJohn Edward Broadbent                     certs::certInstallIntf, "Install",
9207e860f15SJohn Edward Broadbent                     certFile->getCertFilePath());
9217e860f15SJohn Edward Broadbent             });
9227e860f15SJohn Edward Broadbent } // requestRoutesHTTPSCertificateCollection
9235968caeeSMarri Devender Rao 
9245968caeeSMarri Devender Rao /**
92537cce918SMarri Devender Rao  * @brief Retrieve the certificates installed list and append to the
92637cce918SMarri Devender Rao  * response
92737cce918SMarri Devender Rao  *
92837cce918SMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
92937cce918SMarri Devender Rao  * @param[in] certURL  Path of the certificate object
93037cce918SMarri Devender Rao  * @param[in] path  Path of the D-Bus service object
93137cce918SMarri Devender Rao  * @return None
93237cce918SMarri Devender Rao  */
9338d1b46d7Szhanghch05 void getCertificateLocations(
9348d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
9358d1b46d7Szhanghch05     const std::string& certURL, const std::string& path,
93637cce918SMarri Devender Rao     const std::string& service)
93737cce918SMarri Devender Rao {
93837cce918SMarri Devender Rao     BMCWEB_LOG_DEBUG << "getCertificateLocations URI=" << certURL
93937cce918SMarri Devender Rao                      << " Path=" << path << " service= " << service;
94037cce918SMarri Devender Rao     crow::connections::systemBus->async_method_call(
94137cce918SMarri Devender Rao         [asyncResp, certURL](const boost::system::error_code ec,
94237cce918SMarri Devender Rao                              const ManagedObjectType& certs) {
94337cce918SMarri Devender Rao             if (ec)
94437cce918SMarri Devender Rao             {
9459c8e039eSJonathan Doman                 BMCWEB_LOG_WARNING
9469c8e039eSJonathan Doman                     << "Certificate collection query failed: " << ec
9479c8e039eSJonathan Doman                     << ", skipping " << certURL;
94837cce918SMarri Devender Rao                 return;
94937cce918SMarri Devender Rao             }
95037cce918SMarri Devender Rao             nlohmann::json& links =
95137cce918SMarri Devender Rao                 asyncResp->res.jsonValue["Links"]["Certificates"];
95237cce918SMarri Devender Rao             for (auto& cert : certs)
95337cce918SMarri Devender Rao             {
95437cce918SMarri Devender Rao                 long id = getIDFromURL(cert.first.str);
95537cce918SMarri Devender Rao                 if (id >= 0)
95637cce918SMarri Devender Rao                 {
95737cce918SMarri Devender Rao                     links.push_back(
95837cce918SMarri Devender Rao                         {{"@odata.id", certURL + std::to_string(id)}});
95937cce918SMarri Devender Rao                 }
96037cce918SMarri Devender Rao             }
96137cce918SMarri Devender Rao             asyncResp->res.jsonValue["Links"]["Certificates@odata.count"] =
96237cce918SMarri Devender Rao                 links.size();
96337cce918SMarri Devender Rao         },
96437cce918SMarri Devender Rao         service, path, certs::dbusObjManagerIntf, "GetManagedObjects");
9655968caeeSMarri Devender Rao }
9667e860f15SJohn Edward Broadbent 
9677e860f15SJohn Edward Broadbent /**
9687e860f15SJohn Edward Broadbent  * The certificate location schema defines a resource that an administrator
9697e860f15SJohn Edward Broadbent  * can use in order to locate all certificates installed on a given service.
9707e860f15SJohn Edward Broadbent  */
9717e860f15SJohn Edward Broadbent inline void requestRoutesCertificateLocations(App& app)
9727e860f15SJohn Edward Broadbent {
9737e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/")
974*432a890cSEd Tanous         .privileges({{"Login"}})
9757e860f15SJohn Edward Broadbent         .methods(
9767e860f15SJohn Edward Broadbent             boost::beast::http::verb::
9777e860f15SJohn Edward Broadbent                 get)([](const crow::Request&,
9787e860f15SJohn Edward Broadbent                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
9797e860f15SJohn Edward Broadbent             asyncResp->res.jsonValue = {
9807e860f15SJohn Edward Broadbent                 {"@odata.id",
9817e860f15SJohn Edward Broadbent                  "/redfish/v1/CertificateService/CertificateLocations"},
9827e860f15SJohn Edward Broadbent                 {"@odata.type",
9837e860f15SJohn Edward Broadbent                  "#CertificateLocations.v1_0_0.CertificateLocations"},
9847e860f15SJohn Edward Broadbent                 {"Name", "Certificate Locations"},
9857e860f15SJohn Edward Broadbent                 {"Id", "CertificateLocations"},
9867e860f15SJohn Edward Broadbent                 {"Description",
9877e860f15SJohn Edward Broadbent                  "Defines a resource that an administrator can use in order to "
9887e860f15SJohn Edward Broadbent                  "locate all certificates installed on a given service"}};
9897e860f15SJohn Edward Broadbent 
9907e860f15SJohn Edward Broadbent             nlohmann::json& links =
9917e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["Links"]["Certificates"];
9927e860f15SJohn Edward Broadbent             links = nlohmann::json::array();
9937e860f15SJohn Edward Broadbent             getCertificateLocations(
9947e860f15SJohn Edward Broadbent                 asyncResp,
9957e860f15SJohn Edward Broadbent                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/",
9967e860f15SJohn Edward Broadbent                 certs::httpsObjectPath, certs::httpsServiceName);
9977e860f15SJohn Edward Broadbent             getCertificateLocations(
9987e860f15SJohn Edward Broadbent                 asyncResp, "/redfish/v1/AccountService/LDAP/Certificates/",
9997e860f15SJohn Edward Broadbent                 certs::ldapObjectPath, certs::ldapServiceName);
10007e860f15SJohn Edward Broadbent             getCertificateLocations(
10017e860f15SJohn Edward Broadbent                 asyncResp, "/redfish/v1/Managers/bmc/Truststore/Certificates/",
10027e860f15SJohn Edward Broadbent                 certs::authorityObjectPath, certs::authorityServiceName);
10037e860f15SJohn Edward Broadbent         });
10047e860f15SJohn Edward Broadbent }
10057e860f15SJohn Edward Broadbent // requestRoutesCertificateLocations
100637cce918SMarri Devender Rao 
100737cce918SMarri Devender Rao /**
100837cce918SMarri Devender Rao  * Collection of LDAP certificates
100937cce918SMarri Devender Rao  */
10107e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificateCollection(App& app)
101137cce918SMarri Devender Rao {
10127e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
1013*432a890cSEd Tanous         .privileges({{"Login"}})
10147e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
10157e860f15SJohn Edward Broadbent             [](const crow::Request&,
10167e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
10178d1b46d7Szhanghch05                 asyncResp->res.jsonValue = {
10187e860f15SJohn Edward Broadbent                     {"@odata.id",
10197e860f15SJohn Edward Broadbent                      "/redfish/v1/AccountService/LDAP/Certificates"},
10207e860f15SJohn Edward Broadbent                     {"@odata.type",
10217e860f15SJohn Edward Broadbent                      "#CertificateCollection.CertificateCollection"},
102237cce918SMarri Devender Rao                     {"Name", "LDAP Certificates Collection"},
10237e860f15SJohn Edward Broadbent                     {"Description",
10247e860f15SJohn Edward Broadbent                      "A Collection of LDAP certificate instances"}};
10258d1b46d7Szhanghch05 
102637cce918SMarri Devender Rao                 crow::connections::systemBus->async_method_call(
102737cce918SMarri Devender Rao                     [asyncResp](const boost::system::error_code ec,
102837cce918SMarri Devender Rao                                 const ManagedObjectType& certs) {
10297e860f15SJohn Edward Broadbent                         nlohmann::json& members =
10307e860f15SJohn Edward Broadbent                             asyncResp->res.jsonValue["Members"];
10319c8e039eSJonathan Doman                         nlohmann::json& count =
10329c8e039eSJonathan Doman                             asyncResp->res.jsonValue["Members@odata.count"];
10339c8e039eSJonathan Doman                         members = nlohmann::json::array();
10349c8e039eSJonathan Doman                         count = 0;
103537cce918SMarri Devender Rao                         if (ec)
103637cce918SMarri Devender Rao                         {
10377e860f15SJohn Edward Broadbent                             BMCWEB_LOG_WARNING
10387e860f15SJohn Edward Broadbent                                 << "LDAP certificate query failed: " << ec;
103937cce918SMarri Devender Rao                             return;
104037cce918SMarri Devender Rao                         }
104137cce918SMarri Devender Rao                         for (const auto& cert : certs)
104237cce918SMarri Devender Rao                         {
104337cce918SMarri Devender Rao                             long id = getIDFromURL(cert.first.str);
104437cce918SMarri Devender Rao                             if (id >= 0)
104537cce918SMarri Devender Rao                             {
104637cce918SMarri Devender Rao                                 members.push_back(
104737cce918SMarri Devender Rao                                     {{"@odata.id", "/redfish/v1/AccountService/"
104837cce918SMarri Devender Rao                                                    "LDAP/Certificates/" +
104937cce918SMarri Devender Rao                                                        std::to_string(id)}});
105037cce918SMarri Devender Rao                             }
105137cce918SMarri Devender Rao                         }
10529c8e039eSJonathan Doman                         count = members.size();
105337cce918SMarri Devender Rao                     },
105437cce918SMarri Devender Rao                     certs::ldapServiceName, certs::ldapObjectPath,
105537cce918SMarri Devender Rao                     certs::dbusObjManagerIntf, "GetManagedObjects");
10567e860f15SJohn Edward Broadbent             });
105737cce918SMarri Devender Rao 
10587e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
1059*432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
10607e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
10617e860f15SJohn Edward Broadbent             [](const crow::Request& req,
10627e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
10637e860f15SJohn Edward Broadbent                 std::string certFileBody =
10647e860f15SJohn Edward Broadbent                     getCertificateFromReqBody(asyncResp, req);
106558eb238fSKowalski, Kamil 
106658eb238fSKowalski, Kamil                 if (certFileBody.empty())
106758eb238fSKowalski, Kamil                 {
10687e860f15SJohn Edward Broadbent                     BMCWEB_LOG_ERROR
10697e860f15SJohn Edward Broadbent                         << "Cannot get certificate from request body.";
1070a08752f5SZbigniew Kurzynski                     messages::unrecognizedRequestBody(asyncResp->res);
107158eb238fSKowalski, Kamil                     return;
107258eb238fSKowalski, Kamil                 }
107358eb238fSKowalski, Kamil 
107458eb238fSKowalski, Kamil                 std::shared_ptr<CertificateFile> certFile =
107558eb238fSKowalski, Kamil                     std::make_shared<CertificateFile>(certFileBody);
107658eb238fSKowalski, Kamil 
107737cce918SMarri Devender Rao                 crow::connections::systemBus->async_method_call(
1078656ec7e3SZbigniew Kurzynski                     [asyncResp, certFile](const boost::system::error_code ec,
1079656ec7e3SZbigniew Kurzynski                                           const std::string& objectPath) {
108037cce918SMarri Devender Rao                         if (ec)
108137cce918SMarri Devender Rao                         {
108237cce918SMarri Devender Rao                             BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
108337cce918SMarri Devender Rao                             messages::internalError(asyncResp->res);
108437cce918SMarri Devender Rao                             return;
108537cce918SMarri Devender Rao                         }
1086656ec7e3SZbigniew Kurzynski                         long certId = getIDFromURL(objectPath);
1087656ec7e3SZbigniew Kurzynski                         if (certId < 0)
1088656ec7e3SZbigniew Kurzynski                         {
1089656ec7e3SZbigniew Kurzynski                             BMCWEB_LOG_ERROR << "Invalid objectPath value"
1090656ec7e3SZbigniew Kurzynski                                              << objectPath;
1091656ec7e3SZbigniew Kurzynski                             messages::internalError(asyncResp->res);
1092656ec7e3SZbigniew Kurzynski                             return;
1093656ec7e3SZbigniew Kurzynski                         }
109437cce918SMarri Devender Rao                         std::string certURL =
109537cce918SMarri Devender Rao                             "/redfish/v1/AccountService/LDAP/Certificates/" +
109637cce918SMarri Devender Rao                             std::to_string(certId);
109737cce918SMarri Devender Rao                         getCertificateProperties(asyncResp, objectPath,
109837cce918SMarri Devender Rao                                                  certs::ldapServiceName, certId,
109937cce918SMarri Devender Rao                                                  certURL, "LDAP Certificate");
110037cce918SMarri Devender Rao                         BMCWEB_LOG_DEBUG << "LDAP certificate install file="
110137cce918SMarri Devender Rao                                          << certFile->getCertFilePath();
110237cce918SMarri Devender Rao                     },
110337cce918SMarri Devender Rao                     certs::ldapServiceName, certs::ldapObjectPath,
11047e860f15SJohn Edward Broadbent                     certs::certInstallIntf, "Install",
11057e860f15SJohn Edward Broadbent                     certFile->getCertFilePath());
11067e860f15SJohn Edward Broadbent             });
11077e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificateCollection
110837cce918SMarri Devender Rao 
110937cce918SMarri Devender Rao /**
111037cce918SMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
111137cce918SMarri Devender Rao  * of a component, account or service.
111237cce918SMarri Devender Rao  */
11137e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificate(App& app)
111437cce918SMarri Devender Rao {
11157e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/")
1116*432a890cSEd Tanous         .privileges({{"Login"}})
11177e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
11187e860f15SJohn Edward Broadbent             [](const crow::Request& req,
11197e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
11207e860f15SJohn Edward Broadbent                const std::string&) {
112137cce918SMarri Devender Rao                 long id = getIDFromURL(req.url);
112237cce918SMarri Devender Rao                 if (id < 0)
112337cce918SMarri Devender Rao                 {
112437cce918SMarri Devender Rao                     BMCWEB_LOG_ERROR << "Invalid url value" << req.url;
112537cce918SMarri Devender Rao                     messages::internalError(asyncResp->res);
112637cce918SMarri Devender Rao                     return;
112737cce918SMarri Devender Rao                 }
11287e860f15SJohn Edward Broadbent                 BMCWEB_LOG_DEBUG << "LDAP Certificate ID="
11297e860f15SJohn Edward Broadbent                                  << std::to_string(id);
11307e860f15SJohn Edward Broadbent                 std::string certURL =
11317e860f15SJohn Edward Broadbent                     "/redfish/v1/AccountService/LDAP/Certificates/" +
113237cce918SMarri Devender Rao                     std::to_string(id);
113337cce918SMarri Devender Rao                 std::string objectPath = certs::ldapObjectPath;
113437cce918SMarri Devender Rao                 objectPath += "/";
113537cce918SMarri Devender Rao                 objectPath += std::to_string(id);
11367e860f15SJohn Edward Broadbent                 getCertificateProperties(asyncResp, objectPath,
11377e860f15SJohn Edward Broadbent                                          certs::ldapServiceName, id, certURL,
11387e860f15SJohn Edward Broadbent                                          "LDAP Certificate");
11397e860f15SJohn Edward Broadbent             });
11407e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificate
1141cfcd5f6bSMarri Devender Rao /**
1142cfcd5f6bSMarri Devender Rao  * Collection of TrustStoreCertificate certificates
1143cfcd5f6bSMarri Devender Rao  */
11447e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificateCollection(App& app)
1145cfcd5f6bSMarri Devender Rao {
11467e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
1147*432a890cSEd Tanous         .privileges({{"Login"}})
11487e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
11497e860f15SJohn Edward Broadbent             [](const crow::Request&,
11507e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
11518d1b46d7Szhanghch05                 asyncResp->res.jsonValue = {
11527e860f15SJohn Edward Broadbent                     {"@odata.id",
11537e860f15SJohn Edward Broadbent                      "/redfish/v1/Managers/bmc/Truststore/Certificates/"},
11547e860f15SJohn Edward Broadbent                     {"@odata.type",
11557e860f15SJohn Edward Broadbent                      "#CertificateCollection.CertificateCollection"},
1156cfcd5f6bSMarri Devender Rao                     {"Name", "TrustStore Certificates Collection"},
1157cfcd5f6bSMarri Devender Rao                     {"Description",
1158cfcd5f6bSMarri Devender Rao                      "A Collection of TrustStore certificate instances"}};
11598d1b46d7Szhanghch05 
1160cfcd5f6bSMarri Devender Rao                 crow::connections::systemBus->async_method_call(
1161cfcd5f6bSMarri Devender Rao                     [asyncResp](const boost::system::error_code ec,
1162cfcd5f6bSMarri Devender Rao                                 const ManagedObjectType& certs) {
1163cfcd5f6bSMarri Devender Rao                         if (ec)
1164cfcd5f6bSMarri Devender Rao                         {
1165cfcd5f6bSMarri Devender Rao                             BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
1166cfcd5f6bSMarri Devender Rao                             messages::internalError(asyncResp->res);
1167cfcd5f6bSMarri Devender Rao                             return;
1168cfcd5f6bSMarri Devender Rao                         }
11697e860f15SJohn Edward Broadbent                         nlohmann::json& members =
11707e860f15SJohn Edward Broadbent                             asyncResp->res.jsonValue["Members"];
1171cfcd5f6bSMarri Devender Rao                         members = nlohmann::json::array();
1172cfcd5f6bSMarri Devender Rao                         for (const auto& cert : certs)
1173cfcd5f6bSMarri Devender Rao                         {
1174cfcd5f6bSMarri Devender Rao                             long id = getIDFromURL(cert.first.str);
1175cfcd5f6bSMarri Devender Rao                             if (id >= 0)
1176cfcd5f6bSMarri Devender Rao                             {
1177cfcd5f6bSMarri Devender Rao                                 members.push_back(
1178cfcd5f6bSMarri Devender Rao                                     {{"@odata.id", "/redfish/v1/Managers/bmc/"
1179cfcd5f6bSMarri Devender Rao                                                    "Truststore/Certificates/" +
1180cfcd5f6bSMarri Devender Rao                                                        std::to_string(id)}});
1181cfcd5f6bSMarri Devender Rao                             }
1182cfcd5f6bSMarri Devender Rao                         }
1183cfcd5f6bSMarri Devender Rao                         asyncResp->res.jsonValue["Members@odata.count"] =
1184cfcd5f6bSMarri Devender Rao                             members.size();
1185cfcd5f6bSMarri Devender Rao                     },
1186cfcd5f6bSMarri Devender Rao                     certs::authorityServiceName, certs::authorityObjectPath,
1187cfcd5f6bSMarri Devender Rao                     certs::dbusObjManagerIntf, "GetManagedObjects");
11887e860f15SJohn Edward Broadbent             });
1189cfcd5f6bSMarri Devender Rao 
11907e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
1191*432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
11927e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
11937e860f15SJohn Edward Broadbent             [](const crow::Request& req,
11947e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
11957e860f15SJohn Edward Broadbent                 std::string certFileBody =
11967e860f15SJohn Edward Broadbent                     getCertificateFromReqBody(asyncResp, req);
1197a08752f5SZbigniew Kurzynski 
1198a08752f5SZbigniew Kurzynski                 if (certFileBody.empty())
1199a08752f5SZbigniew Kurzynski                 {
12007e860f15SJohn Edward Broadbent                     BMCWEB_LOG_ERROR
12017e860f15SJohn Edward Broadbent                         << "Cannot get certificate from request body.";
1202a08752f5SZbigniew Kurzynski                     messages::unrecognizedRequestBody(asyncResp->res);
1203a08752f5SZbigniew Kurzynski                     return;
1204a08752f5SZbigniew Kurzynski                 }
1205a08752f5SZbigniew Kurzynski 
1206a08752f5SZbigniew Kurzynski                 std::shared_ptr<CertificateFile> certFile =
1207a08752f5SZbigniew Kurzynski                     std::make_shared<CertificateFile>(certFileBody);
1208cfcd5f6bSMarri Devender Rao                 crow::connections::systemBus->async_method_call(
1209656ec7e3SZbigniew Kurzynski                     [asyncResp, certFile](const boost::system::error_code ec,
1210656ec7e3SZbigniew Kurzynski                                           const std::string& objectPath) {
1211cfcd5f6bSMarri Devender Rao                         if (ec)
1212cfcd5f6bSMarri Devender Rao                         {
1213cfcd5f6bSMarri Devender Rao                             BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
1214cfcd5f6bSMarri Devender Rao                             messages::internalError(asyncResp->res);
1215cfcd5f6bSMarri Devender Rao                             return;
1216cfcd5f6bSMarri Devender Rao                         }
1217656ec7e3SZbigniew Kurzynski                         long certId = getIDFromURL(objectPath);
1218656ec7e3SZbigniew Kurzynski                         if (certId < 0)
1219656ec7e3SZbigniew Kurzynski                         {
1220656ec7e3SZbigniew Kurzynski                             BMCWEB_LOG_ERROR << "Invalid objectPath value"
1221656ec7e3SZbigniew Kurzynski                                              << objectPath;
1222656ec7e3SZbigniew Kurzynski                             messages::internalError(asyncResp->res);
1223656ec7e3SZbigniew Kurzynski                             return;
1224656ec7e3SZbigniew Kurzynski                         }
1225cfcd5f6bSMarri Devender Rao                         std::string certURL = "/redfish/v1/Managers/bmc/"
1226cfcd5f6bSMarri Devender Rao                                               "Truststore/Certificates/" +
1227cfcd5f6bSMarri Devender Rao                                               std::to_string(certId);
1228656ec7e3SZbigniew Kurzynski 
12297e860f15SJohn Edward Broadbent                         getCertificateProperties(
12307e860f15SJohn Edward Broadbent                             asyncResp, objectPath, certs::authorityServiceName,
12317e860f15SJohn Edward Broadbent                             certId, certURL, "TrustStore Certificate");
12327e860f15SJohn Edward Broadbent                         BMCWEB_LOG_DEBUG
12337e860f15SJohn Edward Broadbent                             << "TrustStore certificate install file="
1234cfcd5f6bSMarri Devender Rao                             << certFile->getCertFilePath();
1235cfcd5f6bSMarri Devender Rao                     },
1236cfcd5f6bSMarri Devender Rao                     certs::authorityServiceName, certs::authorityObjectPath,
12377e860f15SJohn Edward Broadbent                     certs::certInstallIntf, "Install",
12387e860f15SJohn Edward Broadbent                     certFile->getCertFilePath());
12397e860f15SJohn Edward Broadbent             });
12407e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificateCollection
1241cfcd5f6bSMarri Devender Rao 
1242cfcd5f6bSMarri Devender Rao /**
1243cfcd5f6bSMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
1244cfcd5f6bSMarri Devender Rao  * of a component, account or service.
1245cfcd5f6bSMarri Devender Rao  */
12467e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificate(App& app)
1247cfcd5f6bSMarri Devender Rao {
12487e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
1249*432a890cSEd Tanous         .privileges({{"Loign"}})
12507e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
12517e860f15SJohn Edward Broadbent             [](const crow::Request& req,
12527e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
12537e860f15SJohn Edward Broadbent                const std::string&) {
1254cfcd5f6bSMarri Devender Rao                 long id = getIDFromURL(req.url);
1255cfcd5f6bSMarri Devender Rao                 if (id < 0)
1256cfcd5f6bSMarri Devender Rao                 {
1257cfcd5f6bSMarri Devender Rao                     BMCWEB_LOG_ERROR << "Invalid url value" << req.url;
1258cfcd5f6bSMarri Devender Rao                     messages::internalError(asyncResp->res);
1259cfcd5f6bSMarri Devender Rao                     return;
1260cfcd5f6bSMarri Devender Rao                 }
1261cfcd5f6bSMarri Devender Rao                 BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doGet ID="
1262cfcd5f6bSMarri Devender Rao                                  << std::to_string(id);
1263cfcd5f6bSMarri Devender Rao                 std::string certURL =
1264cfcd5f6bSMarri Devender Rao                     "/redfish/v1/Managers/bmc/Truststore/Certificates/" +
1265cfcd5f6bSMarri Devender Rao                     std::to_string(id);
1266cfcd5f6bSMarri Devender Rao                 std::string objectPath = certs::authorityObjectPath;
1267cfcd5f6bSMarri Devender Rao                 objectPath += "/";
1268cfcd5f6bSMarri Devender Rao                 objectPath += std::to_string(id);
1269cfcd5f6bSMarri Devender Rao                 getCertificateProperties(asyncResp, objectPath,
12707e860f15SJohn Edward Broadbent                                          certs::authorityServiceName, id,
12717e860f15SJohn Edward Broadbent                                          certURL, "TrustStore Certificate");
12727e860f15SJohn Edward Broadbent             });
127307a60299SZbigniew Kurzynski 
12747e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
1275*432a890cSEd Tanous         .privileges({{"ConfigureComponents"}})
12767e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::delete_)(
12777e860f15SJohn Edward Broadbent             [](const crow::Request& req,
12787e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
12797e860f15SJohn Edward Broadbent                const std::string& param) {
12807e860f15SJohn Edward Broadbent                 if (param.empty())
128107a60299SZbigniew Kurzynski                 {
128207a60299SZbigniew Kurzynski                     messages::internalError(asyncResp->res);
128307a60299SZbigniew Kurzynski                     return;
128407a60299SZbigniew Kurzynski                 }
128507a60299SZbigniew Kurzynski 
128607a60299SZbigniew Kurzynski                 long id = getIDFromURL(req.url);
128707a60299SZbigniew Kurzynski                 if (id < 0)
128807a60299SZbigniew Kurzynski                 {
128907a60299SZbigniew Kurzynski                     BMCWEB_LOG_ERROR << "Invalid url value: " << req.url;
12907e860f15SJohn Edward Broadbent                     messages::resourceNotFound(asyncResp->res,
12917e860f15SJohn Edward Broadbent                                                "TrustStore Certificate",
129207a60299SZbigniew Kurzynski                                                std::string(req.url));
129307a60299SZbigniew Kurzynski                     return;
129407a60299SZbigniew Kurzynski                 }
129507a60299SZbigniew Kurzynski                 BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doDelete ID="
129607a60299SZbigniew Kurzynski                                  << std::to_string(id);
129707a60299SZbigniew Kurzynski                 std::string certPath = certs::authorityObjectPath;
129807a60299SZbigniew Kurzynski                 certPath += "/";
129907a60299SZbigniew Kurzynski                 certPath += std::to_string(id);
130007a60299SZbigniew Kurzynski 
130107a60299SZbigniew Kurzynski                 crow::connections::systemBus->async_method_call(
130207a60299SZbigniew Kurzynski                     [asyncResp, id](const boost::system::error_code ec) {
130307a60299SZbigniew Kurzynski                         if (ec)
130407a60299SZbigniew Kurzynski                         {
130507a60299SZbigniew Kurzynski                             messages::resourceNotFound(asyncResp->res,
130607a60299SZbigniew Kurzynski                                                        "TrustStore Certificate",
130707a60299SZbigniew Kurzynski                                                        std::to_string(id));
130807a60299SZbigniew Kurzynski                             return;
130907a60299SZbigniew Kurzynski                         }
131007a60299SZbigniew Kurzynski                         BMCWEB_LOG_INFO << "Certificate deleted";
13117e860f15SJohn Edward Broadbent                         asyncResp->res.result(
13127e860f15SJohn Edward Broadbent                             boost::beast::http::status::no_content);
131307a60299SZbigniew Kurzynski                     },
131407a60299SZbigniew Kurzynski                     certs::authorityServiceName, certPath, certs::objDeleteIntf,
131507a60299SZbigniew Kurzynski                     "Delete");
13167e860f15SJohn Edward Broadbent             });
13177e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificate
13185968caeeSMarri Devender Rao } // namespace redfish
1319