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