15968caeeSMarri Devender Rao #pragma once 25968caeeSMarri Devender Rao 37e860f15SJohn Edward Broadbent #include <app.hpp> 490d2d1e8SJiaqing Zhao #include <boost/system/linux_error.hpp> 5168e20c1SEd Tanous #include <dbus_utility.hpp> 645ca1b86SEd Tanous #include <query.hpp> 7ed398213SEd Tanous #include <registries/privilege_registry.hpp> 81214b7e7SGunnar Mills 95968caeeSMarri Devender Rao namespace redfish 105968caeeSMarri Devender Rao { 115968caeeSMarri Devender Rao namespace certs 125968caeeSMarri Devender Rao { 135968caeeSMarri Devender Rao constexpr char const* certInstallIntf = "xyz.openbmc_project.Certs.Install"; 145968caeeSMarri Devender Rao constexpr char const* certReplaceIntf = "xyz.openbmc_project.Certs.Replace"; 1507a60299SZbigniew Kurzynski constexpr char const* objDeleteIntf = "xyz.openbmc_project.Object.Delete"; 165968caeeSMarri Devender Rao constexpr char const* certPropIntf = "xyz.openbmc_project.Certs.Certificate"; 175968caeeSMarri Devender Rao constexpr char const* dbusPropIntf = "org.freedesktop.DBus.Properties"; 185968caeeSMarri Devender Rao constexpr char const* dbusObjManagerIntf = "org.freedesktop.DBus.ObjectManager"; 1937cce918SMarri Devender Rao constexpr char const* httpsServiceName = 2037cce918SMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Server.Https"; 2137cce918SMarri Devender Rao constexpr char const* ldapServiceName = 2237cce918SMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Client.Ldap"; 23cfcd5f6bSMarri Devender Rao constexpr char const* authorityServiceName = 24cfcd5f6bSMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Authority.Ldap"; 25c6a8dfb1SJiaqing Zhao constexpr char const* baseObjectPath = "/xyz/openbmc_project/certs"; 26c6a8dfb1SJiaqing Zhao constexpr char const* httpsObjectPath = 27c6a8dfb1SJiaqing Zhao "/xyz/openbmc_project/certs/server/https"; 28c6a8dfb1SJiaqing Zhao constexpr char const* ldapObjectPath = "/xyz/openbmc_project/certs/client/ldap"; 29cfcd5f6bSMarri Devender Rao constexpr char const* authorityObjectPath = 30cfcd5f6bSMarri Devender Rao "/xyz/openbmc_project/certs/authority/ldap"; 315968caeeSMarri Devender Rao } // namespace certs 325968caeeSMarri Devender Rao 335968caeeSMarri Devender Rao /** 345968caeeSMarri Devender Rao * The Certificate schema defines a Certificate Service which represents the 355968caeeSMarri Devender Rao * actions available to manage certificates and links to where certificates 365968caeeSMarri Devender Rao * are installed. 375968caeeSMarri Devender Rao */ 387e860f15SJohn Edward Broadbent 395968caeeSMarri Devender Rao // TODO: Issue#61 No entries are available for Certificate 404e0453b1SGunnar Mills // service at https://www.dmtf.org/standards/redfish 415968caeeSMarri Devender Rao // "redfish standard registries". Need to modify after DMTF 425968caeeSMarri Devender Rao // publish Privilege details for certificate service 435968caeeSMarri Devender Rao 447e860f15SJohn Edward Broadbent inline void requestRoutesCertificateService(App& app) 455968caeeSMarri Devender Rao { 467e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/") 47ed398213SEd Tanous .privileges(redfish::privileges::getCertificateService) 48002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 49002d39b4SEd Tanous [&app](const crow::Request& req, 50002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 513ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 5245ca1b86SEd Tanous { 5345ca1b86SEd Tanous return; 5445ca1b86SEd Tanous } 551476687dSEd Tanous 561476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 571476687dSEd Tanous "#CertificateService.v1_0_0.CertificateService"; 581476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 591476687dSEd Tanous "/redfish/v1/CertificateService"; 601476687dSEd Tanous asyncResp->res.jsonValue["Id"] = "CertificateService"; 611476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "Certificate Service"; 621476687dSEd Tanous asyncResp->res.jsonValue["Description"] = 631476687dSEd Tanous "Actions available to manage certificates"; 6472048780SAbhishek Patel // /redfish/v1/CertificateService/CertificateLocations is something 6572048780SAbhishek Patel // only ConfigureManager can access then only display when the user 6672048780SAbhishek Patel // has permissions ConfigureManager 6772048780SAbhishek Patel Privileges effectiveUserPrivileges = 6872048780SAbhishek Patel redfish::getUserPrivileges(req.userRole); 6972048780SAbhishek Patel if (isOperationAllowedWithPrivileges({{"ConfigureManager"}}, 7072048780SAbhishek Patel effectiveUserPrivileges)) 7172048780SAbhishek Patel { 721476687dSEd Tanous asyncResp->res.jsonValue["CertificateLocations"]["@odata.id"] = 731476687dSEd Tanous "/redfish/v1/CertificateService/CertificateLocations"; 7472048780SAbhishek Patel } 750fda0f12SGeorge Liu asyncResp->res 76002d39b4SEd Tanous .jsonValue["Actions"]["#CertificateService.ReplaceCertificate"] = { 770fda0f12SGeorge Liu {"target", 780fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate"}, 795968caeeSMarri Devender Rao {"CertificateType@Redfish.AllowableValues", {"PEM"}}}; 807e860f15SJohn Edward Broadbent asyncResp->res 817e860f15SJohn Edward Broadbent .jsonValue["Actions"]["#CertificateService.GenerateCSR"] = { 820fda0f12SGeorge Liu {"target", 830fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR"}}; 847e860f15SJohn Edward Broadbent }); 857e860f15SJohn Edward Broadbent } // requestRoutesCertificateService 8637cce918SMarri Devender Rao 878d1b46d7Szhanghch05 inline std::string getCertificateFromReqBody( 888d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 8958eb238fSKowalski, Kamil const crow::Request& req) 9058eb238fSKowalski, Kamil { 9158eb238fSKowalski, Kamil nlohmann::json reqJson = nlohmann::json::parse(req.body, nullptr, false); 9258eb238fSKowalski, Kamil 9358eb238fSKowalski, Kamil if (reqJson.is_discarded()) 9458eb238fSKowalski, Kamil { 9558eb238fSKowalski, Kamil // We did not receive JSON request, proceed as it is RAW data 9658eb238fSKowalski, Kamil return req.body; 9758eb238fSKowalski, Kamil } 9858eb238fSKowalski, Kamil 9958eb238fSKowalski, Kamil std::string certificate; 10058eb238fSKowalski, Kamil std::optional<std::string> certificateType = "PEM"; 10158eb238fSKowalski, Kamil 10215ed6780SWilly Tu if (!json_util::readJsonPatch(req, asyncResp->res, "CertificateString", 10315ed6780SWilly Tu certificate, "CertificateType", 10415ed6780SWilly Tu certificateType)) 10558eb238fSKowalski, Kamil { 10658eb238fSKowalski, Kamil BMCWEB_LOG_ERROR << "Required parameters are missing"; 10758eb238fSKowalski, Kamil messages::internalError(asyncResp->res); 108abb93cddSEd Tanous return {}; 10958eb238fSKowalski, Kamil } 11058eb238fSKowalski, Kamil 11158eb238fSKowalski, Kamil if (*certificateType != "PEM") 11258eb238fSKowalski, Kamil { 11358eb238fSKowalski, Kamil messages::propertyValueNotInList(asyncResp->res, *certificateType, 11458eb238fSKowalski, Kamil "CertificateType"); 115abb93cddSEd Tanous return {}; 11658eb238fSKowalski, Kamil } 11758eb238fSKowalski, Kamil 11858eb238fSKowalski, Kamil return certificate; 11958eb238fSKowalski, Kamil } 12058eb238fSKowalski, Kamil 1215968caeeSMarri Devender Rao /** 1225968caeeSMarri Devender Rao * Class to create a temporary certificate file for uploading to system 1235968caeeSMarri Devender Rao */ 1245968caeeSMarri Devender Rao class CertificateFile 1255968caeeSMarri Devender Rao { 1265968caeeSMarri Devender Rao public: 1275968caeeSMarri Devender Rao CertificateFile() = delete; 1285968caeeSMarri Devender Rao CertificateFile(const CertificateFile&) = delete; 1295968caeeSMarri Devender Rao CertificateFile& operator=(const CertificateFile&) = delete; 1305968caeeSMarri Devender Rao CertificateFile(CertificateFile&&) = delete; 1315968caeeSMarri Devender Rao CertificateFile& operator=(CertificateFile&&) = delete; 1324e23a444SEd Tanous explicit CertificateFile(const std::string& certString) 1335968caeeSMarri Devender Rao { 13472d52d25SEd Tanous std::array<char, 18> dirTemplate = {'/', 't', 'm', 'p', '/', 'C', 1355207438cSEd Tanous 'e', 'r', 't', 's', '.', 'X', 1365207438cSEd Tanous 'X', 'X', 'X', 'X', 'X', '\0'}; 1375207438cSEd Tanous char* tempDirectory = mkdtemp(dirTemplate.data()); 138e662eae8SEd Tanous if (tempDirectory != nullptr) 1395968caeeSMarri Devender Rao { 1405968caeeSMarri Devender Rao certDirectory = tempDirectory; 1415968caeeSMarri Devender Rao certificateFile = certDirectory / "cert.pem"; 1425968caeeSMarri Devender Rao std::ofstream out(certificateFile, std::ofstream::out | 1435968caeeSMarri Devender Rao std::ofstream::binary | 1445968caeeSMarri Devender Rao std::ofstream::trunc); 1455968caeeSMarri Devender Rao out << certString; 1465968caeeSMarri Devender Rao out.close(); 1478cc8edecSEd Tanous BMCWEB_LOG_DEBUG << "Creating certificate file" 1488cc8edecSEd Tanous << certificateFile.string(); 1495968caeeSMarri Devender Rao } 1505968caeeSMarri Devender Rao } 1515968caeeSMarri Devender Rao ~CertificateFile() 1525968caeeSMarri Devender Rao { 1535968caeeSMarri Devender Rao if (std::filesystem::exists(certDirectory)) 1545968caeeSMarri Devender Rao { 1558cc8edecSEd Tanous BMCWEB_LOG_DEBUG << "Removing certificate file" 1568cc8edecSEd Tanous << certificateFile.string(); 15723a21a1cSEd Tanous std::error_code ec; 15823a21a1cSEd Tanous std::filesystem::remove_all(certDirectory, ec); 15923a21a1cSEd Tanous if (ec) 1605968caeeSMarri Devender Rao { 1615968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Failed to remove temp directory" 1628cc8edecSEd Tanous << certDirectory.string(); 1635968caeeSMarri Devender Rao } 1645968caeeSMarri Devender Rao } 1655968caeeSMarri Devender Rao } 1665968caeeSMarri Devender Rao std::string getCertFilePath() 1675968caeeSMarri Devender Rao { 1685968caeeSMarri Devender Rao return certificateFile; 1695968caeeSMarri Devender Rao } 1705968caeeSMarri Devender Rao 1715968caeeSMarri Devender Rao private: 1725968caeeSMarri Devender Rao std::filesystem::path certificateFile; 1735968caeeSMarri Devender Rao std::filesystem::path certDirectory; 1745968caeeSMarri Devender Rao }; 1755968caeeSMarri Devender Rao 17659d494eeSPatrick Williams static std::unique_ptr<sdbusplus::bus::match_t> csrMatcher; 17730215816SMarri Devender Rao /** 17830215816SMarri Devender Rao * @brief Read data from CSR D-bus object and set to response 17930215816SMarri Devender Rao * 18030215816SMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 18130215816SMarri Devender Rao * @param[in] certURI Link to certifiate collection URI 18230215816SMarri Devender Rao * @param[in] service D-Bus service name 18330215816SMarri Devender Rao * @param[in] certObjPath certificate D-Bus object path 18430215816SMarri Devender Rao * @param[in] csrObjPath CSR D-Bus object path 18530215816SMarri Devender Rao * @return None 18630215816SMarri Devender Rao */ 1878d1b46d7Szhanghch05 static void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 18830215816SMarri Devender Rao const std::string& certURI, const std::string& service, 18930215816SMarri Devender Rao const std::string& certObjPath, 19030215816SMarri Devender Rao const std::string& csrObjPath) 19130215816SMarri Devender Rao { 19230215816SMarri Devender Rao BMCWEB_LOG_DEBUG << "getCSR CertObjectPath" << certObjPath 19330215816SMarri Devender Rao << " CSRObjectPath=" << csrObjPath 19430215816SMarri Devender Rao << " service=" << service; 19530215816SMarri Devender Rao crow::connections::systemBus->async_method_call( 19630215816SMarri Devender Rao [asyncResp, certURI](const boost::system::error_code ec, 19730215816SMarri Devender Rao const std::string& csr) { 19830215816SMarri Devender Rao if (ec) 19930215816SMarri Devender Rao { 20030215816SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 20130215816SMarri Devender Rao messages::internalError(asyncResp->res); 20230215816SMarri Devender Rao return; 20330215816SMarri Devender Rao } 20430215816SMarri Devender Rao if (csr.empty()) 20530215816SMarri Devender Rao { 20630215816SMarri Devender Rao BMCWEB_LOG_ERROR << "CSR read is empty"; 20730215816SMarri Devender Rao messages::internalError(asyncResp->res); 20830215816SMarri Devender Rao return; 20930215816SMarri Devender Rao } 21030215816SMarri Devender Rao asyncResp->res.jsonValue["CSRString"] = csr; 2111476687dSEd Tanous asyncResp->res.jsonValue["CertificateCollection"]["@odata.id"] = 2121476687dSEd Tanous certURI; 21330215816SMarri Devender Rao }, 21430215816SMarri Devender Rao service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR"); 21530215816SMarri Devender Rao } 21630215816SMarri Devender Rao 21730215816SMarri Devender Rao /** 21830215816SMarri Devender Rao * Action to Generate CSR 21930215816SMarri Devender Rao */ 2207e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionGenerateCSR(App& app) 22130215816SMarri Devender Rao { 2220fda0f12SGeorge Liu BMCWEB_ROUTE( 2230fda0f12SGeorge Liu app, 2240fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR/") 2255344ab8eSAbhishek Patel .privileges(redfish::privileges::postCertificateService) 226002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 227002d39b4SEd Tanous [&app](const crow::Request& req, 2287e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 2293ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 23045ca1b86SEd Tanous { 23145ca1b86SEd Tanous return; 23245ca1b86SEd Tanous } 2332c70f800SEd Tanous static const int rsaKeyBitLength = 2048; 2348d1b46d7Szhanghch05 23530215816SMarri Devender Rao // Required parameters 23630215816SMarri Devender Rao std::string city; 23730215816SMarri Devender Rao std::string commonName; 23830215816SMarri Devender Rao std::string country; 23930215816SMarri Devender Rao std::string organization; 24030215816SMarri Devender Rao std::string organizationalUnit; 24130215816SMarri Devender Rao std::string state; 24230215816SMarri Devender Rao nlohmann::json certificateCollection; 24330215816SMarri Devender Rao 24430215816SMarri Devender Rao // Optional parameters 24530215816SMarri Devender Rao std::optional<std::vector<std::string>> optAlternativeNames = 24630215816SMarri Devender Rao std::vector<std::string>(); 24730215816SMarri Devender Rao std::optional<std::string> optContactPerson = ""; 24830215816SMarri Devender Rao std::optional<std::string> optChallengePassword = ""; 24930215816SMarri Devender Rao std::optional<std::string> optEmail = ""; 25030215816SMarri Devender Rao std::optional<std::string> optGivenName = ""; 25130215816SMarri Devender Rao std::optional<std::string> optInitials = ""; 2522c70f800SEd Tanous std::optional<int64_t> optKeyBitLength = rsaKeyBitLength; 253aaf3206fSVernon Mauery std::optional<std::string> optKeyCurveId = "secp384r1"; 25430215816SMarri Devender Rao std::optional<std::string> optKeyPairAlgorithm = "EC"; 25530215816SMarri Devender Rao std::optional<std::vector<std::string>> optKeyUsage = 25630215816SMarri Devender Rao std::vector<std::string>(); 25730215816SMarri Devender Rao std::optional<std::string> optSurname = ""; 25830215816SMarri Devender Rao std::optional<std::string> optUnstructuredName = ""; 25915ed6780SWilly Tu if (!json_util::readJsonAction( 2600fda0f12SGeorge Liu req, asyncResp->res, "City", city, "CommonName", commonName, 2610fda0f12SGeorge Liu "ContactPerson", optContactPerson, "Country", country, 2620fda0f12SGeorge Liu "Organization", organization, "OrganizationalUnit", 2630fda0f12SGeorge Liu organizationalUnit, "State", state, "CertificateCollection", 264002d39b4SEd Tanous certificateCollection, "AlternativeNames", optAlternativeNames, 265002d39b4SEd Tanous "ChallengePassword", optChallengePassword, "Email", optEmail, 266002d39b4SEd Tanous "GivenName", optGivenName, "Initials", optInitials, 267002d39b4SEd Tanous "KeyBitLength", optKeyBitLength, "KeyCurveId", optKeyCurveId, 2680fda0f12SGeorge Liu "KeyPairAlgorithm", optKeyPairAlgorithm, "KeyUsage", 2690fda0f12SGeorge Liu optKeyUsage, "Surname", optSurname, "UnstructuredName", 2700fda0f12SGeorge Liu optUnstructuredName)) 27130215816SMarri Devender Rao { 27230215816SMarri Devender Rao return; 27330215816SMarri Devender Rao } 27430215816SMarri Devender Rao 27530215816SMarri Devender Rao // bmcweb has no way to store or decode a private key challenge 2767e860f15SJohn Edward Broadbent // password, which will likely cause bmcweb to crash on startup 2777e860f15SJohn Edward Broadbent // if this is not set on a post so not allowing the user to set 2787e860f15SJohn Edward Broadbent // value 27926f6976fSEd Tanous if (!optChallengePassword->empty()) 28030215816SMarri Devender Rao { 281002d39b4SEd Tanous messages::actionParameterNotSupported(asyncResp->res, "GenerateCSR", 282002d39b4SEd Tanous "ChallengePassword"); 28330215816SMarri Devender Rao return; 28430215816SMarri Devender Rao } 28530215816SMarri Devender Rao 28630215816SMarri Devender Rao std::string certURI; 287002d39b4SEd Tanous if (!redfish::json_util::readJson(certificateCollection, asyncResp->res, 288002d39b4SEd Tanous "@odata.id", certURI)) 28930215816SMarri Devender Rao { 29030215816SMarri Devender Rao return; 29130215816SMarri Devender Rao } 29230215816SMarri Devender Rao 29330215816SMarri Devender Rao std::string objectPath; 29430215816SMarri Devender Rao std::string service; 29511ba3979SEd Tanous if (certURI.starts_with( 2960fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) 29730215816SMarri Devender Rao { 29830215816SMarri Devender Rao objectPath = certs::httpsObjectPath; 29930215816SMarri Devender Rao service = certs::httpsServiceName; 30030215816SMarri Devender Rao } 30111ba3979SEd Tanous else if (certURI.starts_with( 30211ba3979SEd Tanous "/redfish/v1/AccountService/LDAP/Certificates")) 3033b7f0149SMarri Devender Rao { 3043b7f0149SMarri Devender Rao objectPath = certs::ldapObjectPath; 3053b7f0149SMarri Devender Rao service = certs::ldapServiceName; 3063b7f0149SMarri Devender Rao } 30730215816SMarri Devender Rao else 30830215816SMarri Devender Rao { 30930215816SMarri Devender Rao messages::actionParameterNotSupported( 31030215816SMarri Devender Rao asyncResp->res, "CertificateCollection", "GenerateCSR"); 31130215816SMarri Devender Rao return; 31230215816SMarri Devender Rao } 31330215816SMarri Devender Rao 31430215816SMarri Devender Rao // supporting only EC and RSA algorithm 3150fda0f12SGeorge Liu if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA") 31630215816SMarri Devender Rao { 31730215816SMarri Devender Rao messages::actionParameterNotSupported( 31830215816SMarri Devender Rao asyncResp->res, "KeyPairAlgorithm", "GenerateCSR"); 31930215816SMarri Devender Rao return; 32030215816SMarri Devender Rao } 32130215816SMarri Devender Rao 3227e860f15SJohn Edward Broadbent // supporting only 2048 key bit length for RSA algorithm due to 3237e860f15SJohn Edward Broadbent // time consumed in generating private key 32430215816SMarri Devender Rao if (*optKeyPairAlgorithm == "RSA" && 3252c70f800SEd Tanous *optKeyBitLength != rsaKeyBitLength) 32630215816SMarri Devender Rao { 327002d39b4SEd Tanous messages::propertyValueNotInList(asyncResp->res, 328002d39b4SEd Tanous std::to_string(*optKeyBitLength), 32930215816SMarri Devender Rao "KeyBitLength"); 33030215816SMarri Devender Rao return; 33130215816SMarri Devender Rao } 33230215816SMarri Devender Rao 33330215816SMarri Devender Rao // validate KeyUsage supporting only 1 type based on URL 33411ba3979SEd Tanous if (certURI.starts_with( 3350fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) 33630215816SMarri Devender Rao { 33726f6976fSEd Tanous if (optKeyUsage->empty()) 33830215816SMarri Devender Rao { 33930215816SMarri Devender Rao optKeyUsage->push_back("ServerAuthentication"); 34030215816SMarri Devender Rao } 34130215816SMarri Devender Rao else if (optKeyUsage->size() == 1) 34230215816SMarri Devender Rao { 34330215816SMarri Devender Rao if ((*optKeyUsage)[0] != "ServerAuthentication") 34430215816SMarri Devender Rao { 34530215816SMarri Devender Rao messages::propertyValueNotInList( 34630215816SMarri Devender Rao asyncResp->res, (*optKeyUsage)[0], "KeyUsage"); 34730215816SMarri Devender Rao return; 34830215816SMarri Devender Rao } 34930215816SMarri Devender Rao } 35030215816SMarri Devender Rao else 35130215816SMarri Devender Rao { 35230215816SMarri Devender Rao messages::actionParameterNotSupported( 35330215816SMarri Devender Rao asyncResp->res, "KeyUsage", "GenerateCSR"); 35430215816SMarri Devender Rao return; 35530215816SMarri Devender Rao } 35630215816SMarri Devender Rao } 35711ba3979SEd Tanous else if (certURI.starts_with( 35811ba3979SEd Tanous "/redfish/v1/AccountService/LDAP/Certificates")) 3593b7f0149SMarri Devender Rao { 36026f6976fSEd Tanous if (optKeyUsage->empty()) 3613b7f0149SMarri Devender Rao { 3623b7f0149SMarri Devender Rao optKeyUsage->push_back("ClientAuthentication"); 3633b7f0149SMarri Devender Rao } 3643b7f0149SMarri Devender Rao else if (optKeyUsage->size() == 1) 3653b7f0149SMarri Devender Rao { 3663b7f0149SMarri Devender Rao if ((*optKeyUsage)[0] != "ClientAuthentication") 3673b7f0149SMarri Devender Rao { 3683b7f0149SMarri Devender Rao messages::propertyValueNotInList( 3693b7f0149SMarri Devender Rao asyncResp->res, (*optKeyUsage)[0], "KeyUsage"); 3703b7f0149SMarri Devender Rao return; 3713b7f0149SMarri Devender Rao } 3723b7f0149SMarri Devender Rao } 3733b7f0149SMarri Devender Rao else 3743b7f0149SMarri Devender Rao { 3753b7f0149SMarri Devender Rao messages::actionParameterNotSupported( 3763b7f0149SMarri Devender Rao asyncResp->res, "KeyUsage", "GenerateCSR"); 3773b7f0149SMarri Devender Rao return; 3783b7f0149SMarri Devender Rao } 3793b7f0149SMarri Devender Rao } 38030215816SMarri Devender Rao 3817e860f15SJohn Edward Broadbent // Only allow one CSR matcher at a time so setting retry 3827e860f15SJohn Edward Broadbent // time-out and timer expiry to 10 seconds for now. 3832c70f800SEd Tanous static const int timeOut = 10; 38430215816SMarri Devender Rao if (csrMatcher) 38530215816SMarri Devender Rao { 386002d39b4SEd Tanous messages::serviceTemporarilyUnavailable(asyncResp->res, 387002d39b4SEd Tanous std::to_string(timeOut)); 38830215816SMarri Devender Rao return; 38930215816SMarri Devender Rao } 39030215816SMarri Devender Rao 39130215816SMarri Devender Rao // Make this static so it survives outside this method 39230215816SMarri Devender Rao static boost::asio::steady_timer timeout(*req.ioService); 3932c70f800SEd Tanous timeout.expires_after(std::chrono::seconds(timeOut)); 394002d39b4SEd Tanous timeout.async_wait([asyncResp](const boost::system::error_code& ec) { 39530215816SMarri Devender Rao csrMatcher = nullptr; 39630215816SMarri Devender Rao if (ec) 39730215816SMarri Devender Rao { 3987e860f15SJohn Edward Broadbent // operation_aborted is expected if timer is canceled 3997e860f15SJohn Edward Broadbent // before completion. 40030215816SMarri Devender Rao if (ec != boost::asio::error::operation_aborted) 40130215816SMarri Devender Rao { 40230215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Async_wait failed " << ec; 40330215816SMarri Devender Rao } 40430215816SMarri Devender Rao return; 40530215816SMarri Devender Rao } 40630215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR"; 40730215816SMarri Devender Rao messages::internalError(asyncResp->res); 40830215816SMarri Devender Rao }); 40930215816SMarri Devender Rao 41030215816SMarri Devender Rao // create a matcher to wait on CSR object 41130215816SMarri Devender Rao BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath; 4120fda0f12SGeorge Liu std::string match("type='signal'," 41330215816SMarri Devender Rao "interface='org.freedesktop.DBus.ObjectManager'," 41430215816SMarri Devender Rao "path='" + 41530215816SMarri Devender Rao objectPath + 41630215816SMarri Devender Rao "'," 41730215816SMarri Devender Rao "member='InterfacesAdded'"); 41859d494eeSPatrick Williams csrMatcher = std::make_unique<sdbusplus::bus::match_t>( 41930215816SMarri Devender Rao *crow::connections::systemBus, match, 42059d494eeSPatrick Williams [asyncResp, service, objectPath, certURI](sdbusplus::message_t& m) { 421271584abSEd Tanous timeout.cancel(); 42230215816SMarri Devender Rao if (m.is_method_error()) 42330215816SMarri Devender Rao { 42430215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Dbus method error!!!"; 42530215816SMarri Devender Rao messages::internalError(asyncResp->res); 42630215816SMarri Devender Rao return; 42730215816SMarri Devender Rao } 428b9d36b47SEd Tanous 429b9d36b47SEd Tanous dbus::utility::DBusInteracesMap interfacesProperties; 430b9d36b47SEd Tanous 43130215816SMarri Devender Rao sdbusplus::message::object_path csrObjectPath; 43230215816SMarri Devender Rao m.read(csrObjectPath, interfacesProperties); 4330fda0f12SGeorge Liu BMCWEB_LOG_DEBUG << "CSR object added" << csrObjectPath.str; 43402cad96eSEd Tanous for (const auto& interface : interfacesProperties) 43530215816SMarri Devender Rao { 4360fda0f12SGeorge Liu if (interface.first == "xyz.openbmc_project.Certs.CSR") 43730215816SMarri Devender Rao { 43830215816SMarri Devender Rao getCSR(asyncResp, certURI, service, objectPath, 43930215816SMarri Devender Rao csrObjectPath.str); 44030215816SMarri Devender Rao break; 44130215816SMarri Devender Rao } 44230215816SMarri Devender Rao } 44330215816SMarri Devender Rao }); 44430215816SMarri Devender Rao crow::connections::systemBus->async_method_call( 445914e2d5dSEd Tanous [asyncResp](const boost::system::error_code ec, 446cb13a392SEd Tanous const std::string&) { 44730215816SMarri Devender Rao if (ec) 44830215816SMarri Devender Rao { 449002d39b4SEd Tanous BMCWEB_LOG_ERROR << "DBUS response error: " << ec.message(); 45030215816SMarri Devender Rao messages::internalError(asyncResp->res); 45130215816SMarri Devender Rao return; 45230215816SMarri Devender Rao } 45330215816SMarri Devender Rao }, 45430215816SMarri Devender Rao service, objectPath, "xyz.openbmc_project.Certs.CSR.Create", 455002d39b4SEd Tanous "GenerateCSR", *optAlternativeNames, *optChallengePassword, city, 456002d39b4SEd Tanous commonName, *optContactPerson, country, *optEmail, *optGivenName, 457002d39b4SEd Tanous *optInitials, *optKeyBitLength, *optKeyCurveId, 4580fda0f12SGeorge Liu *optKeyPairAlgorithm, *optKeyUsage, organization, 4590fda0f12SGeorge Liu organizationalUnit, state, *optSurname, *optUnstructuredName); 4607e860f15SJohn Edward Broadbent }); 4617e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionGenerateCSR 46230215816SMarri Devender Rao 4635968caeeSMarri Devender Rao /** 4644e0453b1SGunnar Mills * @brief Parse and update Certificate Issue/Subject property 4655968caeeSMarri Devender Rao * 4665968caeeSMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 4675968caeeSMarri Devender Rao * @param[in] str Issuer/Subject value in key=value pairs 4685968caeeSMarri Devender Rao * @param[in] type Issuer/Subject 4695968caeeSMarri Devender Rao * @return None 4705968caeeSMarri Devender Rao */ 4715968caeeSMarri Devender Rao static void updateCertIssuerOrSubject(nlohmann::json& out, 4725968caeeSMarri Devender Rao const std::string_view value) 4735968caeeSMarri Devender Rao { 4745968caeeSMarri Devender Rao // example: O=openbmc-project.xyz,CN=localhost 4755968caeeSMarri Devender Rao std::string_view::iterator i = value.begin(); 4765968caeeSMarri Devender Rao while (i != value.end()) 4775968caeeSMarri Devender Rao { 4785968caeeSMarri Devender Rao std::string_view::iterator tokenBegin = i; 4795968caeeSMarri Devender Rao while (i != value.end() && *i != '=') 4805968caeeSMarri Devender Rao { 48117a897dfSManojkiran Eda ++i; 4825968caeeSMarri Devender Rao } 4835968caeeSMarri Devender Rao if (i == value.end()) 4845968caeeSMarri Devender Rao { 4855968caeeSMarri Devender Rao break; 4865968caeeSMarri Devender Rao } 487271584abSEd Tanous const std::string_view key(tokenBegin, 488271584abSEd Tanous static_cast<size_t>(i - tokenBegin)); 48917a897dfSManojkiran Eda ++i; 4905968caeeSMarri Devender Rao tokenBegin = i; 4915968caeeSMarri Devender Rao while (i != value.end() && *i != ',') 4925968caeeSMarri Devender Rao { 49317a897dfSManojkiran Eda ++i; 4945968caeeSMarri Devender Rao } 495271584abSEd Tanous const std::string_view val(tokenBegin, 496271584abSEd Tanous static_cast<size_t>(i - tokenBegin)); 4975968caeeSMarri Devender Rao if (key == "L") 4985968caeeSMarri Devender Rao { 4995968caeeSMarri Devender Rao out["City"] = val; 5005968caeeSMarri Devender Rao } 5015968caeeSMarri Devender Rao else if (key == "CN") 5025968caeeSMarri Devender Rao { 5035968caeeSMarri Devender Rao out["CommonName"] = val; 5045968caeeSMarri Devender Rao } 5055968caeeSMarri Devender Rao else if (key == "C") 5065968caeeSMarri Devender Rao { 5075968caeeSMarri Devender Rao out["Country"] = val; 5085968caeeSMarri Devender Rao } 5095968caeeSMarri Devender Rao else if (key == "O") 5105968caeeSMarri Devender Rao { 5115968caeeSMarri Devender Rao out["Organization"] = val; 5125968caeeSMarri Devender Rao } 5135968caeeSMarri Devender Rao else if (key == "OU") 5145968caeeSMarri Devender Rao { 5155968caeeSMarri Devender Rao out["OrganizationalUnit"] = val; 5165968caeeSMarri Devender Rao } 5175968caeeSMarri Devender Rao else if (key == "ST") 5185968caeeSMarri Devender Rao { 5195968caeeSMarri Devender Rao out["State"] = val; 5205968caeeSMarri Devender Rao } 5215968caeeSMarri Devender Rao // skip comma character 5225968caeeSMarri Devender Rao if (i != value.end()) 5235968caeeSMarri Devender Rao { 52417a897dfSManojkiran Eda ++i; 5255968caeeSMarri Devender Rao } 5265968caeeSMarri Devender Rao } 5275968caeeSMarri Devender Rao } 5285968caeeSMarri Devender Rao 5295968caeeSMarri Devender Rao /** 530d3f92ce7SJiaqing Zhao * @brief Retrieve the installed certificate list 531d3f92ce7SJiaqing Zhao * 532d3f92ce7SJiaqing Zhao * @param[in] asyncResp Shared pointer to the response message 533d3f92ce7SJiaqing Zhao * @param[in] basePath DBus object path to search 534d3f92ce7SJiaqing Zhao * @param[in] listPtr Json pointer to the list in asyncResp 535d3f92ce7SJiaqing Zhao * @param[in] countPtr Json pointer to the count in asyncResp 536d3f92ce7SJiaqing Zhao * @return None 537d3f92ce7SJiaqing Zhao */ 538d3f92ce7SJiaqing Zhao static void 539d3f92ce7SJiaqing Zhao getCertificateList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 540d3f92ce7SJiaqing Zhao const std::string& basePath, 541d3f92ce7SJiaqing Zhao const nlohmann::json::json_pointer& listPtr, 542d3f92ce7SJiaqing Zhao const nlohmann::json::json_pointer& countPtr) 543d3f92ce7SJiaqing Zhao { 544d3f92ce7SJiaqing Zhao crow::connections::systemBus->async_method_call( 545d3f92ce7SJiaqing Zhao [asyncResp, listPtr, countPtr]( 546d3f92ce7SJiaqing Zhao const boost::system::error_code ec, 547d3f92ce7SJiaqing Zhao const dbus::utility::MapperGetSubTreePathsResponse& certPaths) { 548d3f92ce7SJiaqing Zhao if (ec) 549d3f92ce7SJiaqing Zhao { 550d3f92ce7SJiaqing Zhao BMCWEB_LOG_ERROR << "Certificate collection query failed: " << ec; 551d3f92ce7SJiaqing Zhao messages::internalError(asyncResp->res); 552d3f92ce7SJiaqing Zhao return; 553d3f92ce7SJiaqing Zhao } 554d3f92ce7SJiaqing Zhao 555d3f92ce7SJiaqing Zhao nlohmann::json& links = asyncResp->res.jsonValue[listPtr]; 556d3f92ce7SJiaqing Zhao links = nlohmann::json::array(); 557d3f92ce7SJiaqing Zhao for (const auto& certPath : certPaths) 558d3f92ce7SJiaqing Zhao { 559d3f92ce7SJiaqing Zhao sdbusplus::message::object_path objPath(certPath); 560d3f92ce7SJiaqing Zhao std::string certId = objPath.filename(); 561d3f92ce7SJiaqing Zhao if (certId.empty()) 562d3f92ce7SJiaqing Zhao { 563d3f92ce7SJiaqing Zhao BMCWEB_LOG_ERROR << "Invalid certificate objPath " << certPath; 564d3f92ce7SJiaqing Zhao continue; 565d3f92ce7SJiaqing Zhao } 566d3f92ce7SJiaqing Zhao 567d3f92ce7SJiaqing Zhao boost::urls::url certURL; 568d3f92ce7SJiaqing Zhao if (objPath.parent_path() == certs::httpsObjectPath) 569d3f92ce7SJiaqing Zhao { 570d3f92ce7SJiaqing Zhao certURL = crow::utility::urlFromPieces( 571d3f92ce7SJiaqing Zhao "redfish", "v1", "Managers", "bmc", "NetworkProtocol", 572d3f92ce7SJiaqing Zhao "HTTPS", "Certificates", certId); 573d3f92ce7SJiaqing Zhao } 574d3f92ce7SJiaqing Zhao else if (objPath.parent_path() == certs::ldapObjectPath) 575d3f92ce7SJiaqing Zhao { 576d3f92ce7SJiaqing Zhao certURL = crow::utility::urlFromPieces("redfish", "v1", 577d3f92ce7SJiaqing Zhao "AccountService", "LDAP", 578d3f92ce7SJiaqing Zhao "Certificates", certId); 579d3f92ce7SJiaqing Zhao } 580d3f92ce7SJiaqing Zhao else if (objPath.parent_path() == certs::authorityObjectPath) 581d3f92ce7SJiaqing Zhao { 582d3f92ce7SJiaqing Zhao certURL = crow::utility::urlFromPieces( 583d3f92ce7SJiaqing Zhao "redfish", "v1", "Managers", "bmc", "Truststore", 584d3f92ce7SJiaqing Zhao "Certificates", certId); 585d3f92ce7SJiaqing Zhao } 586d3f92ce7SJiaqing Zhao else 587d3f92ce7SJiaqing Zhao { 588d3f92ce7SJiaqing Zhao continue; 589d3f92ce7SJiaqing Zhao } 590d3f92ce7SJiaqing Zhao 591d3f92ce7SJiaqing Zhao nlohmann::json::object_t link; 592d3f92ce7SJiaqing Zhao link["@odata.id"] = certURL; 593d3f92ce7SJiaqing Zhao links.emplace_back(std::move(link)); 594d3f92ce7SJiaqing Zhao } 595d3f92ce7SJiaqing Zhao 596d3f92ce7SJiaqing Zhao asyncResp->res.jsonValue[countPtr] = links.size(); 597d3f92ce7SJiaqing Zhao }, 598d3f92ce7SJiaqing Zhao "xyz.openbmc_project.ObjectMapper", 599d3f92ce7SJiaqing Zhao "/xyz/openbmc_project/object_mapper", 600d3f92ce7SJiaqing Zhao "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", basePath, 0, 601d3f92ce7SJiaqing Zhao std::array<const char*, 1>{certs::certPropIntf}); 602d3f92ce7SJiaqing Zhao } 603d3f92ce7SJiaqing Zhao 604d3f92ce7SJiaqing Zhao /** 6055968caeeSMarri Devender Rao * @brief Retrieve the certificates properties and append to the response 6065968caeeSMarri Devender Rao * message 6075968caeeSMarri Devender Rao * 6085968caeeSMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 6095968caeeSMarri Devender Rao * @param[in] objectPath Path of the D-Bus service object 6105968caeeSMarri Devender Rao * @param[in] certId Id of the certificate 6115968caeeSMarri Devender Rao * @param[in] certURL URL of the certificate object 6125968caeeSMarri Devender Rao * @param[in] name name of the certificate 6135968caeeSMarri Devender Rao * @return None 6145968caeeSMarri Devender Rao */ 6155968caeeSMarri Devender Rao static void getCertificateProperties( 6168d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 617e19e97e2SJiaqing Zhao const std::string& objectPath, const std::string& service, 618e19e97e2SJiaqing Zhao const std::string& certId, const std::string& certURL, 619e19e97e2SJiaqing Zhao const std::string& name) 6205968caeeSMarri Devender Rao { 6215968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "getCertificateProperties Path=" << objectPath 6225968caeeSMarri Devender Rao << " certId=" << certId << " certURl=" << certURL; 6235968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 624b9d36b47SEd Tanous [asyncResp, certURL, certId, 625b9d36b47SEd Tanous name](const boost::system::error_code ec, 626b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& properties) { 6275968caeeSMarri Devender Rao if (ec) 6285968caeeSMarri Devender Rao { 6295968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 630e19e97e2SJiaqing Zhao messages::resourceNotFound(asyncResp->res, name, certId); 6315968caeeSMarri Devender Rao return; 6325968caeeSMarri Devender Rao } 6331476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = certURL; 6341476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 6351476687dSEd Tanous "#Certificate.v1_0_0.Certificate"; 636e19e97e2SJiaqing Zhao asyncResp->res.jsonValue["Id"] = certId; 6371476687dSEd Tanous asyncResp->res.jsonValue["Name"] = name; 6381476687dSEd Tanous asyncResp->res.jsonValue["Description"] = name; 6395968caeeSMarri Devender Rao for (const auto& property : properties) 6405968caeeSMarri Devender Rao { 6415968caeeSMarri Devender Rao if (property.first == "CertificateString") 6425968caeeSMarri Devender Rao { 6435968caeeSMarri Devender Rao asyncResp->res.jsonValue["CertificateString"] = ""; 6445968caeeSMarri Devender Rao const std::string* value = 6455968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 646e662eae8SEd Tanous if (value != nullptr) 6475968caeeSMarri Devender Rao { 64837cce918SMarri Devender Rao asyncResp->res.jsonValue["CertificateString"] = *value; 6495968caeeSMarri Devender Rao } 6505968caeeSMarri Devender Rao } 6515968caeeSMarri Devender Rao else if (property.first == "KeyUsage") 6525968caeeSMarri Devender Rao { 653002d39b4SEd Tanous nlohmann::json& keyUsage = asyncResp->res.jsonValue["KeyUsage"]; 6545968caeeSMarri Devender Rao keyUsage = nlohmann::json::array(); 6555968caeeSMarri Devender Rao const std::vector<std::string>* value = 65637cce918SMarri Devender Rao std::get_if<std::vector<std::string>>(&property.second); 657e662eae8SEd Tanous if (value != nullptr) 6585968caeeSMarri Devender Rao { 6595968caeeSMarri Devender Rao for (const std::string& usage : *value) 6605968caeeSMarri Devender Rao { 6615968caeeSMarri Devender Rao keyUsage.push_back(usage); 6625968caeeSMarri Devender Rao } 6635968caeeSMarri Devender Rao } 6645968caeeSMarri Devender Rao } 6655968caeeSMarri Devender Rao else if (property.first == "Issuer") 6665968caeeSMarri Devender Rao { 6675968caeeSMarri Devender Rao const std::string* value = 6685968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 669e662eae8SEd Tanous if (value != nullptr) 6705968caeeSMarri Devender Rao { 6715968caeeSMarri Devender Rao updateCertIssuerOrSubject( 6725968caeeSMarri Devender Rao asyncResp->res.jsonValue["Issuer"], *value); 6735968caeeSMarri Devender Rao } 6745968caeeSMarri Devender Rao } 6755968caeeSMarri Devender Rao else if (property.first == "Subject") 6765968caeeSMarri Devender Rao { 6775968caeeSMarri Devender Rao const std::string* value = 6785968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 679e662eae8SEd Tanous if (value != nullptr) 6805968caeeSMarri Devender Rao { 6815968caeeSMarri Devender Rao updateCertIssuerOrSubject( 68237cce918SMarri Devender Rao asyncResp->res.jsonValue["Subject"], *value); 6835968caeeSMarri Devender Rao } 6845968caeeSMarri Devender Rao } 6855968caeeSMarri Devender Rao else if (property.first == "ValidNotAfter") 6865968caeeSMarri Devender Rao { 687002d39b4SEd Tanous const uint64_t* value = std::get_if<uint64_t>(&property.second); 688e662eae8SEd Tanous if (value != nullptr) 6895968caeeSMarri Devender Rao { 6905968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotAfter"] = 6911d8782e7SNan Zhou crow::utility::getDateTimeUint(*value); 6925968caeeSMarri Devender Rao } 6935968caeeSMarri Devender Rao } 6945968caeeSMarri Devender Rao else if (property.first == "ValidNotBefore") 6955968caeeSMarri Devender Rao { 696002d39b4SEd Tanous const uint64_t* value = std::get_if<uint64_t>(&property.second); 697e662eae8SEd Tanous if (value != nullptr) 6985968caeeSMarri Devender Rao { 6995968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotBefore"] = 7001d8782e7SNan Zhou crow::utility::getDateTimeUint(*value); 7015968caeeSMarri Devender Rao } 7025968caeeSMarri Devender Rao } 7035968caeeSMarri Devender Rao } 7045968caeeSMarri Devender Rao asyncResp->res.addHeader("Location", certURL); 7055968caeeSMarri Devender Rao }, 7065968caeeSMarri Devender Rao service, objectPath, certs::dbusPropIntf, "GetAll", 7075968caeeSMarri Devender Rao certs::certPropIntf); 7085968caeeSMarri Devender Rao } 7095968caeeSMarri Devender Rao 7105968caeeSMarri Devender Rao /** 7115968caeeSMarri Devender Rao * Action to replace an existing certificate 7125968caeeSMarri Devender Rao */ 7137e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionsReplaceCertificate(App& app) 7145968caeeSMarri Devender Rao { 7150fda0f12SGeorge Liu BMCWEB_ROUTE( 7160fda0f12SGeorge Liu app, 7170fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate/") 718ed398213SEd Tanous .privileges(redfish::privileges::postCertificateService) 719002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 720002d39b4SEd Tanous [&app](const crow::Request& req, 7217e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 7223ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 72345ca1b86SEd Tanous { 72445ca1b86SEd Tanous return; 72545ca1b86SEd Tanous } 7265968caeeSMarri Devender Rao std::string certificate; 7275968caeeSMarri Devender Rao nlohmann::json certificateUri; 7285968caeeSMarri Devender Rao std::optional<std::string> certificateType = "PEM"; 7298d1b46d7Szhanghch05 730002d39b4SEd Tanous if (!json_util::readJsonAction(req, asyncResp->res, "CertificateString", 731002d39b4SEd Tanous certificate, "CertificateUri", 732002d39b4SEd Tanous certificateUri, "CertificateType", 733002d39b4SEd Tanous certificateType)) 7345968caeeSMarri Devender Rao { 7355968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Required parameters are missing"; 7365968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 7375968caeeSMarri Devender Rao return; 7385968caeeSMarri Devender Rao } 7395968caeeSMarri Devender Rao 7405968caeeSMarri Devender Rao if (!certificateType) 7415968caeeSMarri Devender Rao { 7425968caeeSMarri Devender Rao // should never happen, but it never hurts to be paranoid. 7435968caeeSMarri Devender Rao return; 7445968caeeSMarri Devender Rao } 7455968caeeSMarri Devender Rao if (certificateType != "PEM") 7465968caeeSMarri Devender Rao { 7475968caeeSMarri Devender Rao messages::actionParameterNotSupported( 7485968caeeSMarri Devender Rao asyncResp->res, "CertificateType", "ReplaceCertificate"); 7495968caeeSMarri Devender Rao return; 7505968caeeSMarri Devender Rao } 7515968caeeSMarri Devender Rao 7525968caeeSMarri Devender Rao std::string certURI; 7535968caeeSMarri Devender Rao if (!redfish::json_util::readJson(certificateUri, asyncResp->res, 7545968caeeSMarri Devender Rao "@odata.id", certURI)) 7555968caeeSMarri Devender Rao { 7565968caeeSMarri Devender Rao messages::actionParameterMissing( 7575968caeeSMarri Devender Rao asyncResp->res, "ReplaceCertificate", "CertificateUri"); 7585968caeeSMarri Devender Rao return; 7595968caeeSMarri Devender Rao } 760*75b63a2cSJiaqing Zhao BMCWEB_LOG_INFO << "Certificate URI to replace: " << certURI; 7615968caeeSMarri Devender Rao 762*75b63a2cSJiaqing Zhao boost::urls::result<boost::urls::url_view> parsedUrl = 763*75b63a2cSJiaqing Zhao boost::urls::parse_relative_ref(certURI); 764*75b63a2cSJiaqing Zhao if (!parsedUrl) 7655968caeeSMarri Devender Rao { 766002d39b4SEd Tanous messages::actionParameterValueFormatError(asyncResp->res, certURI, 767002d39b4SEd Tanous "CertificateUri", 7685968caeeSMarri Devender Rao "ReplaceCertificate"); 7695968caeeSMarri Devender Rao return; 7705968caeeSMarri Devender Rao } 771*75b63a2cSJiaqing Zhao 772*75b63a2cSJiaqing Zhao std::string id; 773*75b63a2cSJiaqing Zhao sdbusplus::message::object_path objectPath; 7745968caeeSMarri Devender Rao std::string name; 77537cce918SMarri Devender Rao std::string service; 776*75b63a2cSJiaqing Zhao if (crow::utility::readUrlSegments( 777*75b63a2cSJiaqing Zhao *parsedUrl, "redfish", "v1", "Managers", "bmc", 778*75b63a2cSJiaqing Zhao "NetworkProtocol", "HTTPS", "Certificates", std::ref(id))) 7795968caeeSMarri Devender Rao { 780002d39b4SEd Tanous objectPath = 781*75b63a2cSJiaqing Zhao sdbusplus::message::object_path(certs::httpsObjectPath) / id; 7825968caeeSMarri Devender Rao name = "HTTPS certificate"; 78337cce918SMarri Devender Rao service = certs::httpsServiceName; 78437cce918SMarri Devender Rao } 785*75b63a2cSJiaqing Zhao else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1", 786*75b63a2cSJiaqing Zhao "AccountService", "LDAP", 787*75b63a2cSJiaqing Zhao "Certificates", std::ref(id))) 78837cce918SMarri Devender Rao { 789002d39b4SEd Tanous objectPath = 790*75b63a2cSJiaqing Zhao sdbusplus::message::object_path(certs::ldapObjectPath) / id; 79137cce918SMarri Devender Rao name = "LDAP certificate"; 79237cce918SMarri Devender Rao service = certs::ldapServiceName; 7935968caeeSMarri Devender Rao } 794*75b63a2cSJiaqing Zhao else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1", 795*75b63a2cSJiaqing Zhao "Managers", "bmc", "Truststore", 796*75b63a2cSJiaqing Zhao "Certificates", std::ref(id))) 797cfcd5f6bSMarri Devender Rao { 798*75b63a2cSJiaqing Zhao objectPath = 799*75b63a2cSJiaqing Zhao sdbusplus::message::object_path(certs::authorityObjectPath) / 800*75b63a2cSJiaqing Zhao id; 801cfcd5f6bSMarri Devender Rao name = "TrustStore certificate"; 802cfcd5f6bSMarri Devender Rao service = certs::authorityServiceName; 803cfcd5f6bSMarri Devender Rao } 8045968caeeSMarri Devender Rao else 8055968caeeSMarri Devender Rao { 8065968caeeSMarri Devender Rao messages::actionParameterNotSupported( 8075968caeeSMarri Devender Rao asyncResp->res, "CertificateUri", "ReplaceCertificate"); 8085968caeeSMarri Devender Rao return; 8095968caeeSMarri Devender Rao } 8105968caeeSMarri Devender Rao 8115968caeeSMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 8125968caeeSMarri Devender Rao std::make_shared<CertificateFile>(certificate); 8135968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 81437cce918SMarri Devender Rao [asyncResp, certFile, objectPath, service, certURI, id, 8155968caeeSMarri Devender Rao name](const boost::system::error_code ec) { 8165968caeeSMarri Devender Rao if (ec) 8175968caeeSMarri Devender Rao { 8185968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 81990d2d1e8SJiaqing Zhao if (ec.value() == 82090d2d1e8SJiaqing Zhao boost::system::linux_error::bad_request_descriptor) 82190d2d1e8SJiaqing Zhao { 822*75b63a2cSJiaqing Zhao messages::resourceNotFound(asyncResp->res, name, id); 8235968caeeSMarri Devender Rao return; 8245968caeeSMarri Devender Rao } 82590d2d1e8SJiaqing Zhao messages::internalError(asyncResp->res); 82690d2d1e8SJiaqing Zhao return; 82790d2d1e8SJiaqing Zhao } 828*75b63a2cSJiaqing Zhao getCertificateProperties(asyncResp, objectPath, service, id, 829*75b63a2cSJiaqing Zhao certURI, name); 8305968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" 8315968caeeSMarri Devender Rao << certFile->getCertFilePath(); 8325968caeeSMarri Devender Rao }, 8335968caeeSMarri Devender Rao service, objectPath, certs::certReplaceIntf, "Replace", 8345968caeeSMarri Devender Rao certFile->getCertFilePath()); 8357e860f15SJohn Edward Broadbent }); 8367e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionsReplaceCertificate 8375968caeeSMarri Devender Rao 8385968caeeSMarri Devender Rao /** 8395968caeeSMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 8405968caeeSMarri Devender Rao * of a component, account or service. 8415968caeeSMarri Devender Rao */ 8425968caeeSMarri Devender Rao 8437e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificate(App& app) 8445968caeeSMarri Devender Rao { 8457e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 8467e860f15SJohn Edward Broadbent app, 8477e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/<str>/") 848ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 8497e860f15SJohn Edward Broadbent .methods( 8507e860f15SJohn Edward Broadbent boost::beast::http::verb:: 85145ca1b86SEd Tanous get)([&app](const crow::Request& req, 8527e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 853717b9802SJiaqing Zhao const std::string& id) -> void { 8543ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 85545ca1b86SEd Tanous { 85645ca1b86SEd Tanous return; 85745ca1b86SEd Tanous } 8585968caeeSMarri Devender Rao 859717b9802SJiaqing Zhao BMCWEB_LOG_DEBUG << "HTTPS Certificate ID=" << id; 8605968caeeSMarri Devender Rao std::string certURL = 8615968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" + 862717b9802SJiaqing Zhao id; 863717b9802SJiaqing Zhao std::string objPath = 864717b9802SJiaqing Zhao sdbusplus::message::object_path(certs::httpsObjectPath) / id; 865717b9802SJiaqing Zhao getCertificateProperties(asyncResp, objPath, 866717b9802SJiaqing Zhao certs::httpsServiceName, id, certURL, 867717b9802SJiaqing Zhao "HTTPS Certificate"); 8687e860f15SJohn Edward Broadbent }); 8695968caeeSMarri Devender Rao } 8705968caeeSMarri Devender Rao 8715968caeeSMarri Devender Rao /** 8725968caeeSMarri Devender Rao * Collection of HTTPS certificates 8735968caeeSMarri Devender Rao */ 8747e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificateCollection(App& app) 8755968caeeSMarri Devender Rao { 8767e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 8775968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/") 878ed398213SEd Tanous .privileges(redfish::privileges::getCertificateCollection) 879002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 880002d39b4SEd Tanous [&app](const crow::Request& req, 881002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 8823ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 88345ca1b86SEd Tanous { 88445ca1b86SEd Tanous return; 88545ca1b86SEd Tanous } 8861476687dSEd Tanous 8871476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 8881476687dSEd Tanous "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"; 8891476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 8901476687dSEd Tanous "#CertificateCollection.CertificateCollection"; 8911476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "HTTPS Certificates Collection"; 8921476687dSEd Tanous asyncResp->res.jsonValue["Description"] = 8931476687dSEd Tanous "A Collection of HTTPS certificate instances"; 8948d1b46d7Szhanghch05 895d3f92ce7SJiaqing Zhao getCertificateList(asyncResp, certs::httpsObjectPath, 896d3f92ce7SJiaqing Zhao "/Members"_json_pointer, 897d3f92ce7SJiaqing Zhao "/Members@odata.count"_json_pointer); 8987e860f15SJohn Edward Broadbent }); 8995968caeeSMarri Devender Rao 9007e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 9017e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/") 902ed398213SEd Tanous .privileges(redfish::privileges::postCertificateCollection) 903002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 904002d39b4SEd Tanous [&app](const crow::Request& req, 9057e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 9063ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 90745ca1b86SEd Tanous { 90845ca1b86SEd Tanous return; 90945ca1b86SEd Tanous } 9105968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost"; 9118d1b46d7Szhanghch05 9121476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "HTTPS Certificate"; 9131476687dSEd Tanous asyncResp->res.jsonValue["Description"] = "HTTPS Certificate"; 9145968caeeSMarri Devender Rao 915002d39b4SEd Tanous std::string certFileBody = getCertificateFromReqBody(asyncResp, req); 91658eb238fSKowalski, Kamil 91758eb238fSKowalski, Kamil if (certFileBody.empty()) 91858eb238fSKowalski, Kamil { 9190fda0f12SGeorge Liu BMCWEB_LOG_ERROR << "Cannot get certificate from request body."; 920a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 92158eb238fSKowalski, Kamil return; 92258eb238fSKowalski, Kamil } 92358eb238fSKowalski, Kamil 9245968caeeSMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 92558eb238fSKowalski, Kamil std::make_shared<CertificateFile>(certFileBody); 9265968caeeSMarri Devender Rao 9275968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 928656ec7e3SZbigniew Kurzynski [asyncResp, certFile](const boost::system::error_code ec, 929656ec7e3SZbigniew Kurzynski const std::string& objectPath) { 9305968caeeSMarri Devender Rao if (ec) 9315968caeeSMarri Devender Rao { 9325968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 9335968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 9345968caeeSMarri Devender Rao return; 9355968caeeSMarri Devender Rao } 936717b9802SJiaqing Zhao 937717b9802SJiaqing Zhao sdbusplus::message::object_path path(objectPath); 938717b9802SJiaqing Zhao std::string certId = path.filename(); 9395968caeeSMarri Devender Rao std::string certURL = 9400fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" + 941717b9802SJiaqing Zhao certId; 942717b9802SJiaqing Zhao getCertificateProperties(asyncResp, objectPath, 943717b9802SJiaqing Zhao certs::httpsServiceName, certId, certURL, 944717b9802SJiaqing Zhao "HTTPS Certificate"); 9455968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" 9465968caeeSMarri Devender Rao << certFile->getCertFilePath(); 9475968caeeSMarri Devender Rao }, 94837cce918SMarri Devender Rao certs::httpsServiceName, certs::httpsObjectPath, 9490fda0f12SGeorge Liu certs::certInstallIntf, "Install", certFile->getCertFilePath()); 9507e860f15SJohn Edward Broadbent }); 9517e860f15SJohn Edward Broadbent } // requestRoutesHTTPSCertificateCollection 9525968caeeSMarri Devender Rao 9535968caeeSMarri Devender Rao /** 9547e860f15SJohn Edward Broadbent * The certificate location schema defines a resource that an administrator 9557e860f15SJohn Edward Broadbent * can use in order to locate all certificates installed on a given service. 9567e860f15SJohn Edward Broadbent */ 9577e860f15SJohn Edward Broadbent inline void requestRoutesCertificateLocations(App& app) 9587e860f15SJohn Edward Broadbent { 9597e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/") 960ed398213SEd Tanous .privileges(redfish::privileges::getCertificateLocations) 961002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 962002d39b4SEd Tanous [&app](const crow::Request& req, 963002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 9643ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 96545ca1b86SEd Tanous { 96645ca1b86SEd Tanous return; 96745ca1b86SEd Tanous } 9681476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 9691476687dSEd Tanous "/redfish/v1/CertificateService/CertificateLocations"; 9701476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 9711476687dSEd Tanous "#CertificateLocations.v1_0_0.CertificateLocations"; 9721476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "Certificate Locations"; 9731476687dSEd Tanous asyncResp->res.jsonValue["Id"] = "CertificateLocations"; 9741476687dSEd Tanous asyncResp->res.jsonValue["Description"] = 9757e860f15SJohn Edward Broadbent "Defines a resource that an administrator can use in order to " 9761476687dSEd Tanous "locate all certificates installed on a given service"; 9777e860f15SJohn Edward Broadbent 978d3f92ce7SJiaqing Zhao getCertificateList(asyncResp, certs::baseObjectPath, 979d3f92ce7SJiaqing Zhao "/Links/Certificates"_json_pointer, 980d3f92ce7SJiaqing Zhao "/Links/Certificates@odata.count"_json_pointer); 9817e860f15SJohn Edward Broadbent }); 9827e860f15SJohn Edward Broadbent } 9837e860f15SJohn Edward Broadbent // requestRoutesCertificateLocations 98437cce918SMarri Devender Rao 98537cce918SMarri Devender Rao /** 98637cce918SMarri Devender Rao * Collection of LDAP certificates 98737cce918SMarri Devender Rao */ 9887e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificateCollection(App& app) 98937cce918SMarri Devender Rao { 9907e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/") 991ed398213SEd Tanous .privileges(redfish::privileges::getCertificateCollection) 992002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 993002d39b4SEd Tanous [&app](const crow::Request& req, 994002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 9953ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 99645ca1b86SEd Tanous { 99745ca1b86SEd Tanous return; 99845ca1b86SEd Tanous } 9991476687dSEd Tanous 10001476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 10011476687dSEd Tanous "/redfish/v1/AccountService/LDAP/Certificates"; 10021476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 10031476687dSEd Tanous "#CertificateCollection.CertificateCollection"; 10041476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "LDAP Certificates Collection"; 10051476687dSEd Tanous asyncResp->res.jsonValue["Description"] = 10061476687dSEd Tanous "A Collection of LDAP certificate instances"; 10078d1b46d7Szhanghch05 1008d3f92ce7SJiaqing Zhao getCertificateList(asyncResp, certs::ldapObjectPath, 1009d3f92ce7SJiaqing Zhao "/Members"_json_pointer, 1010d3f92ce7SJiaqing Zhao "/Members@odata.count"_json_pointer); 10117e860f15SJohn Edward Broadbent }); 101237cce918SMarri Devender Rao 10137e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/") 1014ed398213SEd Tanous .privileges(redfish::privileges::postCertificateCollection) 10157e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 101645ca1b86SEd Tanous [&app](const crow::Request& req, 10177e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 10183ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 101945ca1b86SEd Tanous { 102045ca1b86SEd Tanous return; 102145ca1b86SEd Tanous } 1022002d39b4SEd Tanous std::string certFileBody = getCertificateFromReqBody(asyncResp, req); 102358eb238fSKowalski, Kamil 102458eb238fSKowalski, Kamil if (certFileBody.empty()) 102558eb238fSKowalski, Kamil { 1026002d39b4SEd Tanous BMCWEB_LOG_ERROR << "Cannot get certificate from request body."; 1027a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 102858eb238fSKowalski, Kamil return; 102958eb238fSKowalski, Kamil } 103058eb238fSKowalski, Kamil 103158eb238fSKowalski, Kamil std::shared_ptr<CertificateFile> certFile = 103258eb238fSKowalski, Kamil std::make_shared<CertificateFile>(certFileBody); 103358eb238fSKowalski, Kamil 103437cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 1035656ec7e3SZbigniew Kurzynski [asyncResp, certFile](const boost::system::error_code ec, 1036656ec7e3SZbigniew Kurzynski const std::string& objectPath) { 103737cce918SMarri Devender Rao if (ec) 103837cce918SMarri Devender Rao { 103937cce918SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 104037cce918SMarri Devender Rao messages::internalError(asyncResp->res); 104137cce918SMarri Devender Rao return; 104237cce918SMarri Devender Rao } 1043717b9802SJiaqing Zhao 1044717b9802SJiaqing Zhao sdbusplus::message::object_path path(objectPath); 1045717b9802SJiaqing Zhao std::string certId = path.filename(); 104637cce918SMarri Devender Rao std::string certURL = 1047717b9802SJiaqing Zhao "/redfish/v1/AccountService/LDAP/Certificates/" + certId; 1048717b9802SJiaqing Zhao getCertificateProperties(asyncResp, objectPath, 1049717b9802SJiaqing Zhao certs::ldapServiceName, certId, certURL, 1050717b9802SJiaqing Zhao "LDAP Certificate"); 105137cce918SMarri Devender Rao BMCWEB_LOG_DEBUG << "LDAP certificate install file=" 105237cce918SMarri Devender Rao << certFile->getCertFilePath(); 105337cce918SMarri Devender Rao }, 105437cce918SMarri Devender Rao certs::ldapServiceName, certs::ldapObjectPath, 1055002d39b4SEd Tanous certs::certInstallIntf, "Install", certFile->getCertFilePath()); 10567e860f15SJohn Edward Broadbent }); 10577e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificateCollection 105837cce918SMarri Devender Rao 105937cce918SMarri Devender Rao /** 106037cce918SMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 106137cce918SMarri Devender Rao * of a component, account or service. 106237cce918SMarri Devender Rao */ 10637e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificate(App& app) 106437cce918SMarri Devender Rao { 10657e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/") 1066ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 10677e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 106845ca1b86SEd Tanous [&app](const crow::Request& req, 10697e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1070717b9802SJiaqing Zhao const std::string& id) { 10713ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 107245ca1b86SEd Tanous { 107345ca1b86SEd Tanous return; 107445ca1b86SEd Tanous } 1075717b9802SJiaqing Zhao 1076717b9802SJiaqing Zhao BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" << id; 1077717b9802SJiaqing Zhao std::string certURL = 1078717b9802SJiaqing Zhao "/redfish/v1/AccountService/LDAP/Certificates/" + id; 1079717b9802SJiaqing Zhao std::string objPath = 1080717b9802SJiaqing Zhao sdbusplus::message::object_path(certs::ldapObjectPath) / id; 1081717b9802SJiaqing Zhao getCertificateProperties(asyncResp, objPath, certs::ldapServiceName, id, 1082717b9802SJiaqing Zhao certURL, "LDAP Certificate"); 10837e860f15SJohn Edward Broadbent }); 10847e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificate 1085cfcd5f6bSMarri Devender Rao /** 1086cfcd5f6bSMarri Devender Rao * Collection of TrustStoreCertificate certificates 1087cfcd5f6bSMarri Devender Rao */ 10887e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificateCollection(App& app) 1089cfcd5f6bSMarri Devender Rao { 10907e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/") 1091ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 1092002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1093002d39b4SEd Tanous [&app](const crow::Request& req, 1094002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 10953ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 109645ca1b86SEd Tanous { 109745ca1b86SEd Tanous return; 109845ca1b86SEd Tanous } 10991476687dSEd Tanous 11001476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 11011476687dSEd Tanous "/redfish/v1/Managers/bmc/Truststore/Certificates/"; 11021476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 11031476687dSEd Tanous "#CertificateCollection.CertificateCollection"; 1104002d39b4SEd Tanous asyncResp->res.jsonValue["Name"] = "TrustStore Certificates Collection"; 11051476687dSEd Tanous asyncResp->res.jsonValue["Description"] = 11061476687dSEd Tanous "A Collection of TrustStore certificate instances"; 11078d1b46d7Szhanghch05 1108d3f92ce7SJiaqing Zhao getCertificateList(asyncResp, certs::authorityObjectPath, 1109d3f92ce7SJiaqing Zhao "/Members"_json_pointer, 1110d3f92ce7SJiaqing Zhao "/Members@odata.count"_json_pointer); 11117e860f15SJohn Edward Broadbent }); 1112cfcd5f6bSMarri Devender Rao 11137e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/") 1114ed398213SEd Tanous .privileges(redfish::privileges::postCertificateCollection) 1115002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 1116002d39b4SEd Tanous [&app](const crow::Request& req, 11177e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 11183ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 111945ca1b86SEd Tanous { 112045ca1b86SEd Tanous return; 112145ca1b86SEd Tanous } 1122002d39b4SEd Tanous std::string certFileBody = getCertificateFromReqBody(asyncResp, req); 1123a08752f5SZbigniew Kurzynski 1124a08752f5SZbigniew Kurzynski if (certFileBody.empty()) 1125a08752f5SZbigniew Kurzynski { 11260fda0f12SGeorge Liu BMCWEB_LOG_ERROR << "Cannot get certificate from request body."; 1127a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 1128a08752f5SZbigniew Kurzynski return; 1129a08752f5SZbigniew Kurzynski } 1130a08752f5SZbigniew Kurzynski 1131a08752f5SZbigniew Kurzynski std::shared_ptr<CertificateFile> certFile = 1132a08752f5SZbigniew Kurzynski std::make_shared<CertificateFile>(certFileBody); 1133cfcd5f6bSMarri Devender Rao crow::connections::systemBus->async_method_call( 1134656ec7e3SZbigniew Kurzynski [asyncResp, certFile](const boost::system::error_code ec, 1135656ec7e3SZbigniew Kurzynski const std::string& objectPath) { 1136cfcd5f6bSMarri Devender Rao if (ec) 1137cfcd5f6bSMarri Devender Rao { 1138cfcd5f6bSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 1139cfcd5f6bSMarri Devender Rao messages::internalError(asyncResp->res); 1140cfcd5f6bSMarri Devender Rao return; 1141cfcd5f6bSMarri Devender Rao } 1142656ec7e3SZbigniew Kurzynski 1143717b9802SJiaqing Zhao sdbusplus::message::object_path path(objectPath); 1144717b9802SJiaqing Zhao std::string certId = path.filename(); 1145717b9802SJiaqing Zhao std::string certURL = 1146717b9802SJiaqing Zhao "/redfish/v1/Managers/bmc/Truststore/Certificates/" + certId; 1147717b9802SJiaqing Zhao getCertificateProperties(asyncResp, objectPath, 1148717b9802SJiaqing Zhao certs::authorityServiceName, certId, 1149717b9802SJiaqing Zhao certURL, "TrustStore Certificate"); 11500fda0f12SGeorge Liu BMCWEB_LOG_DEBUG << "TrustStore certificate install file=" 1151cfcd5f6bSMarri Devender Rao << certFile->getCertFilePath(); 1152cfcd5f6bSMarri Devender Rao }, 1153cfcd5f6bSMarri Devender Rao certs::authorityServiceName, certs::authorityObjectPath, 11540fda0f12SGeorge Liu certs::certInstallIntf, "Install", certFile->getCertFilePath()); 11557e860f15SJohn Edward Broadbent }); 11567e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificateCollection 1157cfcd5f6bSMarri Devender Rao 1158cfcd5f6bSMarri Devender Rao /** 1159cfcd5f6bSMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 1160cfcd5f6bSMarri Devender Rao * of a component, account or service. 1161cfcd5f6bSMarri Devender Rao */ 11627e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificate(App& app) 1163cfcd5f6bSMarri Devender Rao { 11647e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/") 1165ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 11667e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 116745ca1b86SEd Tanous [&app](const crow::Request& req, 11687e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1169717b9802SJiaqing Zhao const std::string& id) { 11703ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 117145ca1b86SEd Tanous { 117245ca1b86SEd Tanous return; 117345ca1b86SEd Tanous } 1174717b9802SJiaqing Zhao 1175717b9802SJiaqing Zhao BMCWEB_LOG_DEBUG << "Truststore Certificate ID=" << id; 1176cfcd5f6bSMarri Devender Rao std::string certURL = 1177717b9802SJiaqing Zhao "/redfish/v1/Managers/bmc/Truststore/Certificates/" + id; 1178717b9802SJiaqing Zhao std::string objPath = 1179717b9802SJiaqing Zhao sdbusplus::message::object_path(certs::authorityObjectPath) / id; 1180717b9802SJiaqing Zhao getCertificateProperties(asyncResp, objPath, 1181717b9802SJiaqing Zhao certs::authorityServiceName, id, certURL, 1182717b9802SJiaqing Zhao "TrustStore Certificate"); 11837e860f15SJohn Edward Broadbent }); 118407a60299SZbigniew Kurzynski 11857e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/") 1186ed398213SEd Tanous .privileges(redfish::privileges::deleteCertificate) 11877e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::delete_)( 118845ca1b86SEd Tanous [&app](const crow::Request& req, 11897e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1190717b9802SJiaqing Zhao const std::string& id) { 11913ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 119245ca1b86SEd Tanous { 119345ca1b86SEd Tanous return; 119445ca1b86SEd Tanous } 119507a60299SZbigniew Kurzynski 1196717b9802SJiaqing Zhao BMCWEB_LOG_DEBUG << "Delete TrustStore Certificate ID=" << id; 1197717b9802SJiaqing Zhao std::string objPath = 1198717b9802SJiaqing Zhao sdbusplus::message::object_path(certs::authorityObjectPath) / id; 119907a60299SZbigniew Kurzynski 120007a60299SZbigniew Kurzynski crow::connections::systemBus->async_method_call( 120107a60299SZbigniew Kurzynski [asyncResp, id](const boost::system::error_code ec) { 120207a60299SZbigniew Kurzynski if (ec) 120307a60299SZbigniew Kurzynski { 120407a60299SZbigniew Kurzynski messages::resourceNotFound(asyncResp->res, 1205717b9802SJiaqing Zhao "TrustStore Certificate", id); 120607a60299SZbigniew Kurzynski return; 120707a60299SZbigniew Kurzynski } 120807a60299SZbigniew Kurzynski BMCWEB_LOG_INFO << "Certificate deleted"; 1209002d39b4SEd Tanous asyncResp->res.result(boost::beast::http::status::no_content); 121007a60299SZbigniew Kurzynski }, 1211717b9802SJiaqing Zhao certs::authorityServiceName, objPath, certs::objDeleteIntf, 121207a60299SZbigniew Kurzynski "Delete"); 12137e860f15SJohn Edward Broadbent }); 12147e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificate 12155968caeeSMarri Devender Rao } // namespace redfish 1216