xref: /openbmc/bmcweb/features/redfish/lib/certificate_service.hpp (revision 7e860f1550c8686eec42f7a75bc5f2ef51e756ad)
15968caeeSMarri Devender Rao #pragma once
25968caeeSMarri Devender Rao 
3*7e860f15SJohn 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  */
36*7e860f15SJohn 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 
42*7e860f15SJohn Edward Broadbent inline void requestRoutesCertificateService(App& app)
435968caeeSMarri Devender Rao {
44*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/")
45*7e860f15SJohn Edward Broadbent         .privileges({"Login"})
46*7e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
47*7e860f15SJohn Edward Broadbent             [](const crow::Request&,
48*7e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
498d1b46d7Szhanghch05                 asyncResp->res.jsonValue = {
50*7e860f15SJohn Edward Broadbent                     {"@odata.type",
51*7e860f15SJohn 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"},
55*7e860f15SJohn Edward Broadbent                     {"Description",
56*7e860f15SJohn 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
61*7e860f15SJohn Edward Broadbent                     .jsonValue["Actions"]
62*7e860f15SJohn Edward Broadbent                               ["#CertificateService.ReplaceCertificate"] = {
635968caeeSMarri Devender Rao                     {"target", "/redfish/v1/CertificateService/Actions/"
645968caeeSMarri Devender Rao                                "CertificateService.ReplaceCertificate"},
655968caeeSMarri Devender Rao                     {"CertificateType@Redfish.AllowableValues", {"PEM"}}};
66*7e860f15SJohn Edward Broadbent                 asyncResp->res
67*7e860f15SJohn Edward Broadbent                     .jsonValue["Actions"]["#CertificateService.GenerateCSR"] = {
68*7e860f15SJohn Edward Broadbent                     {"target", "/redfish/v1/CertificateService/Actions/"
6930215816SMarri Devender Rao                                "CertificateService.GenerateCSR"}};
70*7e860f15SJohn Edward Broadbent             });
71*7e860f15SJohn 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  */
227*7e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionGenerateCSR(App& app)
22830215816SMarri Devender Rao {
229*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/Actions/"
23030215816SMarri Devender Rao                       "CertificateService.GenerateCSR/")
231*7e860f15SJohn Edward Broadbent         .privileges({"ConfigureComponents"})
232*7e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
233*7e860f15SJohn Edward Broadbent             [](const crow::Request& req,
234*7e860f15SJohn 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(
262*7e860f15SJohn Edward Broadbent                         req, asyncResp->res, "City", city, "CommonName",
263*7e860f15SJohn Edward Broadbent                         commonName, "ContactPerson", optContactPerson,
264*7e860f15SJohn Edward Broadbent                         "Country", country, "Organization", organization,
265*7e860f15SJohn Edward Broadbent                         "OrganizationalUnit", organizationalUnit, "State",
266*7e860f15SJohn Edward Broadbent                         state, "CertificateCollection", certificateCollection,
267*7e860f15SJohn Edward Broadbent                         "AlternativeNames", optAlternativeNames,
268*7e860f15SJohn Edward Broadbent                         "ChallengePassword", optChallengePassword, "Email",
269*7e860f15SJohn Edward Broadbent                         optEmail, "GivenName", optGivenName, "Initials",
270*7e860f15SJohn Edward Broadbent                         optInitials, "KeyBitLength", optKeyBitLength,
271*7e860f15SJohn Edward Broadbent                         "KeyCurveId", optKeyCurveId, "KeyPairAlgorithm",
272*7e860f15SJohn Edward Broadbent                         optKeyPairAlgorithm, "KeyUsage", optKeyUsage, "Surname",
273*7e860f15SJohn 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
279*7e860f15SJohn Edward Broadbent                 // password, which will likely cause bmcweb to crash on startup
280*7e860f15SJohn Edward Broadbent                 // if this is not set on a post so not allowing the user to set
281*7e860f15SJohn Edward Broadbent                 // value
28230215816SMarri Devender Rao                 if (*optChallengePassword != "")
28330215816SMarri Devender Rao                 {
284*7e860f15SJohn Edward Broadbent                     messages::actionParameterNotSupported(
285*7e860f15SJohn Edward Broadbent                         asyncResp->res, "GenerateCSR", "ChallengePassword");
28630215816SMarri Devender Rao                     return;
28730215816SMarri Devender Rao                 }
28830215816SMarri Devender Rao 
28930215816SMarri Devender Rao                 std::string certURI;
290*7e860f15SJohn Edward Broadbent                 if (!redfish::json_util::readJson(certificateCollection,
291*7e860f15SJohn Edward Broadbent                                                   asyncResp->res, "@odata.id",
292*7e860f15SJohn 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;
299*7e860f15SJohn Edward Broadbent                 if (boost::starts_with(certURI,
300*7e860f15SJohn Edward Broadbent                                        "/redfish/v1/Managers/bmc/"
301*7e860f15SJohn 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(
307*7e860f15SJohn Edward Broadbent                              certURI,
308*7e860f15SJohn 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
321*7e860f15SJohn Edward Broadbent                 if (*optKeyPairAlgorithm != "EC" &&
322*7e860f15SJohn 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 
329*7e860f15SJohn Edward Broadbent                 // supporting only 2048 key bit length for RSA algorithm due to
330*7e860f15SJohn Edward Broadbent                 // time consumed in generating private key
33130215816SMarri Devender Rao                 if (*optKeyPairAlgorithm == "RSA" &&
3322c70f800SEd Tanous                     *optKeyBitLength != rsaKeyBitLength)
33330215816SMarri Devender Rao                 {
334*7e860f15SJohn Edward Broadbent                     messages::propertyValueNotInList(
335*7e860f15SJohn 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
341*7e860f15SJohn Edward Broadbent                 if (boost::starts_with(certURI,
342*7e860f15SJohn Edward Broadbent                                        "/redfish/v1/Managers/bmc/"
343*7e860f15SJohn 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(
366*7e860f15SJohn Edward Broadbent                              certURI,
367*7e860f15SJohn 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 
390*7e860f15SJohn Edward Broadbent                 // Only allow one CSR matcher at a time so setting retry
391*7e860f15SJohn 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                 {
395*7e860f15SJohn Edward Broadbent                     messages::serviceTemporarilyUnavailable(
396*7e860f15SJohn 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));
403*7e860f15SJohn Edward Broadbent                 timeout.async_wait([asyncResp](
404*7e860f15SJohn Edward Broadbent                                        const boost::system::error_code& ec) {
40530215816SMarri Devender Rao                     csrMatcher = nullptr;
40630215816SMarri Devender Rao                     if (ec)
40730215816SMarri Devender Rao                     {
408*7e860f15SJohn Edward Broadbent                         // operation_aborted is expected if timer is canceled
409*7e860f15SJohn 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;
422*7e860f15SJohn Edward Broadbent                 std::string match(
423*7e860f15SJohn 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<
441*7e860f15SJohn Edward Broadbent                             std::string,
442*7e860f15SJohn Edward Broadbent                             std::vector<std::pair<std::string,
443*7e860f15SJohn 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);
447*7e860f15SJohn Edward Broadbent                         BMCWEB_LOG_DEBUG << "CSR object added"
448*7e860f15SJohn Edward Broadbent                                          << csrObjectPath.str;
44930215816SMarri Devender Rao                         for (auto& interface : interfacesProperties)
45030215816SMarri Devender Rao                         {
451*7e860f15SJohn Edward Broadbent                             if (interface.first ==
452*7e860f15SJohn 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                         {
465*7e860f15SJohn Edward Broadbent                             BMCWEB_LOG_ERROR << "DBUS response error: "
466*7e860f15SJohn 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",
472*7e860f15SJohn Edward Broadbent                     "GenerateCSR", *optAlternativeNames, *optChallengePassword,
473*7e860f15SJohn Edward Broadbent                     city, commonName, *optContactPerson, country, *optEmail,
474*7e860f15SJohn Edward Broadbent                     *optGivenName, *optInitials, *optKeyBitLength,
475*7e860f15SJohn Edward Broadbent                     *optKeyCurveId, *optKeyPairAlgorithm, *optKeyUsage,
476*7e860f15SJohn Edward Broadbent                     organization, organizationalUnit, state, *optSurname,
477*7e860f15SJohn Edward Broadbent                     *optUnstructuredName);
478*7e860f15SJohn Edward Broadbent             });
479*7e860f15SJohn 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  */
666*7e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionsReplaceCertificate(App& app)
6675968caeeSMarri Devender Rao {
668*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/Actions/"
6695968caeeSMarri Devender Rao                       "CertificateService.ReplaceCertificate/")
670*7e860f15SJohn Edward Broadbent         .privileges({"ConfigureComponents"})
671*7e860f15SJohn Edward Broadbent         .methods(
672*7e860f15SJohn Edward Broadbent             boost::beast::http::verb::
673*7e860f15SJohn Edward Broadbent                 post)([](const crow::Request& req,
674*7e860f15SJohn 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",
680*7e860f15SJohn Edward Broadbent                                      certificate, "CertificateUri",
681*7e860f15SJohn Edward Broadbent                                      certificateUri, "CertificateType",
682*7e860f15SJohn 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             {
714*7e860f15SJohn Edward Broadbent                 messages::actionParameterValueFormatError(
715*7e860f15SJohn 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;
722*7e860f15SJohn Edward Broadbent             if (boost::starts_with(certURI,
723*7e860f15SJohn Edward Broadbent                                    "/redfish/v1/Managers/bmc/NetworkProtocol/"
724*7e860f15SJohn Edward Broadbent                                    "HTTPS/Certificates/"))
7255968caeeSMarri Devender Rao             {
726*7e860f15SJohn Edward Broadbent                 objectPath = std::string(certs::httpsObjectPath) + "/" +
727*7e860f15SJohn 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(
732*7e860f15SJohn Edward Broadbent                          certURI,
733*7e860f15SJohn Edward Broadbent                          "/redfish/v1/AccountService/LDAP/Certificates/"))
73437cce918SMarri Devender Rao             {
735*7e860f15SJohn Edward Broadbent                 objectPath = std::string(certs::ldapObjectPath) + "/" +
736*7e860f15SJohn 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());
775*7e860f15SJohn Edward Broadbent         });
776*7e860f15SJohn 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 
783*7e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificate(App& app)
7845968caeeSMarri Devender Rao {
785*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
786*7e860f15SJohn Edward Broadbent         app,
787*7e860f15SJohn Edward Broadbent         "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/<str>/")
788*7e860f15SJohn Edward Broadbent         .privileges({"Login"})
789*7e860f15SJohn Edward Broadbent         .methods(
790*7e860f15SJohn Edward Broadbent             boost::beast::http::verb::
791*7e860f15SJohn Edward Broadbent                 get)([](const crow::Request& req,
792*7e860f15SJohn Edward Broadbent                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
793*7e860f15SJohn Edward Broadbent                         const std::string& param) -> void {
794*7e860f15SJohn 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 
801*7e860f15SJohn Edward Broadbent             BMCWEB_LOG_DEBUG << "HTTPSCertificate::doGet ID="
802*7e860f15SJohn 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);
809*7e860f15SJohn Edward Broadbent             getCertificateProperties(asyncResp, objectPath,
810*7e860f15SJohn Edward Broadbent                                      certs::httpsServiceName, id, certURL,
811*7e860f15SJohn Edward Broadbent                                      "HTTPS Certificate");
812*7e860f15SJohn Edward Broadbent         });
8135968caeeSMarri Devender Rao }
8145968caeeSMarri Devender Rao 
8155968caeeSMarri Devender Rao /**
8165968caeeSMarri Devender Rao  * Collection of HTTPS certificates
8175968caeeSMarri Devender Rao  */
818*7e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificateCollection(App& app)
8195968caeeSMarri Devender Rao {
820*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
8215968caeeSMarri Devender Rao                  "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
822*7e860f15SJohn Edward Broadbent         .privileges({"Login"})
823*7e860f15SJohn Edward Broadbent         .methods(
824*7e860f15SJohn Edward Broadbent             boost::beast::http::verb::
825*7e860f15SJohn Edward Broadbent                 get)([](const crow::Request&,
826*7e860f15SJohn 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                     }
843*7e860f15SJohn Edward Broadbent                     nlohmann::json& members =
844*7e860f15SJohn 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");
863*7e860f15SJohn Edward Broadbent         });
8645968caeeSMarri Devender Rao 
865*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
866*7e860f15SJohn Edward Broadbent                  "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
867*7e860f15SJohn Edward Broadbent         .privileges({"ConfigureComponents"})
868*7e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
869*7e860f15SJohn Edward Broadbent             [](const crow::Request& req,
870*7e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
8715968caeeSMarri Devender Rao                 BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost";
8728d1b46d7Szhanghch05 
873*7e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue = {
874*7e860f15SJohn Edward Broadbent                     {"Name", "HTTPS Certificate"},
8755968caeeSMarri Devender Rao                     {"Description", "HTTPS Certificate"}};
8765968caeeSMarri Devender Rao 
877*7e860f15SJohn Edward Broadbent                 std::string certFileBody =
878*7e860f15SJohn Edward Broadbent                     getCertificateFromReqBody(asyncResp, req);
87958eb238fSKowalski, Kamil 
88058eb238fSKowalski, Kamil                 if (certFileBody.empty())
88158eb238fSKowalski, Kamil                 {
882*7e860f15SJohn Edward Broadbent                     BMCWEB_LOG_ERROR
883*7e860f15SJohn 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);
912*7e860f15SJohn Edward Broadbent                         getCertificateProperties(
913*7e860f15SJohn Edward Broadbent                             asyncResp, objectPath, certs::httpsServiceName,
914*7e860f15SJohn 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,
919*7e860f15SJohn Edward Broadbent                     certs::certInstallIntf, "Install",
920*7e860f15SJohn Edward Broadbent                     certFile->getCertFilePath());
921*7e860f15SJohn Edward Broadbent             });
922*7e860f15SJohn 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 }
966*7e860f15SJohn Edward Broadbent 
967*7e860f15SJohn Edward Broadbent /**
968*7e860f15SJohn Edward Broadbent  * The certificate location schema defines a resource that an administrator
969*7e860f15SJohn Edward Broadbent  * can use in order to locate all certificates installed on a given service.
970*7e860f15SJohn Edward Broadbent  */
971*7e860f15SJohn Edward Broadbent inline void requestRoutesCertificateLocations(App& app)
972*7e860f15SJohn Edward Broadbent {
973*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/")
974*7e860f15SJohn Edward Broadbent         .privileges({"Login"})
975*7e860f15SJohn Edward Broadbent         .methods(
976*7e860f15SJohn Edward Broadbent             boost::beast::http::verb::
977*7e860f15SJohn Edward Broadbent                 get)([](const crow::Request&,
978*7e860f15SJohn Edward Broadbent                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
979*7e860f15SJohn Edward Broadbent             asyncResp->res.jsonValue = {
980*7e860f15SJohn Edward Broadbent                 {"@odata.id",
981*7e860f15SJohn Edward Broadbent                  "/redfish/v1/CertificateService/CertificateLocations"},
982*7e860f15SJohn Edward Broadbent                 {"@odata.type",
983*7e860f15SJohn Edward Broadbent                  "#CertificateLocations.v1_0_0.CertificateLocations"},
984*7e860f15SJohn Edward Broadbent                 {"Name", "Certificate Locations"},
985*7e860f15SJohn Edward Broadbent                 {"Id", "CertificateLocations"},
986*7e860f15SJohn Edward Broadbent                 {"Description",
987*7e860f15SJohn Edward Broadbent                  "Defines a resource that an administrator can use in order to "
988*7e860f15SJohn Edward Broadbent                  "locate all certificates installed on a given service"}};
989*7e860f15SJohn Edward Broadbent 
990*7e860f15SJohn Edward Broadbent             nlohmann::json& links =
991*7e860f15SJohn Edward Broadbent                 asyncResp->res.jsonValue["Links"]["Certificates"];
992*7e860f15SJohn Edward Broadbent             links = nlohmann::json::array();
993*7e860f15SJohn Edward Broadbent             getCertificateLocations(
994*7e860f15SJohn Edward Broadbent                 asyncResp,
995*7e860f15SJohn Edward Broadbent                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/",
996*7e860f15SJohn Edward Broadbent                 certs::httpsObjectPath, certs::httpsServiceName);
997*7e860f15SJohn Edward Broadbent             getCertificateLocations(
998*7e860f15SJohn Edward Broadbent                 asyncResp, "/redfish/v1/AccountService/LDAP/Certificates/",
999*7e860f15SJohn Edward Broadbent                 certs::ldapObjectPath, certs::ldapServiceName);
1000*7e860f15SJohn Edward Broadbent             getCertificateLocations(
1001*7e860f15SJohn Edward Broadbent                 asyncResp, "/redfish/v1/Managers/bmc/Truststore/Certificates/",
1002*7e860f15SJohn Edward Broadbent                 certs::authorityObjectPath, certs::authorityServiceName);
1003*7e860f15SJohn Edward Broadbent         });
1004*7e860f15SJohn Edward Broadbent }
1005*7e860f15SJohn Edward Broadbent // requestRoutesCertificateLocations
100637cce918SMarri Devender Rao 
100737cce918SMarri Devender Rao /**
100837cce918SMarri Devender Rao  * Collection of LDAP certificates
100937cce918SMarri Devender Rao  */
1010*7e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificateCollection(App& app)
101137cce918SMarri Devender Rao {
1012*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
1013*7e860f15SJohn Edward Broadbent         .privileges({"Login"})
1014*7e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
1015*7e860f15SJohn Edward Broadbent             [](const crow::Request&,
1016*7e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
10178d1b46d7Szhanghch05                 asyncResp->res.jsonValue = {
1018*7e860f15SJohn Edward Broadbent                     {"@odata.id",
1019*7e860f15SJohn Edward Broadbent                      "/redfish/v1/AccountService/LDAP/Certificates"},
1020*7e860f15SJohn Edward Broadbent                     {"@odata.type",
1021*7e860f15SJohn Edward Broadbent                      "#CertificateCollection.CertificateCollection"},
102237cce918SMarri Devender Rao                     {"Name", "LDAP Certificates Collection"},
1023*7e860f15SJohn Edward Broadbent                     {"Description",
1024*7e860f15SJohn 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) {
1029*7e860f15SJohn Edward Broadbent                         nlohmann::json& members =
1030*7e860f15SJohn 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                         {
1037*7e860f15SJohn Edward Broadbent                             BMCWEB_LOG_WARNING
1038*7e860f15SJohn 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");
1056*7e860f15SJohn Edward Broadbent             });
105737cce918SMarri Devender Rao 
1058*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
1059*7e860f15SJohn Edward Broadbent         .privileges({"ConfigureComponents"})
1060*7e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
1061*7e860f15SJohn Edward Broadbent             [](const crow::Request& req,
1062*7e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1063*7e860f15SJohn Edward Broadbent                 std::string certFileBody =
1064*7e860f15SJohn Edward Broadbent                     getCertificateFromReqBody(asyncResp, req);
106558eb238fSKowalski, Kamil 
106658eb238fSKowalski, Kamil                 if (certFileBody.empty())
106758eb238fSKowalski, Kamil                 {
1068*7e860f15SJohn Edward Broadbent                     BMCWEB_LOG_ERROR
1069*7e860f15SJohn 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,
1104*7e860f15SJohn Edward Broadbent                     certs::certInstallIntf, "Install",
1105*7e860f15SJohn Edward Broadbent                     certFile->getCertFilePath());
1106*7e860f15SJohn Edward Broadbent             });
1107*7e860f15SJohn 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  */
1113*7e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificate(App& app)
111437cce918SMarri Devender Rao {
1115*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/")
1116*7e860f15SJohn Edward Broadbent         .privileges({"Login"})
1117*7e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
1118*7e860f15SJohn Edward Broadbent             [](const crow::Request& req,
1119*7e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1120*7e860f15SJohn 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                 }
1128*7e860f15SJohn Edward Broadbent                 BMCWEB_LOG_DEBUG << "LDAP Certificate ID="
1129*7e860f15SJohn Edward Broadbent                                  << std::to_string(id);
1130*7e860f15SJohn Edward Broadbent                 std::string certURL =
1131*7e860f15SJohn 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);
1136*7e860f15SJohn Edward Broadbent                 getCertificateProperties(asyncResp, objectPath,
1137*7e860f15SJohn Edward Broadbent                                          certs::ldapServiceName, id, certURL,
1138*7e860f15SJohn Edward Broadbent                                          "LDAP Certificate");
1139*7e860f15SJohn Edward Broadbent             });
1140*7e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificate
1141cfcd5f6bSMarri Devender Rao /**
1142cfcd5f6bSMarri Devender Rao  * Collection of TrustStoreCertificate certificates
1143cfcd5f6bSMarri Devender Rao  */
1144*7e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificateCollection(App& app)
1145cfcd5f6bSMarri Devender Rao {
1146*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
1147*7e860f15SJohn Edward Broadbent         .privileges({"Login"})
1148*7e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
1149*7e860f15SJohn Edward Broadbent             [](const crow::Request&,
1150*7e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
11518d1b46d7Szhanghch05                 asyncResp->res.jsonValue = {
1152*7e860f15SJohn Edward Broadbent                     {"@odata.id",
1153*7e860f15SJohn Edward Broadbent                      "/redfish/v1/Managers/bmc/Truststore/Certificates/"},
1154*7e860f15SJohn Edward Broadbent                     {"@odata.type",
1155*7e860f15SJohn 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                         }
1169*7e860f15SJohn Edward Broadbent                         nlohmann::json& members =
1170*7e860f15SJohn 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");
1188*7e860f15SJohn Edward Broadbent             });
1189cfcd5f6bSMarri Devender Rao 
1190*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
1191*7e860f15SJohn Edward Broadbent         .privileges({"ConfigureComponents"})
1192*7e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
1193*7e860f15SJohn Edward Broadbent             [](const crow::Request& req,
1194*7e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
1195*7e860f15SJohn Edward Broadbent                 std::string certFileBody =
1196*7e860f15SJohn Edward Broadbent                     getCertificateFromReqBody(asyncResp, req);
1197a08752f5SZbigniew Kurzynski 
1198a08752f5SZbigniew Kurzynski                 if (certFileBody.empty())
1199a08752f5SZbigniew Kurzynski                 {
1200*7e860f15SJohn Edward Broadbent                     BMCWEB_LOG_ERROR
1201*7e860f15SJohn 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 
1229*7e860f15SJohn Edward Broadbent                         getCertificateProperties(
1230*7e860f15SJohn Edward Broadbent                             asyncResp, objectPath, certs::authorityServiceName,
1231*7e860f15SJohn Edward Broadbent                             certId, certURL, "TrustStore Certificate");
1232*7e860f15SJohn Edward Broadbent                         BMCWEB_LOG_DEBUG
1233*7e860f15SJohn Edward Broadbent                             << "TrustStore certificate install file="
1234cfcd5f6bSMarri Devender Rao                             << certFile->getCertFilePath();
1235cfcd5f6bSMarri Devender Rao                     },
1236cfcd5f6bSMarri Devender Rao                     certs::authorityServiceName, certs::authorityObjectPath,
1237*7e860f15SJohn Edward Broadbent                     certs::certInstallIntf, "Install",
1238*7e860f15SJohn Edward Broadbent                     certFile->getCertFilePath());
1239*7e860f15SJohn Edward Broadbent             });
1240*7e860f15SJohn 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  */
1246*7e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificate(App& app)
1247cfcd5f6bSMarri Devender Rao {
1248*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
1249*7e860f15SJohn Edward Broadbent         .privileges({"Loign"})
1250*7e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
1251*7e860f15SJohn Edward Broadbent             [](const crow::Request& req,
1252*7e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1253*7e860f15SJohn 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,
1270*7e860f15SJohn Edward Broadbent                                          certs::authorityServiceName, id,
1271*7e860f15SJohn Edward Broadbent                                          certURL, "TrustStore Certificate");
1272*7e860f15SJohn Edward Broadbent             });
127307a60299SZbigniew Kurzynski 
1274*7e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
1275*7e860f15SJohn Edward Broadbent         .privileges({"ConfigureComponents"})
1276*7e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::delete_)(
1277*7e860f15SJohn Edward Broadbent             [](const crow::Request& req,
1278*7e860f15SJohn Edward Broadbent                const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
1279*7e860f15SJohn Edward Broadbent                const std::string& param) {
1280*7e860f15SJohn 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;
1290*7e860f15SJohn Edward Broadbent                     messages::resourceNotFound(asyncResp->res,
1291*7e860f15SJohn 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";
1311*7e860f15SJohn Edward Broadbent                         asyncResp->res.result(
1312*7e860f15SJohn Edward Broadbent                             boost::beast::http::status::no_content);
131307a60299SZbigniew Kurzynski                     },
131407a60299SZbigniew Kurzynski                     certs::authorityServiceName, certPath, certs::objDeleteIntf,
131507a60299SZbigniew Kurzynski                     "Delete");
1316*7e860f15SJohn Edward Broadbent             });
1317*7e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificate
13185968caeeSMarri Devender Rao } // namespace redfish
1319