xref: /openbmc/bmcweb/features/redfish/lib/certificate_service.hpp (revision e19e97e247880345aefdf51f557cf1f18d25a5bb)
15968caeeSMarri Devender Rao #pragma once
25968caeeSMarri Devender Rao 
37e860f15SJohn Edward Broadbent #include <app.hpp>
4e6604b11SIwona Klimaszewska #include <boost/convert.hpp>
5e6604b11SIwona Klimaszewska #include <boost/convert/strtol.hpp>
690d2d1e8SJiaqing Zhao #include <boost/system/linux_error.hpp>
7168e20c1SEd Tanous #include <dbus_utility.hpp>
845ca1b86SEd Tanous #include <query.hpp>
9ed398213SEd Tanous #include <registries/privilege_registry.hpp>
101214b7e7SGunnar Mills 
115968caeeSMarri Devender Rao namespace redfish
125968caeeSMarri Devender Rao {
135968caeeSMarri Devender Rao namespace certs
145968caeeSMarri Devender Rao {
155968caeeSMarri Devender Rao constexpr char const* certInstallIntf = "xyz.openbmc_project.Certs.Install";
165968caeeSMarri Devender Rao constexpr char const* certReplaceIntf = "xyz.openbmc_project.Certs.Replace";
1707a60299SZbigniew Kurzynski constexpr char const* objDeleteIntf = "xyz.openbmc_project.Object.Delete";
185968caeeSMarri Devender Rao constexpr char const* certPropIntf = "xyz.openbmc_project.Certs.Certificate";
195968caeeSMarri Devender Rao constexpr char const* dbusPropIntf = "org.freedesktop.DBus.Properties";
205968caeeSMarri Devender Rao constexpr char const* dbusObjManagerIntf = "org.freedesktop.DBus.ObjectManager";
2137cce918SMarri Devender Rao constexpr char const* httpsServiceName =
2237cce918SMarri Devender Rao     "xyz.openbmc_project.Certs.Manager.Server.Https";
2337cce918SMarri Devender Rao constexpr char const* ldapServiceName =
2437cce918SMarri Devender Rao     "xyz.openbmc_project.Certs.Manager.Client.Ldap";
25cfcd5f6bSMarri Devender Rao constexpr char const* authorityServiceName =
26cfcd5f6bSMarri Devender Rao     "xyz.openbmc_project.Certs.Manager.Authority.Ldap";
27c6a8dfb1SJiaqing Zhao constexpr char const* baseObjectPath = "/xyz/openbmc_project/certs";
28c6a8dfb1SJiaqing Zhao constexpr char const* httpsObjectPath =
29c6a8dfb1SJiaqing Zhao     "/xyz/openbmc_project/certs/server/https";
30c6a8dfb1SJiaqing Zhao constexpr char const* ldapObjectPath = "/xyz/openbmc_project/certs/client/ldap";
31cfcd5f6bSMarri Devender Rao constexpr char const* authorityObjectPath =
32cfcd5f6bSMarri Devender Rao     "/xyz/openbmc_project/certs/authority/ldap";
335968caeeSMarri Devender Rao } // namespace certs
345968caeeSMarri Devender Rao 
355968caeeSMarri Devender Rao /**
365968caeeSMarri Devender Rao  * The Certificate schema defines a Certificate Service which represents the
375968caeeSMarri Devender Rao  * actions available to manage certificates and links to where certificates
385968caeeSMarri Devender Rao  * are installed.
395968caeeSMarri Devender Rao  */
407e860f15SJohn Edward Broadbent 
415968caeeSMarri Devender Rao // TODO: Issue#61 No entries are available for Certificate
424e0453b1SGunnar Mills // service at https://www.dmtf.org/standards/redfish
435968caeeSMarri Devender Rao // "redfish standard registries". Need to modify after DMTF
445968caeeSMarri Devender Rao // publish Privilege details for certificate service
455968caeeSMarri Devender Rao 
467e860f15SJohn Edward Broadbent inline void requestRoutesCertificateService(App& app)
475968caeeSMarri Devender Rao {
487e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/")
49ed398213SEd Tanous         .privileges(redfish::privileges::getCertificateService)
50002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
51002d39b4SEd Tanous             [&app](const crow::Request& req,
52002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
533ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
5445ca1b86SEd Tanous         {
5545ca1b86SEd Tanous             return;
5645ca1b86SEd Tanous         }
571476687dSEd Tanous 
581476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
591476687dSEd Tanous             "#CertificateService.v1_0_0.CertificateService";
601476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
611476687dSEd Tanous             "/redfish/v1/CertificateService";
621476687dSEd Tanous         asyncResp->res.jsonValue["Id"] = "CertificateService";
631476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = "Certificate Service";
641476687dSEd Tanous         asyncResp->res.jsonValue["Description"] =
651476687dSEd Tanous             "Actions available to manage certificates";
6672048780SAbhishek Patel         // /redfish/v1/CertificateService/CertificateLocations is something
6772048780SAbhishek Patel         // only ConfigureManager can access then only display when the user
6872048780SAbhishek Patel         // has permissions ConfigureManager
6972048780SAbhishek Patel         Privileges effectiveUserPrivileges =
7072048780SAbhishek Patel             redfish::getUserPrivileges(req.userRole);
7172048780SAbhishek Patel         if (isOperationAllowedWithPrivileges({{"ConfigureManager"}},
7272048780SAbhishek Patel                                              effectiveUserPrivileges))
7372048780SAbhishek Patel         {
741476687dSEd Tanous             asyncResp->res.jsonValue["CertificateLocations"]["@odata.id"] =
751476687dSEd Tanous                 "/redfish/v1/CertificateService/CertificateLocations";
7672048780SAbhishek Patel         }
770fda0f12SGeorge Liu         asyncResp->res
78002d39b4SEd Tanous             .jsonValue["Actions"]["#CertificateService.ReplaceCertificate"] = {
790fda0f12SGeorge Liu             {"target",
800fda0f12SGeorge Liu              "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate"},
815968caeeSMarri Devender Rao             {"CertificateType@Redfish.AllowableValues", {"PEM"}}};
827e860f15SJohn Edward Broadbent         asyncResp->res
837e860f15SJohn Edward Broadbent             .jsonValue["Actions"]["#CertificateService.GenerateCSR"] = {
840fda0f12SGeorge Liu             {"target",
850fda0f12SGeorge Liu              "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR"}};
867e860f15SJohn Edward Broadbent         });
877e860f15SJohn Edward Broadbent } // requestRoutesCertificateService
8837cce918SMarri Devender Rao 
895968caeeSMarri Devender Rao /**
905968caeeSMarri Devender Rao  * @brief Find the ID specified in the URL
915968caeeSMarri Devender Rao  * Finds the numbers specified after the last "/" in the URL and returns.
925968caeeSMarri Devender Rao  * @param[in] path URL
935968caeeSMarri Devender Rao  * @return -1 on failure and number on success
945968caeeSMarri Devender Rao  */
9523a21a1cSEd Tanous inline long getIDFromURL(const std::string_view url)
965968caeeSMarri Devender Rao {
97f23b7296SEd Tanous     std::size_t found = url.rfind('/');
985968caeeSMarri Devender Rao     if (found == std::string::npos)
995968caeeSMarri Devender Rao     {
1005968caeeSMarri Devender Rao         return -1;
1015968caeeSMarri Devender Rao     }
102e6604b11SIwona Klimaszewska 
1035968caeeSMarri Devender Rao     if ((found + 1) < url.length())
1045968caeeSMarri Devender Rao     {
1055968caeeSMarri Devender Rao         std::string_view str = url.substr(found + 1);
106e6604b11SIwona Klimaszewska 
107e6604b11SIwona Klimaszewska         return boost::convert<long>(str, boost::cnv::strtol()).value_or(-1);
1085968caeeSMarri Devender Rao     }
109e6604b11SIwona Klimaszewska 
1105968caeeSMarri Devender Rao     return -1;
1115968caeeSMarri Devender Rao }
1125968caeeSMarri Devender Rao 
1138d1b46d7Szhanghch05 inline std::string getCertificateFromReqBody(
1148d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
11558eb238fSKowalski, Kamil     const crow::Request& req)
11658eb238fSKowalski, Kamil {
11758eb238fSKowalski, Kamil     nlohmann::json reqJson = nlohmann::json::parse(req.body, nullptr, false);
11858eb238fSKowalski, Kamil 
11958eb238fSKowalski, Kamil     if (reqJson.is_discarded())
12058eb238fSKowalski, Kamil     {
12158eb238fSKowalski, Kamil         // We did not receive JSON request, proceed as it is RAW data
12258eb238fSKowalski, Kamil         return req.body;
12358eb238fSKowalski, Kamil     }
12458eb238fSKowalski, Kamil 
12558eb238fSKowalski, Kamil     std::string certificate;
12658eb238fSKowalski, Kamil     std::optional<std::string> certificateType = "PEM";
12758eb238fSKowalski, Kamil 
12815ed6780SWilly Tu     if (!json_util::readJsonPatch(req, asyncResp->res, "CertificateString",
12915ed6780SWilly Tu                                   certificate, "CertificateType",
13015ed6780SWilly Tu                                   certificateType))
13158eb238fSKowalski, Kamil     {
13258eb238fSKowalski, Kamil         BMCWEB_LOG_ERROR << "Required parameters are missing";
13358eb238fSKowalski, Kamil         messages::internalError(asyncResp->res);
134abb93cddSEd Tanous         return {};
13558eb238fSKowalski, Kamil     }
13658eb238fSKowalski, Kamil 
13758eb238fSKowalski, Kamil     if (*certificateType != "PEM")
13858eb238fSKowalski, Kamil     {
13958eb238fSKowalski, Kamil         messages::propertyValueNotInList(asyncResp->res, *certificateType,
14058eb238fSKowalski, Kamil                                          "CertificateType");
141abb93cddSEd Tanous         return {};
14258eb238fSKowalski, Kamil     }
14358eb238fSKowalski, Kamil 
14458eb238fSKowalski, Kamil     return certificate;
14558eb238fSKowalski, Kamil }
14658eb238fSKowalski, Kamil 
1475968caeeSMarri Devender Rao /**
1485968caeeSMarri Devender Rao  * Class to create a temporary certificate file for uploading to system
1495968caeeSMarri Devender Rao  */
1505968caeeSMarri Devender Rao class CertificateFile
1515968caeeSMarri Devender Rao {
1525968caeeSMarri Devender Rao   public:
1535968caeeSMarri Devender Rao     CertificateFile() = delete;
1545968caeeSMarri Devender Rao     CertificateFile(const CertificateFile&) = delete;
1555968caeeSMarri Devender Rao     CertificateFile& operator=(const CertificateFile&) = delete;
1565968caeeSMarri Devender Rao     CertificateFile(CertificateFile&&) = delete;
1575968caeeSMarri Devender Rao     CertificateFile& operator=(CertificateFile&&) = delete;
1584e23a444SEd Tanous     explicit CertificateFile(const std::string& certString)
1595968caeeSMarri Devender Rao     {
16072d52d25SEd Tanous         std::array<char, 18> dirTemplate = {'/', 't', 'm', 'p', '/', 'C',
1615207438cSEd Tanous                                             'e', 'r', 't', 's', '.', 'X',
1625207438cSEd Tanous                                             'X', 'X', 'X', 'X', 'X', '\0'};
1635207438cSEd Tanous         char* tempDirectory = mkdtemp(dirTemplate.data());
164e662eae8SEd Tanous         if (tempDirectory != nullptr)
1655968caeeSMarri Devender Rao         {
1665968caeeSMarri Devender Rao             certDirectory = tempDirectory;
1675968caeeSMarri Devender Rao             certificateFile = certDirectory / "cert.pem";
1685968caeeSMarri Devender Rao             std::ofstream out(certificateFile, std::ofstream::out |
1695968caeeSMarri Devender Rao                                                    std::ofstream::binary |
1705968caeeSMarri Devender Rao                                                    std::ofstream::trunc);
1715968caeeSMarri Devender Rao             out << certString;
1725968caeeSMarri Devender Rao             out.close();
1738cc8edecSEd Tanous             BMCWEB_LOG_DEBUG << "Creating certificate file"
1748cc8edecSEd Tanous                              << certificateFile.string();
1755968caeeSMarri Devender Rao         }
1765968caeeSMarri Devender Rao     }
1775968caeeSMarri Devender Rao     ~CertificateFile()
1785968caeeSMarri Devender Rao     {
1795968caeeSMarri Devender Rao         if (std::filesystem::exists(certDirectory))
1805968caeeSMarri Devender Rao         {
1818cc8edecSEd Tanous             BMCWEB_LOG_DEBUG << "Removing certificate file"
1828cc8edecSEd Tanous                              << certificateFile.string();
18323a21a1cSEd Tanous             std::error_code ec;
18423a21a1cSEd Tanous             std::filesystem::remove_all(certDirectory, ec);
18523a21a1cSEd Tanous             if (ec)
1865968caeeSMarri Devender Rao             {
1875968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "Failed to remove temp directory"
1888cc8edecSEd Tanous                                  << certDirectory.string();
1895968caeeSMarri Devender Rao             }
1905968caeeSMarri Devender Rao         }
1915968caeeSMarri Devender Rao     }
1925968caeeSMarri Devender Rao     std::string getCertFilePath()
1935968caeeSMarri Devender Rao     {
1945968caeeSMarri Devender Rao         return certificateFile;
1955968caeeSMarri Devender Rao     }
1965968caeeSMarri Devender Rao 
1975968caeeSMarri Devender Rao   private:
1985968caeeSMarri Devender Rao     std::filesystem::path certificateFile;
1995968caeeSMarri Devender Rao     std::filesystem::path certDirectory;
2005968caeeSMarri Devender Rao };
2015968caeeSMarri Devender Rao 
20259d494eeSPatrick Williams static std::unique_ptr<sdbusplus::bus::match_t> csrMatcher;
20330215816SMarri Devender Rao /**
20430215816SMarri Devender Rao  * @brief Read data from CSR D-bus object and set to response
20530215816SMarri Devender Rao  *
20630215816SMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
20730215816SMarri Devender Rao  * @param[in] certURI Link to certifiate collection URI
20830215816SMarri Devender Rao  * @param[in] service D-Bus service name
20930215816SMarri Devender Rao  * @param[in] certObjPath certificate D-Bus object path
21030215816SMarri Devender Rao  * @param[in] csrObjPath CSR D-Bus object path
21130215816SMarri Devender Rao  * @return None
21230215816SMarri Devender Rao  */
2138d1b46d7Szhanghch05 static void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
21430215816SMarri Devender Rao                    const std::string& certURI, const std::string& service,
21530215816SMarri Devender Rao                    const std::string& certObjPath,
21630215816SMarri Devender Rao                    const std::string& csrObjPath)
21730215816SMarri Devender Rao {
21830215816SMarri Devender Rao     BMCWEB_LOG_DEBUG << "getCSR CertObjectPath" << certObjPath
21930215816SMarri Devender Rao                      << " CSRObjectPath=" << csrObjPath
22030215816SMarri Devender Rao                      << " service=" << service;
22130215816SMarri Devender Rao     crow::connections::systemBus->async_method_call(
22230215816SMarri Devender Rao         [asyncResp, certURI](const boost::system::error_code ec,
22330215816SMarri Devender Rao                              const std::string& csr) {
22430215816SMarri Devender Rao         if (ec)
22530215816SMarri Devender Rao         {
22630215816SMarri Devender Rao             BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
22730215816SMarri Devender Rao             messages::internalError(asyncResp->res);
22830215816SMarri Devender Rao             return;
22930215816SMarri Devender Rao         }
23030215816SMarri Devender Rao         if (csr.empty())
23130215816SMarri Devender Rao         {
23230215816SMarri Devender Rao             BMCWEB_LOG_ERROR << "CSR read is empty";
23330215816SMarri Devender Rao             messages::internalError(asyncResp->res);
23430215816SMarri Devender Rao             return;
23530215816SMarri Devender Rao         }
23630215816SMarri Devender Rao         asyncResp->res.jsonValue["CSRString"] = csr;
2371476687dSEd Tanous         asyncResp->res.jsonValue["CertificateCollection"]["@odata.id"] =
2381476687dSEd Tanous             certURI;
23930215816SMarri Devender Rao         },
24030215816SMarri Devender Rao         service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR");
24130215816SMarri Devender Rao }
24230215816SMarri Devender Rao 
24330215816SMarri Devender Rao /**
24430215816SMarri Devender Rao  * Action to Generate CSR
24530215816SMarri Devender Rao  */
2467e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionGenerateCSR(App& app)
24730215816SMarri Devender Rao {
2480fda0f12SGeorge Liu     BMCWEB_ROUTE(
2490fda0f12SGeorge Liu         app,
2500fda0f12SGeorge Liu         "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR/")
2515344ab8eSAbhishek Patel         .privileges(redfish::privileges::postCertificateService)
252002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
253002d39b4SEd Tanous             [&app](const crow::Request& req,
2547e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
2553ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
25645ca1b86SEd Tanous         {
25745ca1b86SEd Tanous             return;
25845ca1b86SEd Tanous         }
2592c70f800SEd Tanous         static const int rsaKeyBitLength = 2048;
2608d1b46d7Szhanghch05 
26130215816SMarri Devender Rao         // Required parameters
26230215816SMarri Devender Rao         std::string city;
26330215816SMarri Devender Rao         std::string commonName;
26430215816SMarri Devender Rao         std::string country;
26530215816SMarri Devender Rao         std::string organization;
26630215816SMarri Devender Rao         std::string organizationalUnit;
26730215816SMarri Devender Rao         std::string state;
26830215816SMarri Devender Rao         nlohmann::json certificateCollection;
26930215816SMarri Devender Rao 
27030215816SMarri Devender Rao         // Optional parameters
27130215816SMarri Devender Rao         std::optional<std::vector<std::string>> optAlternativeNames =
27230215816SMarri Devender Rao             std::vector<std::string>();
27330215816SMarri Devender Rao         std::optional<std::string> optContactPerson = "";
27430215816SMarri Devender Rao         std::optional<std::string> optChallengePassword = "";
27530215816SMarri Devender Rao         std::optional<std::string> optEmail = "";
27630215816SMarri Devender Rao         std::optional<std::string> optGivenName = "";
27730215816SMarri Devender Rao         std::optional<std::string> optInitials = "";
2782c70f800SEd Tanous         std::optional<int64_t> optKeyBitLength = rsaKeyBitLength;
279aaf3206fSVernon Mauery         std::optional<std::string> optKeyCurveId = "secp384r1";
28030215816SMarri Devender Rao         std::optional<std::string> optKeyPairAlgorithm = "EC";
28130215816SMarri Devender Rao         std::optional<std::vector<std::string>> optKeyUsage =
28230215816SMarri Devender Rao             std::vector<std::string>();
28330215816SMarri Devender Rao         std::optional<std::string> optSurname = "";
28430215816SMarri Devender Rao         std::optional<std::string> optUnstructuredName = "";
28515ed6780SWilly Tu         if (!json_util::readJsonAction(
2860fda0f12SGeorge Liu                 req, asyncResp->res, "City", city, "CommonName", commonName,
2870fda0f12SGeorge Liu                 "ContactPerson", optContactPerson, "Country", country,
2880fda0f12SGeorge Liu                 "Organization", organization, "OrganizationalUnit",
2890fda0f12SGeorge Liu                 organizationalUnit, "State", state, "CertificateCollection",
290002d39b4SEd Tanous                 certificateCollection, "AlternativeNames", optAlternativeNames,
291002d39b4SEd Tanous                 "ChallengePassword", optChallengePassword, "Email", optEmail,
292002d39b4SEd Tanous                 "GivenName", optGivenName, "Initials", optInitials,
293002d39b4SEd Tanous                 "KeyBitLength", optKeyBitLength, "KeyCurveId", optKeyCurveId,
2940fda0f12SGeorge Liu                 "KeyPairAlgorithm", optKeyPairAlgorithm, "KeyUsage",
2950fda0f12SGeorge Liu                 optKeyUsage, "Surname", optSurname, "UnstructuredName",
2960fda0f12SGeorge Liu                 optUnstructuredName))
29730215816SMarri Devender Rao         {
29830215816SMarri Devender Rao             return;
29930215816SMarri Devender Rao         }
30030215816SMarri Devender Rao 
30130215816SMarri Devender Rao         // bmcweb has no way to store or decode a private key challenge
3027e860f15SJohn Edward Broadbent         // password, which will likely cause bmcweb to crash on startup
3037e860f15SJohn Edward Broadbent         // if this is not set on a post so not allowing the user to set
3047e860f15SJohn Edward Broadbent         // value
30526f6976fSEd Tanous         if (!optChallengePassword->empty())
30630215816SMarri Devender Rao         {
307002d39b4SEd Tanous             messages::actionParameterNotSupported(asyncResp->res, "GenerateCSR",
308002d39b4SEd Tanous                                                   "ChallengePassword");
30930215816SMarri Devender Rao             return;
31030215816SMarri Devender Rao         }
31130215816SMarri Devender Rao 
31230215816SMarri Devender Rao         std::string certURI;
313002d39b4SEd Tanous         if (!redfish::json_util::readJson(certificateCollection, asyncResp->res,
314002d39b4SEd Tanous                                           "@odata.id", certURI))
31530215816SMarri Devender Rao         {
31630215816SMarri Devender Rao             return;
31730215816SMarri Devender Rao         }
31830215816SMarri Devender Rao 
31930215816SMarri Devender Rao         std::string objectPath;
32030215816SMarri Devender Rao         std::string service;
32111ba3979SEd Tanous         if (certURI.starts_with(
3220fda0f12SGeorge Liu                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"))
32330215816SMarri Devender Rao         {
32430215816SMarri Devender Rao             objectPath = certs::httpsObjectPath;
32530215816SMarri Devender Rao             service = certs::httpsServiceName;
32630215816SMarri Devender Rao         }
32711ba3979SEd Tanous         else if (certURI.starts_with(
32811ba3979SEd Tanous                      "/redfish/v1/AccountService/LDAP/Certificates"))
3293b7f0149SMarri Devender Rao         {
3303b7f0149SMarri Devender Rao             objectPath = certs::ldapObjectPath;
3313b7f0149SMarri Devender Rao             service = certs::ldapServiceName;
3323b7f0149SMarri Devender Rao         }
33330215816SMarri Devender Rao         else
33430215816SMarri Devender Rao         {
33530215816SMarri Devender Rao             messages::actionParameterNotSupported(
33630215816SMarri Devender Rao                 asyncResp->res, "CertificateCollection", "GenerateCSR");
33730215816SMarri Devender Rao             return;
33830215816SMarri Devender Rao         }
33930215816SMarri Devender Rao 
34030215816SMarri Devender Rao         // supporting only EC and RSA algorithm
3410fda0f12SGeorge Liu         if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA")
34230215816SMarri Devender Rao         {
34330215816SMarri Devender Rao             messages::actionParameterNotSupported(
34430215816SMarri Devender Rao                 asyncResp->res, "KeyPairAlgorithm", "GenerateCSR");
34530215816SMarri Devender Rao             return;
34630215816SMarri Devender Rao         }
34730215816SMarri Devender Rao 
3487e860f15SJohn Edward Broadbent         // supporting only 2048 key bit length for RSA algorithm due to
3497e860f15SJohn Edward Broadbent         // time consumed in generating private key
35030215816SMarri Devender Rao         if (*optKeyPairAlgorithm == "RSA" &&
3512c70f800SEd Tanous             *optKeyBitLength != rsaKeyBitLength)
35230215816SMarri Devender Rao         {
353002d39b4SEd Tanous             messages::propertyValueNotInList(asyncResp->res,
354002d39b4SEd Tanous                                              std::to_string(*optKeyBitLength),
35530215816SMarri Devender Rao                                              "KeyBitLength");
35630215816SMarri Devender Rao             return;
35730215816SMarri Devender Rao         }
35830215816SMarri Devender Rao 
35930215816SMarri Devender Rao         // validate KeyUsage supporting only 1 type based on URL
36011ba3979SEd Tanous         if (certURI.starts_with(
3610fda0f12SGeorge Liu                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"))
36230215816SMarri Devender Rao         {
36326f6976fSEd Tanous             if (optKeyUsage->empty())
36430215816SMarri Devender Rao             {
36530215816SMarri Devender Rao                 optKeyUsage->push_back("ServerAuthentication");
36630215816SMarri Devender Rao             }
36730215816SMarri Devender Rao             else if (optKeyUsage->size() == 1)
36830215816SMarri Devender Rao             {
36930215816SMarri Devender Rao                 if ((*optKeyUsage)[0] != "ServerAuthentication")
37030215816SMarri Devender Rao                 {
37130215816SMarri Devender Rao                     messages::propertyValueNotInList(
37230215816SMarri Devender Rao                         asyncResp->res, (*optKeyUsage)[0], "KeyUsage");
37330215816SMarri Devender Rao                     return;
37430215816SMarri Devender Rao                 }
37530215816SMarri Devender Rao             }
37630215816SMarri Devender Rao             else
37730215816SMarri Devender Rao             {
37830215816SMarri Devender Rao                 messages::actionParameterNotSupported(
37930215816SMarri Devender Rao                     asyncResp->res, "KeyUsage", "GenerateCSR");
38030215816SMarri Devender Rao                 return;
38130215816SMarri Devender Rao             }
38230215816SMarri Devender Rao         }
38311ba3979SEd Tanous         else if (certURI.starts_with(
38411ba3979SEd Tanous                      "/redfish/v1/AccountService/LDAP/Certificates"))
3853b7f0149SMarri Devender Rao         {
38626f6976fSEd Tanous             if (optKeyUsage->empty())
3873b7f0149SMarri Devender Rao             {
3883b7f0149SMarri Devender Rao                 optKeyUsage->push_back("ClientAuthentication");
3893b7f0149SMarri Devender Rao             }
3903b7f0149SMarri Devender Rao             else if (optKeyUsage->size() == 1)
3913b7f0149SMarri Devender Rao             {
3923b7f0149SMarri Devender Rao                 if ((*optKeyUsage)[0] != "ClientAuthentication")
3933b7f0149SMarri Devender Rao                 {
3943b7f0149SMarri Devender Rao                     messages::propertyValueNotInList(
3953b7f0149SMarri Devender Rao                         asyncResp->res, (*optKeyUsage)[0], "KeyUsage");
3963b7f0149SMarri Devender Rao                     return;
3973b7f0149SMarri Devender Rao                 }
3983b7f0149SMarri Devender Rao             }
3993b7f0149SMarri Devender Rao             else
4003b7f0149SMarri Devender Rao             {
4013b7f0149SMarri Devender Rao                 messages::actionParameterNotSupported(
4023b7f0149SMarri Devender Rao                     asyncResp->res, "KeyUsage", "GenerateCSR");
4033b7f0149SMarri Devender Rao                 return;
4043b7f0149SMarri Devender Rao             }
4053b7f0149SMarri Devender Rao         }
40630215816SMarri Devender Rao 
4077e860f15SJohn Edward Broadbent         // Only allow one CSR matcher at a time so setting retry
4087e860f15SJohn Edward Broadbent         // time-out and timer expiry to 10 seconds for now.
4092c70f800SEd Tanous         static const int timeOut = 10;
41030215816SMarri Devender Rao         if (csrMatcher)
41130215816SMarri Devender Rao         {
412002d39b4SEd Tanous             messages::serviceTemporarilyUnavailable(asyncResp->res,
413002d39b4SEd Tanous                                                     std::to_string(timeOut));
41430215816SMarri Devender Rao             return;
41530215816SMarri Devender Rao         }
41630215816SMarri Devender Rao 
41730215816SMarri Devender Rao         // Make this static so it survives outside this method
41830215816SMarri Devender Rao         static boost::asio::steady_timer timeout(*req.ioService);
4192c70f800SEd Tanous         timeout.expires_after(std::chrono::seconds(timeOut));
420002d39b4SEd Tanous         timeout.async_wait([asyncResp](const boost::system::error_code& ec) {
42130215816SMarri Devender Rao             csrMatcher = nullptr;
42230215816SMarri Devender Rao             if (ec)
42330215816SMarri Devender Rao             {
4247e860f15SJohn Edward Broadbent                 // operation_aborted is expected if timer is canceled
4257e860f15SJohn Edward Broadbent                 // before completion.
42630215816SMarri Devender Rao                 if (ec != boost::asio::error::operation_aborted)
42730215816SMarri Devender Rao                 {
42830215816SMarri Devender Rao                     BMCWEB_LOG_ERROR << "Async_wait failed " << ec;
42930215816SMarri Devender Rao                 }
43030215816SMarri Devender Rao                 return;
43130215816SMarri Devender Rao             }
43230215816SMarri Devender Rao             BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR";
43330215816SMarri Devender Rao             messages::internalError(asyncResp->res);
43430215816SMarri Devender Rao         });
43530215816SMarri Devender Rao 
43630215816SMarri Devender Rao         // create a matcher to wait on CSR object
43730215816SMarri Devender Rao         BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath;
4380fda0f12SGeorge Liu         std::string match("type='signal',"
43930215816SMarri Devender Rao                           "interface='org.freedesktop.DBus.ObjectManager',"
44030215816SMarri Devender Rao                           "path='" +
44130215816SMarri Devender Rao                           objectPath +
44230215816SMarri Devender Rao                           "',"
44330215816SMarri Devender Rao                           "member='InterfacesAdded'");
44459d494eeSPatrick Williams         csrMatcher = std::make_unique<sdbusplus::bus::match_t>(
44530215816SMarri Devender Rao             *crow::connections::systemBus, match,
44659d494eeSPatrick Williams             [asyncResp, service, objectPath, certURI](sdbusplus::message_t& m) {
447271584abSEd Tanous             timeout.cancel();
44830215816SMarri Devender Rao             if (m.is_method_error())
44930215816SMarri Devender Rao             {
45030215816SMarri Devender Rao                 BMCWEB_LOG_ERROR << "Dbus method error!!!";
45130215816SMarri Devender Rao                 messages::internalError(asyncResp->res);
45230215816SMarri Devender Rao                 return;
45330215816SMarri Devender Rao             }
454b9d36b47SEd Tanous 
455b9d36b47SEd Tanous             dbus::utility::DBusInteracesMap interfacesProperties;
456b9d36b47SEd Tanous 
45730215816SMarri Devender Rao             sdbusplus::message::object_path csrObjectPath;
45830215816SMarri Devender Rao             m.read(csrObjectPath, interfacesProperties);
4590fda0f12SGeorge Liu             BMCWEB_LOG_DEBUG << "CSR object added" << csrObjectPath.str;
46002cad96eSEd Tanous             for (const auto& interface : interfacesProperties)
46130215816SMarri Devender Rao             {
4620fda0f12SGeorge Liu                 if (interface.first == "xyz.openbmc_project.Certs.CSR")
46330215816SMarri Devender Rao                 {
46430215816SMarri Devender Rao                     getCSR(asyncResp, certURI, service, objectPath,
46530215816SMarri Devender Rao                            csrObjectPath.str);
46630215816SMarri Devender Rao                     break;
46730215816SMarri Devender Rao                 }
46830215816SMarri Devender Rao             }
46930215816SMarri Devender Rao             });
47030215816SMarri Devender Rao         crow::connections::systemBus->async_method_call(
471914e2d5dSEd Tanous             [asyncResp](const boost::system::error_code ec,
472cb13a392SEd Tanous                         const std::string&) {
47330215816SMarri Devender Rao             if (ec)
47430215816SMarri Devender Rao             {
475002d39b4SEd Tanous                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec.message();
47630215816SMarri Devender Rao                 messages::internalError(asyncResp->res);
47730215816SMarri Devender Rao                 return;
47830215816SMarri Devender Rao             }
47930215816SMarri Devender Rao             },
48030215816SMarri Devender Rao             service, objectPath, "xyz.openbmc_project.Certs.CSR.Create",
481002d39b4SEd Tanous             "GenerateCSR", *optAlternativeNames, *optChallengePassword, city,
482002d39b4SEd Tanous             commonName, *optContactPerson, country, *optEmail, *optGivenName,
483002d39b4SEd Tanous             *optInitials, *optKeyBitLength, *optKeyCurveId,
4840fda0f12SGeorge Liu             *optKeyPairAlgorithm, *optKeyUsage, organization,
4850fda0f12SGeorge Liu             organizationalUnit, state, *optSurname, *optUnstructuredName);
4867e860f15SJohn Edward Broadbent         });
4877e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionGenerateCSR
48830215816SMarri Devender Rao 
4895968caeeSMarri Devender Rao /**
4904e0453b1SGunnar Mills  * @brief Parse and update Certificate Issue/Subject property
4915968caeeSMarri Devender Rao  *
4925968caeeSMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
4935968caeeSMarri Devender Rao  * @param[in] str  Issuer/Subject value in key=value pairs
4945968caeeSMarri Devender Rao  * @param[in] type Issuer/Subject
4955968caeeSMarri Devender Rao  * @return None
4965968caeeSMarri Devender Rao  */
4975968caeeSMarri Devender Rao static void updateCertIssuerOrSubject(nlohmann::json& out,
4985968caeeSMarri Devender Rao                                       const std::string_view value)
4995968caeeSMarri Devender Rao {
5005968caeeSMarri Devender Rao     // example: O=openbmc-project.xyz,CN=localhost
5015968caeeSMarri Devender Rao     std::string_view::iterator i = value.begin();
5025968caeeSMarri Devender Rao     while (i != value.end())
5035968caeeSMarri Devender Rao     {
5045968caeeSMarri Devender Rao         std::string_view::iterator tokenBegin = i;
5055968caeeSMarri Devender Rao         while (i != value.end() && *i != '=')
5065968caeeSMarri Devender Rao         {
50717a897dfSManojkiran Eda             ++i;
5085968caeeSMarri Devender Rao         }
5095968caeeSMarri Devender Rao         if (i == value.end())
5105968caeeSMarri Devender Rao         {
5115968caeeSMarri Devender Rao             break;
5125968caeeSMarri Devender Rao         }
513271584abSEd Tanous         const std::string_view key(tokenBegin,
514271584abSEd Tanous                                    static_cast<size_t>(i - tokenBegin));
51517a897dfSManojkiran Eda         ++i;
5165968caeeSMarri Devender Rao         tokenBegin = i;
5175968caeeSMarri Devender Rao         while (i != value.end() && *i != ',')
5185968caeeSMarri Devender Rao         {
51917a897dfSManojkiran Eda             ++i;
5205968caeeSMarri Devender Rao         }
521271584abSEd Tanous         const std::string_view val(tokenBegin,
522271584abSEd Tanous                                    static_cast<size_t>(i - tokenBegin));
5235968caeeSMarri Devender Rao         if (key == "L")
5245968caeeSMarri Devender Rao         {
5255968caeeSMarri Devender Rao             out["City"] = val;
5265968caeeSMarri Devender Rao         }
5275968caeeSMarri Devender Rao         else if (key == "CN")
5285968caeeSMarri Devender Rao         {
5295968caeeSMarri Devender Rao             out["CommonName"] = val;
5305968caeeSMarri Devender Rao         }
5315968caeeSMarri Devender Rao         else if (key == "C")
5325968caeeSMarri Devender Rao         {
5335968caeeSMarri Devender Rao             out["Country"] = val;
5345968caeeSMarri Devender Rao         }
5355968caeeSMarri Devender Rao         else if (key == "O")
5365968caeeSMarri Devender Rao         {
5375968caeeSMarri Devender Rao             out["Organization"] = val;
5385968caeeSMarri Devender Rao         }
5395968caeeSMarri Devender Rao         else if (key == "OU")
5405968caeeSMarri Devender Rao         {
5415968caeeSMarri Devender Rao             out["OrganizationalUnit"] = val;
5425968caeeSMarri Devender Rao         }
5435968caeeSMarri Devender Rao         else if (key == "ST")
5445968caeeSMarri Devender Rao         {
5455968caeeSMarri Devender Rao             out["State"] = val;
5465968caeeSMarri Devender Rao         }
5475968caeeSMarri Devender Rao         // skip comma character
5485968caeeSMarri Devender Rao         if (i != value.end())
5495968caeeSMarri Devender Rao         {
55017a897dfSManojkiran Eda             ++i;
5515968caeeSMarri Devender Rao         }
5525968caeeSMarri Devender Rao     }
5535968caeeSMarri Devender Rao }
5545968caeeSMarri Devender Rao 
5555968caeeSMarri Devender Rao /**
556d3f92ce7SJiaqing Zhao  * @brief Retrieve the installed certificate list
557d3f92ce7SJiaqing Zhao  *
558d3f92ce7SJiaqing Zhao  * @param[in] asyncResp Shared pointer to the response message
559d3f92ce7SJiaqing Zhao  * @param[in] basePath DBus object path to search
560d3f92ce7SJiaqing Zhao  * @param[in] listPtr Json pointer to the list in asyncResp
561d3f92ce7SJiaqing Zhao  * @param[in] countPtr Json pointer to the count in asyncResp
562d3f92ce7SJiaqing Zhao  * @return None
563d3f92ce7SJiaqing Zhao  */
564d3f92ce7SJiaqing Zhao static void
565d3f92ce7SJiaqing Zhao     getCertificateList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
566d3f92ce7SJiaqing Zhao                        const std::string& basePath,
567d3f92ce7SJiaqing Zhao                        const nlohmann::json::json_pointer& listPtr,
568d3f92ce7SJiaqing Zhao                        const nlohmann::json::json_pointer& countPtr)
569d3f92ce7SJiaqing Zhao {
570d3f92ce7SJiaqing Zhao     crow::connections::systemBus->async_method_call(
571d3f92ce7SJiaqing Zhao         [asyncResp, listPtr, countPtr](
572d3f92ce7SJiaqing Zhao             const boost::system::error_code ec,
573d3f92ce7SJiaqing Zhao             const dbus::utility::MapperGetSubTreePathsResponse& certPaths) {
574d3f92ce7SJiaqing Zhao         if (ec)
575d3f92ce7SJiaqing Zhao         {
576d3f92ce7SJiaqing Zhao             BMCWEB_LOG_ERROR << "Certificate collection query failed: " << ec;
577d3f92ce7SJiaqing Zhao             messages::internalError(asyncResp->res);
578d3f92ce7SJiaqing Zhao             return;
579d3f92ce7SJiaqing Zhao         }
580d3f92ce7SJiaqing Zhao 
581d3f92ce7SJiaqing Zhao         nlohmann::json& links = asyncResp->res.jsonValue[listPtr];
582d3f92ce7SJiaqing Zhao         links = nlohmann::json::array();
583d3f92ce7SJiaqing Zhao         for (const auto& certPath : certPaths)
584d3f92ce7SJiaqing Zhao         {
585d3f92ce7SJiaqing Zhao             sdbusplus::message::object_path objPath(certPath);
586d3f92ce7SJiaqing Zhao             std::string certId = objPath.filename();
587d3f92ce7SJiaqing Zhao             if (certId.empty())
588d3f92ce7SJiaqing Zhao             {
589d3f92ce7SJiaqing Zhao                 BMCWEB_LOG_ERROR << "Invalid certificate objPath " << certPath;
590d3f92ce7SJiaqing Zhao                 continue;
591d3f92ce7SJiaqing Zhao             }
592d3f92ce7SJiaqing Zhao 
593d3f92ce7SJiaqing Zhao             boost::urls::url certURL;
594d3f92ce7SJiaqing Zhao             if (objPath.parent_path() == certs::httpsObjectPath)
595d3f92ce7SJiaqing Zhao             {
596d3f92ce7SJiaqing Zhao                 certURL = crow::utility::urlFromPieces(
597d3f92ce7SJiaqing Zhao                     "redfish", "v1", "Managers", "bmc", "NetworkProtocol",
598d3f92ce7SJiaqing Zhao                     "HTTPS", "Certificates", certId);
599d3f92ce7SJiaqing Zhao             }
600d3f92ce7SJiaqing Zhao             else if (objPath.parent_path() == certs::ldapObjectPath)
601d3f92ce7SJiaqing Zhao             {
602d3f92ce7SJiaqing Zhao                 certURL = crow::utility::urlFromPieces("redfish", "v1",
603d3f92ce7SJiaqing Zhao                                                        "AccountService", "LDAP",
604d3f92ce7SJiaqing Zhao                                                        "Certificates", certId);
605d3f92ce7SJiaqing Zhao             }
606d3f92ce7SJiaqing Zhao             else if (objPath.parent_path() == certs::authorityObjectPath)
607d3f92ce7SJiaqing Zhao             {
608d3f92ce7SJiaqing Zhao                 certURL = crow::utility::urlFromPieces(
609d3f92ce7SJiaqing Zhao                     "redfish", "v1", "Managers", "bmc", "Truststore",
610d3f92ce7SJiaqing Zhao                     "Certificates", certId);
611d3f92ce7SJiaqing Zhao             }
612d3f92ce7SJiaqing Zhao             else
613d3f92ce7SJiaqing Zhao             {
614d3f92ce7SJiaqing Zhao                 continue;
615d3f92ce7SJiaqing Zhao             }
616d3f92ce7SJiaqing Zhao 
617d3f92ce7SJiaqing Zhao             nlohmann::json::object_t link;
618d3f92ce7SJiaqing Zhao             link["@odata.id"] = certURL;
619d3f92ce7SJiaqing Zhao             links.emplace_back(std::move(link));
620d3f92ce7SJiaqing Zhao         }
621d3f92ce7SJiaqing Zhao 
622d3f92ce7SJiaqing Zhao         asyncResp->res.jsonValue[countPtr] = links.size();
623d3f92ce7SJiaqing Zhao         },
624d3f92ce7SJiaqing Zhao         "xyz.openbmc_project.ObjectMapper",
625d3f92ce7SJiaqing Zhao         "/xyz/openbmc_project/object_mapper",
626d3f92ce7SJiaqing Zhao         "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", basePath, 0,
627d3f92ce7SJiaqing Zhao         std::array<const char*, 1>{certs::certPropIntf});
628d3f92ce7SJiaqing Zhao }
629d3f92ce7SJiaqing Zhao 
630d3f92ce7SJiaqing Zhao /**
6315968caeeSMarri Devender Rao  * @brief Retrieve the certificates properties and append to the response
6325968caeeSMarri Devender Rao  * message
6335968caeeSMarri Devender Rao  *
6345968caeeSMarri Devender Rao  * @param[in] asyncResp Shared pointer to the response message
6355968caeeSMarri Devender Rao  * @param[in] objectPath  Path of the D-Bus service object
6365968caeeSMarri Devender Rao  * @param[in] certId  Id of the certificate
6375968caeeSMarri Devender Rao  * @param[in] certURL  URL of the certificate object
6385968caeeSMarri Devender Rao  * @param[in] name  name of the certificate
6395968caeeSMarri Devender Rao  * @return None
6405968caeeSMarri Devender Rao  */
6415968caeeSMarri Devender Rao static void getCertificateProperties(
6428d1b46d7Szhanghch05     const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
643*e19e97e2SJiaqing Zhao     const std::string& objectPath, const std::string& service,
644*e19e97e2SJiaqing Zhao     const std::string& certId, const std::string& certURL,
645*e19e97e2SJiaqing Zhao     const std::string& name)
6465968caeeSMarri Devender Rao {
6475968caeeSMarri Devender Rao     BMCWEB_LOG_DEBUG << "getCertificateProperties Path=" << objectPath
6485968caeeSMarri Devender Rao                      << " certId=" << certId << " certURl=" << certURL;
6495968caeeSMarri Devender Rao     crow::connections::systemBus->async_method_call(
650b9d36b47SEd Tanous         [asyncResp, certURL, certId,
651b9d36b47SEd Tanous          name](const boost::system::error_code ec,
652b9d36b47SEd Tanous                const dbus::utility::DBusPropertiesMap& properties) {
6535968caeeSMarri Devender Rao         if (ec)
6545968caeeSMarri Devender Rao         {
6555968caeeSMarri Devender Rao             BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
656*e19e97e2SJiaqing Zhao             messages::resourceNotFound(asyncResp->res, name, certId);
6575968caeeSMarri Devender Rao             return;
6585968caeeSMarri Devender Rao         }
6591476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] = certURL;
6601476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
6611476687dSEd Tanous             "#Certificate.v1_0_0.Certificate";
662*e19e97e2SJiaqing Zhao         asyncResp->res.jsonValue["Id"] = certId;
6631476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = name;
6641476687dSEd Tanous         asyncResp->res.jsonValue["Description"] = name;
6655968caeeSMarri Devender Rao         for (const auto& property : properties)
6665968caeeSMarri Devender Rao         {
6675968caeeSMarri Devender Rao             if (property.first == "CertificateString")
6685968caeeSMarri Devender Rao             {
6695968caeeSMarri Devender Rao                 asyncResp->res.jsonValue["CertificateString"] = "";
6705968caeeSMarri Devender Rao                 const std::string* value =
6715968caeeSMarri Devender Rao                     std::get_if<std::string>(&property.second);
672e662eae8SEd Tanous                 if (value != nullptr)
6735968caeeSMarri Devender Rao                 {
67437cce918SMarri Devender Rao                     asyncResp->res.jsonValue["CertificateString"] = *value;
6755968caeeSMarri Devender Rao                 }
6765968caeeSMarri Devender Rao             }
6775968caeeSMarri Devender Rao             else if (property.first == "KeyUsage")
6785968caeeSMarri Devender Rao             {
679002d39b4SEd Tanous                 nlohmann::json& keyUsage = asyncResp->res.jsonValue["KeyUsage"];
6805968caeeSMarri Devender Rao                 keyUsage = nlohmann::json::array();
6815968caeeSMarri Devender Rao                 const std::vector<std::string>* value =
68237cce918SMarri Devender Rao                     std::get_if<std::vector<std::string>>(&property.second);
683e662eae8SEd Tanous                 if (value != nullptr)
6845968caeeSMarri Devender Rao                 {
6855968caeeSMarri Devender Rao                     for (const std::string& usage : *value)
6865968caeeSMarri Devender Rao                     {
6875968caeeSMarri Devender Rao                         keyUsage.push_back(usage);
6885968caeeSMarri Devender Rao                     }
6895968caeeSMarri Devender Rao                 }
6905968caeeSMarri Devender Rao             }
6915968caeeSMarri Devender Rao             else if (property.first == "Issuer")
6925968caeeSMarri Devender Rao             {
6935968caeeSMarri Devender Rao                 const std::string* value =
6945968caeeSMarri Devender Rao                     std::get_if<std::string>(&property.second);
695e662eae8SEd Tanous                 if (value != nullptr)
6965968caeeSMarri Devender Rao                 {
6975968caeeSMarri Devender Rao                     updateCertIssuerOrSubject(
6985968caeeSMarri Devender Rao                         asyncResp->res.jsonValue["Issuer"], *value);
6995968caeeSMarri Devender Rao                 }
7005968caeeSMarri Devender Rao             }
7015968caeeSMarri Devender Rao             else if (property.first == "Subject")
7025968caeeSMarri Devender Rao             {
7035968caeeSMarri Devender Rao                 const std::string* value =
7045968caeeSMarri Devender Rao                     std::get_if<std::string>(&property.second);
705e662eae8SEd Tanous                 if (value != nullptr)
7065968caeeSMarri Devender Rao                 {
7075968caeeSMarri Devender Rao                     updateCertIssuerOrSubject(
70837cce918SMarri Devender Rao                         asyncResp->res.jsonValue["Subject"], *value);
7095968caeeSMarri Devender Rao                 }
7105968caeeSMarri Devender Rao             }
7115968caeeSMarri Devender Rao             else if (property.first == "ValidNotAfter")
7125968caeeSMarri Devender Rao             {
713002d39b4SEd Tanous                 const uint64_t* value = std::get_if<uint64_t>(&property.second);
714e662eae8SEd Tanous                 if (value != nullptr)
7155968caeeSMarri Devender Rao                 {
7165968caeeSMarri Devender Rao                     asyncResp->res.jsonValue["ValidNotAfter"] =
7171d8782e7SNan Zhou                         crow::utility::getDateTimeUint(*value);
7185968caeeSMarri Devender Rao                 }
7195968caeeSMarri Devender Rao             }
7205968caeeSMarri Devender Rao             else if (property.first == "ValidNotBefore")
7215968caeeSMarri Devender Rao             {
722002d39b4SEd Tanous                 const uint64_t* value = std::get_if<uint64_t>(&property.second);
723e662eae8SEd Tanous                 if (value != nullptr)
7245968caeeSMarri Devender Rao                 {
7255968caeeSMarri Devender Rao                     asyncResp->res.jsonValue["ValidNotBefore"] =
7261d8782e7SNan Zhou                         crow::utility::getDateTimeUint(*value);
7275968caeeSMarri Devender Rao                 }
7285968caeeSMarri Devender Rao             }
7295968caeeSMarri Devender Rao         }
7305968caeeSMarri Devender Rao         asyncResp->res.addHeader("Location", certURL);
7315968caeeSMarri Devender Rao         },
7325968caeeSMarri Devender Rao         service, objectPath, certs::dbusPropIntf, "GetAll",
7335968caeeSMarri Devender Rao         certs::certPropIntf);
7345968caeeSMarri Devender Rao }
7355968caeeSMarri Devender Rao 
7365968caeeSMarri Devender Rao /**
7375968caeeSMarri Devender Rao  * Action to replace an existing certificate
7385968caeeSMarri Devender Rao  */
7397e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionsReplaceCertificate(App& app)
7405968caeeSMarri Devender Rao {
7410fda0f12SGeorge Liu     BMCWEB_ROUTE(
7420fda0f12SGeorge Liu         app,
7430fda0f12SGeorge Liu         "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate/")
744ed398213SEd Tanous         .privileges(redfish::privileges::postCertificateService)
745002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
746002d39b4SEd Tanous             [&app](const crow::Request& req,
7477e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
7483ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
74945ca1b86SEd Tanous         {
75045ca1b86SEd Tanous             return;
75145ca1b86SEd Tanous         }
7525968caeeSMarri Devender Rao         std::string certificate;
7535968caeeSMarri Devender Rao         nlohmann::json certificateUri;
7545968caeeSMarri Devender Rao         std::optional<std::string> certificateType = "PEM";
7558d1b46d7Szhanghch05 
756002d39b4SEd Tanous         if (!json_util::readJsonAction(req, asyncResp->res, "CertificateString",
757002d39b4SEd Tanous                                        certificate, "CertificateUri",
758002d39b4SEd Tanous                                        certificateUri, "CertificateType",
759002d39b4SEd Tanous                                        certificateType))
7605968caeeSMarri Devender Rao         {
7615968caeeSMarri Devender Rao             BMCWEB_LOG_ERROR << "Required parameters are missing";
7625968caeeSMarri Devender Rao             messages::internalError(asyncResp->res);
7635968caeeSMarri Devender Rao             return;
7645968caeeSMarri Devender Rao         }
7655968caeeSMarri Devender Rao 
7665968caeeSMarri Devender Rao         if (!certificateType)
7675968caeeSMarri Devender Rao         {
7685968caeeSMarri Devender Rao             // should never happen, but it never hurts to be paranoid.
7695968caeeSMarri Devender Rao             return;
7705968caeeSMarri Devender Rao         }
7715968caeeSMarri Devender Rao         if (certificateType != "PEM")
7725968caeeSMarri Devender Rao         {
7735968caeeSMarri Devender Rao             messages::actionParameterNotSupported(
7745968caeeSMarri Devender Rao                 asyncResp->res, "CertificateType", "ReplaceCertificate");
7755968caeeSMarri Devender Rao             return;
7765968caeeSMarri Devender Rao         }
7775968caeeSMarri Devender Rao 
7785968caeeSMarri Devender Rao         std::string certURI;
7795968caeeSMarri Devender Rao         if (!redfish::json_util::readJson(certificateUri, asyncResp->res,
7805968caeeSMarri Devender Rao                                           "@odata.id", certURI))
7815968caeeSMarri Devender Rao         {
7825968caeeSMarri Devender Rao             messages::actionParameterMissing(
7835968caeeSMarri Devender Rao                 asyncResp->res, "ReplaceCertificate", "CertificateUri");
7845968caeeSMarri Devender Rao             return;
7855968caeeSMarri Devender Rao         }
7865968caeeSMarri Devender Rao 
7875968caeeSMarri Devender Rao         BMCWEB_LOG_INFO << "Certificate URI to replace" << certURI;
7885968caeeSMarri Devender Rao         long id = getIDFromURL(certURI);
7895968caeeSMarri Devender Rao         if (id < 0)
7905968caeeSMarri Devender Rao         {
791002d39b4SEd Tanous             messages::actionParameterValueFormatError(asyncResp->res, certURI,
792002d39b4SEd Tanous                                                       "CertificateUri",
7935968caeeSMarri Devender Rao                                                       "ReplaceCertificate");
7945968caeeSMarri Devender Rao             return;
7955968caeeSMarri Devender Rao         }
7965968caeeSMarri Devender Rao         std::string objectPath;
7975968caeeSMarri Devender Rao         std::string name;
79837cce918SMarri Devender Rao         std::string service;
79911ba3979SEd Tanous         if (certURI.starts_with(
8000fda0f12SGeorge Liu                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/"))
8015968caeeSMarri Devender Rao         {
802002d39b4SEd Tanous             objectPath =
803002d39b4SEd Tanous                 std::string(certs::httpsObjectPath) + "/" + std::to_string(id);
8045968caeeSMarri Devender Rao             name = "HTTPS certificate";
80537cce918SMarri Devender Rao             service = certs::httpsServiceName;
80637cce918SMarri Devender Rao         }
80711ba3979SEd Tanous         else if (certURI.starts_with(
80811ba3979SEd Tanous                      "/redfish/v1/AccountService/LDAP/Certificates/"))
80937cce918SMarri Devender Rao         {
810002d39b4SEd Tanous             objectPath =
811002d39b4SEd Tanous                 std::string(certs::ldapObjectPath) + "/" + std::to_string(id);
81237cce918SMarri Devender Rao             name = "LDAP certificate";
81337cce918SMarri Devender Rao             service = certs::ldapServiceName;
8145968caeeSMarri Devender Rao         }
81511ba3979SEd Tanous         else if (certURI.starts_with(
816cfcd5f6bSMarri Devender Rao                      "/redfish/v1/Managers/bmc/Truststore/Certificates/"))
817cfcd5f6bSMarri Devender Rao         {
818cfcd5f6bSMarri Devender Rao             objectPath = std::string(certs::authorityObjectPath) + "/" +
819cfcd5f6bSMarri Devender Rao                          std::to_string(id);
820cfcd5f6bSMarri Devender Rao             name = "TrustStore certificate";
821cfcd5f6bSMarri Devender Rao             service = certs::authorityServiceName;
822cfcd5f6bSMarri Devender Rao         }
8235968caeeSMarri Devender Rao         else
8245968caeeSMarri Devender Rao         {
8255968caeeSMarri Devender Rao             messages::actionParameterNotSupported(
8265968caeeSMarri Devender Rao                 asyncResp->res, "CertificateUri", "ReplaceCertificate");
8275968caeeSMarri Devender Rao             return;
8285968caeeSMarri Devender Rao         }
8295968caeeSMarri Devender Rao 
8305968caeeSMarri Devender Rao         std::shared_ptr<CertificateFile> certFile =
8315968caeeSMarri Devender Rao             std::make_shared<CertificateFile>(certificate);
8325968caeeSMarri Devender Rao         crow::connections::systemBus->async_method_call(
83337cce918SMarri Devender Rao             [asyncResp, certFile, objectPath, service, certURI, id,
8345968caeeSMarri Devender Rao              name](const boost::system::error_code ec) {
8355968caeeSMarri Devender Rao             if (ec)
8365968caeeSMarri Devender Rao             {
8375968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
83890d2d1e8SJiaqing Zhao                 if (ec.value() ==
83990d2d1e8SJiaqing Zhao                     boost::system::linux_error::bad_request_descriptor)
84090d2d1e8SJiaqing Zhao                 {
8418aae75adSMarri Devender Rao                     messages::resourceNotFound(asyncResp->res, name,
8428aae75adSMarri Devender Rao                                                std::to_string(id));
8435968caeeSMarri Devender Rao                     return;
8445968caeeSMarri Devender Rao                 }
84590d2d1e8SJiaqing Zhao                 messages::internalError(asyncResp->res);
84690d2d1e8SJiaqing Zhao                 return;
84790d2d1e8SJiaqing Zhao             }
848*e19e97e2SJiaqing Zhao             getCertificateProperties(asyncResp, objectPath, service,
849*e19e97e2SJiaqing Zhao                                      std::to_string(id), certURI, name);
8505968caeeSMarri Devender Rao             BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
8515968caeeSMarri Devender Rao                              << certFile->getCertFilePath();
8525968caeeSMarri Devender Rao             },
8535968caeeSMarri Devender Rao             service, objectPath, certs::certReplaceIntf, "Replace",
8545968caeeSMarri Devender Rao             certFile->getCertFilePath());
8557e860f15SJohn Edward Broadbent         });
8567e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionsReplaceCertificate
8575968caeeSMarri Devender Rao 
8585968caeeSMarri Devender Rao /**
8595968caeeSMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
8605968caeeSMarri Devender Rao  * of a component, account or service.
8615968caeeSMarri Devender Rao  */
8625968caeeSMarri Devender Rao 
8637e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificate(App& app)
8645968caeeSMarri Devender Rao {
8657e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(
8667e860f15SJohn Edward Broadbent         app,
8677e860f15SJohn Edward Broadbent         "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/<str>/")
868ed398213SEd Tanous         .privileges(redfish::privileges::getCertificate)
8697e860f15SJohn Edward Broadbent         .methods(
8707e860f15SJohn Edward Broadbent             boost::beast::http::verb::
87145ca1b86SEd Tanous                 get)([&app](const crow::Request& req,
8727e860f15SJohn Edward Broadbent                             const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
8737e860f15SJohn Edward Broadbent                             const std::string& param) -> void {
8743ba00073SCarson Labrado             if (!redfish::setUpRedfishRoute(app, req, asyncResp))
87545ca1b86SEd Tanous             {
87645ca1b86SEd Tanous                 return;
87745ca1b86SEd Tanous             }
8787e860f15SJohn Edward Broadbent             if (param.empty())
8795968caeeSMarri Devender Rao             {
8805968caeeSMarri Devender Rao                 messages::internalError(asyncResp->res);
8815968caeeSMarri Devender Rao                 return;
8825968caeeSMarri Devender Rao             }
8835968caeeSMarri Devender Rao             long id = getIDFromURL(req.url);
8845968caeeSMarri Devender Rao 
8857e860f15SJohn Edward Broadbent             BMCWEB_LOG_DEBUG << "HTTPSCertificate::doGet ID="
8867e860f15SJohn Edward Broadbent                              << std::to_string(id);
8875968caeeSMarri Devender Rao             std::string certURL =
8885968caeeSMarri Devender Rao                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" +
8895968caeeSMarri Devender Rao                 std::to_string(id);
8905968caeeSMarri Devender Rao             std::string objectPath = certs::httpsObjectPath;
8915968caeeSMarri Devender Rao             objectPath += "/";
8925968caeeSMarri Devender Rao             objectPath += std::to_string(id);
893*e19e97e2SJiaqing Zhao             getCertificateProperties(
894*e19e97e2SJiaqing Zhao                 asyncResp, objectPath, certs::httpsServiceName,
895*e19e97e2SJiaqing Zhao                 std::to_string(id), certURL, "HTTPS Certificate");
8967e860f15SJohn Edward Broadbent         });
8975968caeeSMarri Devender Rao }
8985968caeeSMarri Devender Rao 
8995968caeeSMarri Devender Rao /**
9005968caeeSMarri Devender Rao  * Collection of HTTPS certificates
9015968caeeSMarri Devender Rao  */
9027e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificateCollection(App& app)
9035968caeeSMarri Devender Rao {
9047e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
9055968caeeSMarri Devender Rao                  "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
906ed398213SEd Tanous         .privileges(redfish::privileges::getCertificateCollection)
907002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
908002d39b4SEd Tanous             [&app](const crow::Request& req,
909002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
9103ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
91145ca1b86SEd Tanous         {
91245ca1b86SEd Tanous             return;
91345ca1b86SEd Tanous         }
9141476687dSEd Tanous 
9151476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
9161476687dSEd Tanous             "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates";
9171476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
9181476687dSEd Tanous             "#CertificateCollection.CertificateCollection";
9191476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = "HTTPS Certificates Collection";
9201476687dSEd Tanous         asyncResp->res.jsonValue["Description"] =
9211476687dSEd Tanous             "A Collection of HTTPS certificate instances";
9228d1b46d7Szhanghch05 
923d3f92ce7SJiaqing Zhao         getCertificateList(asyncResp, certs::httpsObjectPath,
924d3f92ce7SJiaqing Zhao                            "/Members"_json_pointer,
925d3f92ce7SJiaqing Zhao                            "/Members@odata.count"_json_pointer);
9267e860f15SJohn Edward Broadbent         });
9275968caeeSMarri Devender Rao 
9287e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app,
9297e860f15SJohn Edward Broadbent                  "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")
930ed398213SEd Tanous         .privileges(redfish::privileges::postCertificateCollection)
931002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
932002d39b4SEd Tanous             [&app](const crow::Request& req,
9337e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
9343ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
93545ca1b86SEd Tanous         {
93645ca1b86SEd Tanous             return;
93745ca1b86SEd Tanous         }
9385968caeeSMarri Devender Rao         BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost";
9398d1b46d7Szhanghch05 
9401476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = "HTTPS Certificate";
9411476687dSEd Tanous         asyncResp->res.jsonValue["Description"] = "HTTPS Certificate";
9425968caeeSMarri Devender Rao 
943002d39b4SEd Tanous         std::string certFileBody = getCertificateFromReqBody(asyncResp, req);
94458eb238fSKowalski, Kamil 
94558eb238fSKowalski, Kamil         if (certFileBody.empty())
94658eb238fSKowalski, Kamil         {
9470fda0f12SGeorge Liu             BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
948a08752f5SZbigniew Kurzynski             messages::unrecognizedRequestBody(asyncResp->res);
94958eb238fSKowalski, Kamil             return;
95058eb238fSKowalski, Kamil         }
95158eb238fSKowalski, Kamil 
9525968caeeSMarri Devender Rao         std::shared_ptr<CertificateFile> certFile =
95358eb238fSKowalski, Kamil             std::make_shared<CertificateFile>(certFileBody);
9545968caeeSMarri Devender Rao 
9555968caeeSMarri Devender Rao         crow::connections::systemBus->async_method_call(
956656ec7e3SZbigniew Kurzynski             [asyncResp, certFile](const boost::system::error_code ec,
957656ec7e3SZbigniew Kurzynski                                   const std::string& objectPath) {
9585968caeeSMarri Devender Rao             if (ec)
9595968caeeSMarri Devender Rao             {
9605968caeeSMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
9615968caeeSMarri Devender Rao                 messages::internalError(asyncResp->res);
9625968caeeSMarri Devender Rao                 return;
9635968caeeSMarri Devender Rao             }
964656ec7e3SZbigniew Kurzynski             long certId = getIDFromURL(objectPath);
965656ec7e3SZbigniew Kurzynski             if (certId < 0)
966656ec7e3SZbigniew Kurzynski             {
967002d39b4SEd Tanous                 BMCWEB_LOG_ERROR << "Invalid objectPath value" << objectPath;
968656ec7e3SZbigniew Kurzynski                 messages::internalError(asyncResp->res);
969656ec7e3SZbigniew Kurzynski                 return;
970656ec7e3SZbigniew Kurzynski             }
9715968caeeSMarri Devender Rao             std::string certURL =
9720fda0f12SGeorge Liu                 "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" +
9735968caeeSMarri Devender Rao                 std::to_string(certId);
974*e19e97e2SJiaqing Zhao             getCertificateProperties(
975*e19e97e2SJiaqing Zhao                 asyncResp, objectPath, certs::httpsServiceName,
976*e19e97e2SJiaqing Zhao                 std::to_string(certId), certURL, "HTTPS Certificate");
9775968caeeSMarri Devender Rao             BMCWEB_LOG_DEBUG << "HTTPS certificate install file="
9785968caeeSMarri Devender Rao                              << certFile->getCertFilePath();
9795968caeeSMarri Devender Rao             },
98037cce918SMarri Devender Rao             certs::httpsServiceName, certs::httpsObjectPath,
9810fda0f12SGeorge Liu             certs::certInstallIntf, "Install", certFile->getCertFilePath());
9827e860f15SJohn Edward Broadbent         });
9837e860f15SJohn Edward Broadbent } // requestRoutesHTTPSCertificateCollection
9845968caeeSMarri Devender Rao 
9855968caeeSMarri Devender Rao /**
9867e860f15SJohn Edward Broadbent  * The certificate location schema defines a resource that an administrator
9877e860f15SJohn Edward Broadbent  * can use in order to locate all certificates installed on a given service.
9887e860f15SJohn Edward Broadbent  */
9897e860f15SJohn Edward Broadbent inline void requestRoutesCertificateLocations(App& app)
9907e860f15SJohn Edward Broadbent {
9917e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/")
992ed398213SEd Tanous         .privileges(redfish::privileges::getCertificateLocations)
993002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
994002d39b4SEd Tanous             [&app](const crow::Request& req,
995002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
9963ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
99745ca1b86SEd Tanous         {
99845ca1b86SEd Tanous             return;
99945ca1b86SEd Tanous         }
10001476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
10011476687dSEd Tanous             "/redfish/v1/CertificateService/CertificateLocations";
10021476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
10031476687dSEd Tanous             "#CertificateLocations.v1_0_0.CertificateLocations";
10041476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = "Certificate Locations";
10051476687dSEd Tanous         asyncResp->res.jsonValue["Id"] = "CertificateLocations";
10061476687dSEd Tanous         asyncResp->res.jsonValue["Description"] =
10077e860f15SJohn Edward Broadbent             "Defines a resource that an administrator can use in order to "
10081476687dSEd Tanous             "locate all certificates installed on a given service";
10097e860f15SJohn Edward Broadbent 
1010d3f92ce7SJiaqing Zhao         getCertificateList(asyncResp, certs::baseObjectPath,
1011d3f92ce7SJiaqing Zhao                            "/Links/Certificates"_json_pointer,
1012d3f92ce7SJiaqing Zhao                            "/Links/Certificates@odata.count"_json_pointer);
10137e860f15SJohn Edward Broadbent         });
10147e860f15SJohn Edward Broadbent }
10157e860f15SJohn Edward Broadbent // requestRoutesCertificateLocations
101637cce918SMarri Devender Rao 
101737cce918SMarri Devender Rao /**
101837cce918SMarri Devender Rao  * Collection of LDAP certificates
101937cce918SMarri Devender Rao  */
10207e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificateCollection(App& app)
102137cce918SMarri Devender Rao {
10227e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
1023ed398213SEd Tanous         .privileges(redfish::privileges::getCertificateCollection)
1024002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
1025002d39b4SEd Tanous             [&app](const crow::Request& req,
1026002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
10273ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
102845ca1b86SEd Tanous         {
102945ca1b86SEd Tanous             return;
103045ca1b86SEd Tanous         }
10311476687dSEd Tanous 
10321476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
10331476687dSEd Tanous             "/redfish/v1/AccountService/LDAP/Certificates";
10341476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
10351476687dSEd Tanous             "#CertificateCollection.CertificateCollection";
10361476687dSEd Tanous         asyncResp->res.jsonValue["Name"] = "LDAP Certificates Collection";
10371476687dSEd Tanous         asyncResp->res.jsonValue["Description"] =
10381476687dSEd Tanous             "A Collection of LDAP certificate instances";
10398d1b46d7Szhanghch05 
1040d3f92ce7SJiaqing Zhao         getCertificateList(asyncResp, certs::ldapObjectPath,
1041d3f92ce7SJiaqing Zhao                            "/Members"_json_pointer,
1042d3f92ce7SJiaqing Zhao                            "/Members@odata.count"_json_pointer);
10437e860f15SJohn Edward Broadbent         });
104437cce918SMarri Devender Rao 
10457e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/")
1046ed398213SEd Tanous         .privileges(redfish::privileges::postCertificateCollection)
10477e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::post)(
104845ca1b86SEd Tanous             [&app](const crow::Request& req,
10497e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
10503ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
105145ca1b86SEd Tanous         {
105245ca1b86SEd Tanous             return;
105345ca1b86SEd Tanous         }
1054002d39b4SEd Tanous         std::string certFileBody = getCertificateFromReqBody(asyncResp, req);
105558eb238fSKowalski, Kamil 
105658eb238fSKowalski, Kamil         if (certFileBody.empty())
105758eb238fSKowalski, Kamil         {
1058002d39b4SEd Tanous             BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
1059a08752f5SZbigniew Kurzynski             messages::unrecognizedRequestBody(asyncResp->res);
106058eb238fSKowalski, Kamil             return;
106158eb238fSKowalski, Kamil         }
106258eb238fSKowalski, Kamil 
106358eb238fSKowalski, Kamil         std::shared_ptr<CertificateFile> certFile =
106458eb238fSKowalski, Kamil             std::make_shared<CertificateFile>(certFileBody);
106558eb238fSKowalski, Kamil 
106637cce918SMarri Devender Rao         crow::connections::systemBus->async_method_call(
1067656ec7e3SZbigniew Kurzynski             [asyncResp, certFile](const boost::system::error_code ec,
1068656ec7e3SZbigniew Kurzynski                                   const std::string& objectPath) {
106937cce918SMarri Devender Rao             if (ec)
107037cce918SMarri Devender Rao             {
107137cce918SMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
107237cce918SMarri Devender Rao                 messages::internalError(asyncResp->res);
107337cce918SMarri Devender Rao                 return;
107437cce918SMarri Devender Rao             }
1075656ec7e3SZbigniew Kurzynski             long certId = getIDFromURL(objectPath);
1076656ec7e3SZbigniew Kurzynski             if (certId < 0)
1077656ec7e3SZbigniew Kurzynski             {
1078002d39b4SEd Tanous                 BMCWEB_LOG_ERROR << "Invalid objectPath value" << objectPath;
1079656ec7e3SZbigniew Kurzynski                 messages::internalError(asyncResp->res);
1080656ec7e3SZbigniew Kurzynski                 return;
1081656ec7e3SZbigniew Kurzynski             }
108237cce918SMarri Devender Rao             std::string certURL =
108337cce918SMarri Devender Rao                 "/redfish/v1/AccountService/LDAP/Certificates/" +
108437cce918SMarri Devender Rao                 std::to_string(certId);
1085*e19e97e2SJiaqing Zhao             getCertificateProperties(
1086*e19e97e2SJiaqing Zhao                 asyncResp, objectPath, certs::ldapServiceName,
1087*e19e97e2SJiaqing Zhao                 std::to_string(certId), certURL, "LDAP Certificate");
108837cce918SMarri Devender Rao             BMCWEB_LOG_DEBUG << "LDAP certificate install file="
108937cce918SMarri Devender Rao                              << certFile->getCertFilePath();
109037cce918SMarri Devender Rao             },
109137cce918SMarri Devender Rao             certs::ldapServiceName, certs::ldapObjectPath,
1092002d39b4SEd Tanous             certs::certInstallIntf, "Install", certFile->getCertFilePath());
10937e860f15SJohn Edward Broadbent         });
10947e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificateCollection
109537cce918SMarri Devender Rao 
109637cce918SMarri Devender Rao /**
109737cce918SMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
109837cce918SMarri Devender Rao  * of a component, account or service.
109937cce918SMarri Devender Rao  */
11007e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificate(App& app)
110137cce918SMarri Devender Rao {
11027e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/")
1103ed398213SEd Tanous         .privileges(redfish::privileges::getCertificate)
11047e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
110545ca1b86SEd Tanous             [&app](const crow::Request& req,
11067e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
11077e860f15SJohn Edward Broadbent                    const std::string&) {
11083ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
110945ca1b86SEd Tanous         {
111045ca1b86SEd Tanous             return;
111145ca1b86SEd Tanous         }
111237cce918SMarri Devender Rao         long id = getIDFromURL(req.url);
111337cce918SMarri Devender Rao         if (id < 0)
111437cce918SMarri Devender Rao         {
111537cce918SMarri Devender Rao             BMCWEB_LOG_ERROR << "Invalid url value" << req.url;
111637cce918SMarri Devender Rao             messages::internalError(asyncResp->res);
111737cce918SMarri Devender Rao             return;
111837cce918SMarri Devender Rao         }
1119002d39b4SEd Tanous         BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" << std::to_string(id);
1120002d39b4SEd Tanous         std::string certURL = "/redfish/v1/AccountService/LDAP/Certificates/" +
112137cce918SMarri Devender Rao                               std::to_string(id);
112237cce918SMarri Devender Rao         std::string objectPath = certs::ldapObjectPath;
112337cce918SMarri Devender Rao         objectPath += "/";
112437cce918SMarri Devender Rao         objectPath += std::to_string(id);
1125002d39b4SEd Tanous         getCertificateProperties(asyncResp, objectPath, certs::ldapServiceName,
1126*e19e97e2SJiaqing Zhao                                  std::to_string(id), certURL,
1127*e19e97e2SJiaqing Zhao                                  "LDAP Certificate");
11287e860f15SJohn Edward Broadbent         });
11297e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificate
1130cfcd5f6bSMarri Devender Rao /**
1131cfcd5f6bSMarri Devender Rao  * Collection of TrustStoreCertificate certificates
1132cfcd5f6bSMarri Devender Rao  */
11337e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificateCollection(App& app)
1134cfcd5f6bSMarri Devender Rao {
11357e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
1136ed398213SEd Tanous         .privileges(redfish::privileges::getCertificate)
1137002d39b4SEd Tanous         .methods(boost::beast::http::verb::get)(
1138002d39b4SEd Tanous             [&app](const crow::Request& req,
1139002d39b4SEd Tanous                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
11403ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
114145ca1b86SEd Tanous         {
114245ca1b86SEd Tanous             return;
114345ca1b86SEd Tanous         }
11441476687dSEd Tanous 
11451476687dSEd Tanous         asyncResp->res.jsonValue["@odata.id"] =
11461476687dSEd Tanous             "/redfish/v1/Managers/bmc/Truststore/Certificates/";
11471476687dSEd Tanous         asyncResp->res.jsonValue["@odata.type"] =
11481476687dSEd Tanous             "#CertificateCollection.CertificateCollection";
1149002d39b4SEd Tanous         asyncResp->res.jsonValue["Name"] = "TrustStore Certificates Collection";
11501476687dSEd Tanous         asyncResp->res.jsonValue["Description"] =
11511476687dSEd Tanous             "A Collection of TrustStore certificate instances";
11528d1b46d7Szhanghch05 
1153d3f92ce7SJiaqing Zhao         getCertificateList(asyncResp, certs::authorityObjectPath,
1154d3f92ce7SJiaqing Zhao                            "/Members"_json_pointer,
1155d3f92ce7SJiaqing Zhao                            "/Members@odata.count"_json_pointer);
11567e860f15SJohn Edward Broadbent         });
1157cfcd5f6bSMarri Devender Rao 
11587e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/")
1159ed398213SEd Tanous         .privileges(redfish::privileges::postCertificateCollection)
1160002d39b4SEd Tanous         .methods(boost::beast::http::verb::post)(
1161002d39b4SEd Tanous             [&app](const crow::Request& req,
11627e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
11633ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
116445ca1b86SEd Tanous         {
116545ca1b86SEd Tanous             return;
116645ca1b86SEd Tanous         }
1167002d39b4SEd Tanous         std::string certFileBody = getCertificateFromReqBody(asyncResp, req);
1168a08752f5SZbigniew Kurzynski 
1169a08752f5SZbigniew Kurzynski         if (certFileBody.empty())
1170a08752f5SZbigniew Kurzynski         {
11710fda0f12SGeorge Liu             BMCWEB_LOG_ERROR << "Cannot get certificate from request body.";
1172a08752f5SZbigniew Kurzynski             messages::unrecognizedRequestBody(asyncResp->res);
1173a08752f5SZbigniew Kurzynski             return;
1174a08752f5SZbigniew Kurzynski         }
1175a08752f5SZbigniew Kurzynski 
1176a08752f5SZbigniew Kurzynski         std::shared_ptr<CertificateFile> certFile =
1177a08752f5SZbigniew Kurzynski             std::make_shared<CertificateFile>(certFileBody);
1178cfcd5f6bSMarri Devender Rao         crow::connections::systemBus->async_method_call(
1179656ec7e3SZbigniew Kurzynski             [asyncResp, certFile](const boost::system::error_code ec,
1180656ec7e3SZbigniew Kurzynski                                   const std::string& objectPath) {
1181cfcd5f6bSMarri Devender Rao             if (ec)
1182cfcd5f6bSMarri Devender Rao             {
1183cfcd5f6bSMarri Devender Rao                 BMCWEB_LOG_ERROR << "DBUS response error: " << ec;
1184cfcd5f6bSMarri Devender Rao                 messages::internalError(asyncResp->res);
1185cfcd5f6bSMarri Devender Rao                 return;
1186cfcd5f6bSMarri Devender Rao             }
1187656ec7e3SZbigniew Kurzynski             long certId = getIDFromURL(objectPath);
1188656ec7e3SZbigniew Kurzynski             if (certId < 0)
1189656ec7e3SZbigniew Kurzynski             {
1190002d39b4SEd Tanous                 BMCWEB_LOG_ERROR << "Invalid objectPath value" << objectPath;
1191656ec7e3SZbigniew Kurzynski                 messages::internalError(asyncResp->res);
1192656ec7e3SZbigniew Kurzynski                 return;
1193656ec7e3SZbigniew Kurzynski             }
11940fda0f12SGeorge Liu             std::string certURL =
11950fda0f12SGeorge Liu                 "/redfish/v1/Managers/bmc/Truststore/Certificates/" +
1196cfcd5f6bSMarri Devender Rao                 std::to_string(certId);
1197656ec7e3SZbigniew Kurzynski 
1198*e19e97e2SJiaqing Zhao             getCertificateProperties(
1199*e19e97e2SJiaqing Zhao                 asyncResp, objectPath, certs::authorityServiceName,
1200*e19e97e2SJiaqing Zhao                 std::to_string(certId), certURL, "TrustStore Certificate");
12010fda0f12SGeorge Liu             BMCWEB_LOG_DEBUG << "TrustStore certificate install file="
1202cfcd5f6bSMarri Devender Rao                              << certFile->getCertFilePath();
1203cfcd5f6bSMarri Devender Rao             },
1204cfcd5f6bSMarri Devender Rao             certs::authorityServiceName, certs::authorityObjectPath,
12050fda0f12SGeorge Liu             certs::certInstallIntf, "Install", certFile->getCertFilePath());
12067e860f15SJohn Edward Broadbent         });
12077e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificateCollection
1208cfcd5f6bSMarri Devender Rao 
1209cfcd5f6bSMarri Devender Rao /**
1210cfcd5f6bSMarri Devender Rao  * Certificate resource describes a certificate used to prove the identity
1211cfcd5f6bSMarri Devender Rao  * of a component, account or service.
1212cfcd5f6bSMarri Devender Rao  */
12137e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificate(App& app)
1214cfcd5f6bSMarri Devender Rao {
12157e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
1216ed398213SEd Tanous         .privileges(redfish::privileges::getCertificate)
12177e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::get)(
121845ca1b86SEd Tanous             [&app](const crow::Request& req,
12197e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
12207e860f15SJohn Edward Broadbent                    const std::string&) {
12213ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
122245ca1b86SEd Tanous         {
122345ca1b86SEd Tanous             return;
122445ca1b86SEd Tanous         }
1225cfcd5f6bSMarri Devender Rao         long id = getIDFromURL(req.url);
1226cfcd5f6bSMarri Devender Rao         if (id < 0)
1227cfcd5f6bSMarri Devender Rao         {
1228cfcd5f6bSMarri Devender Rao             BMCWEB_LOG_ERROR << "Invalid url value" << req.url;
1229cfcd5f6bSMarri Devender Rao             messages::internalError(asyncResp->res);
1230cfcd5f6bSMarri Devender Rao             return;
1231cfcd5f6bSMarri Devender Rao         }
1232cfcd5f6bSMarri Devender Rao         BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doGet ID="
1233cfcd5f6bSMarri Devender Rao                          << std::to_string(id);
1234cfcd5f6bSMarri Devender Rao         std::string certURL =
1235cfcd5f6bSMarri Devender Rao             "/redfish/v1/Managers/bmc/Truststore/Certificates/" +
1236cfcd5f6bSMarri Devender Rao             std::to_string(id);
1237cfcd5f6bSMarri Devender Rao         std::string objectPath = certs::authorityObjectPath;
1238cfcd5f6bSMarri Devender Rao         objectPath += "/";
1239cfcd5f6bSMarri Devender Rao         objectPath += std::to_string(id);
1240*e19e97e2SJiaqing Zhao         getCertificateProperties(
1241*e19e97e2SJiaqing Zhao             asyncResp, objectPath, certs::authorityServiceName,
1242*e19e97e2SJiaqing Zhao             std::to_string(id), certURL, "TrustStore Certificate");
12437e860f15SJohn Edward Broadbent         });
124407a60299SZbigniew Kurzynski 
12457e860f15SJohn Edward Broadbent     BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/")
1246ed398213SEd Tanous         .privileges(redfish::privileges::deleteCertificate)
12477e860f15SJohn Edward Broadbent         .methods(boost::beast::http::verb::delete_)(
124845ca1b86SEd Tanous             [&app](const crow::Request& req,
12497e860f15SJohn Edward Broadbent                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
12507e860f15SJohn Edward Broadbent                    const std::string& param) {
12513ba00073SCarson Labrado         if (!redfish::setUpRedfishRoute(app, req, asyncResp))
125245ca1b86SEd Tanous         {
125345ca1b86SEd Tanous             return;
125445ca1b86SEd Tanous         }
12557e860f15SJohn Edward Broadbent         if (param.empty())
125607a60299SZbigniew Kurzynski         {
125707a60299SZbigniew Kurzynski             messages::internalError(asyncResp->res);
125807a60299SZbigniew Kurzynski             return;
125907a60299SZbigniew Kurzynski         }
126007a60299SZbigniew Kurzynski 
126107a60299SZbigniew Kurzynski         long id = getIDFromURL(req.url);
126207a60299SZbigniew Kurzynski         if (id < 0)
126307a60299SZbigniew Kurzynski         {
126407a60299SZbigniew Kurzynski             BMCWEB_LOG_ERROR << "Invalid url value: " << req.url;
1265002d39b4SEd Tanous             messages::resourceNotFound(asyncResp->res, "TrustStore Certificate",
126607a60299SZbigniew Kurzynski                                        std::string(req.url));
126707a60299SZbigniew Kurzynski             return;
126807a60299SZbigniew Kurzynski         }
126907a60299SZbigniew Kurzynski         BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doDelete ID="
127007a60299SZbigniew Kurzynski                          << std::to_string(id);
127107a60299SZbigniew Kurzynski         std::string certPath = certs::authorityObjectPath;
127207a60299SZbigniew Kurzynski         certPath += "/";
127307a60299SZbigniew Kurzynski         certPath += std::to_string(id);
127407a60299SZbigniew Kurzynski 
127507a60299SZbigniew Kurzynski         crow::connections::systemBus->async_method_call(
127607a60299SZbigniew Kurzynski             [asyncResp, id](const boost::system::error_code ec) {
127707a60299SZbigniew Kurzynski             if (ec)
127807a60299SZbigniew Kurzynski             {
127907a60299SZbigniew Kurzynski                 messages::resourceNotFound(asyncResp->res,
128007a60299SZbigniew Kurzynski                                            "TrustStore Certificate",
128107a60299SZbigniew Kurzynski                                            std::to_string(id));
128207a60299SZbigniew Kurzynski                 return;
128307a60299SZbigniew Kurzynski             }
128407a60299SZbigniew Kurzynski             BMCWEB_LOG_INFO << "Certificate deleted";
1285002d39b4SEd Tanous             asyncResp->res.result(boost::beast::http::status::no_content);
128607a60299SZbigniew Kurzynski             },
128707a60299SZbigniew Kurzynski             certs::authorityServiceName, certPath, certs::objDeleteIntf,
128807a60299SZbigniew Kurzynski             "Delete");
12897e860f15SJohn Edward Broadbent         });
12907e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificate
12915968caeeSMarri Devender Rao } // namespace redfish
1292