15968caeeSMarri Devender Rao #pragma once 25968caeeSMarri Devender Rao 39b12d1f9SKrzysztof Grobelny #include "utils/dbus_utils.hpp" 49b12d1f9SKrzysztof Grobelny 57e860f15SJohn Edward Broadbent #include <app.hpp> 6d9f6c621SEd Tanous #include <async_resp.hpp> 790d2d1e8SJiaqing Zhao #include <boost/system/linux_error.hpp> 8168e20c1SEd Tanous #include <dbus_utility.hpp> 9d9f6c621SEd Tanous #include <http_response.hpp> 1045ca1b86SEd Tanous #include <query.hpp> 11ed398213SEd Tanous #include <registries/privilege_registry.hpp> 129b12d1f9SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp> 139b12d1f9SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 141214b7e7SGunnar Mills 155968caeeSMarri Devender Rao namespace redfish 165968caeeSMarri Devender Rao { 175968caeeSMarri Devender Rao namespace certs 185968caeeSMarri Devender Rao { 195968caeeSMarri Devender Rao constexpr char const* certInstallIntf = "xyz.openbmc_project.Certs.Install"; 205968caeeSMarri Devender Rao constexpr char const* certReplaceIntf = "xyz.openbmc_project.Certs.Replace"; 2107a60299SZbigniew Kurzynski constexpr char const* objDeleteIntf = "xyz.openbmc_project.Object.Delete"; 225968caeeSMarri Devender Rao constexpr char const* certPropIntf = "xyz.openbmc_project.Certs.Certificate"; 235968caeeSMarri Devender Rao constexpr char const* dbusPropIntf = "org.freedesktop.DBus.Properties"; 245968caeeSMarri Devender Rao constexpr char const* dbusObjManagerIntf = "org.freedesktop.DBus.ObjectManager"; 2537cce918SMarri Devender Rao constexpr char const* httpsServiceName = 2637cce918SMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Server.Https"; 2737cce918SMarri Devender Rao constexpr char const* ldapServiceName = 2837cce918SMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Client.Ldap"; 29cfcd5f6bSMarri Devender Rao constexpr char const* authorityServiceName = 30cfcd5f6bSMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Authority.Ldap"; 31c6a8dfb1SJiaqing Zhao constexpr char const* baseObjectPath = "/xyz/openbmc_project/certs"; 32c6a8dfb1SJiaqing Zhao constexpr char const* httpsObjectPath = 33c6a8dfb1SJiaqing Zhao "/xyz/openbmc_project/certs/server/https"; 34c6a8dfb1SJiaqing Zhao constexpr char const* ldapObjectPath = "/xyz/openbmc_project/certs/client/ldap"; 35cfcd5f6bSMarri Devender Rao constexpr char const* authorityObjectPath = 36cfcd5f6bSMarri Devender Rao "/xyz/openbmc_project/certs/authority/ldap"; 375968caeeSMarri Devender Rao } // namespace certs 385968caeeSMarri Devender Rao 395968caeeSMarri Devender Rao /** 405968caeeSMarri Devender Rao * The Certificate schema defines a Certificate Service which represents the 415968caeeSMarri Devender Rao * actions available to manage certificates and links to where certificates 425968caeeSMarri Devender Rao * are installed. 435968caeeSMarri Devender Rao */ 447e860f15SJohn Edward Broadbent 455968caeeSMarri Devender Rao // TODO: Issue#61 No entries are available for Certificate 464e0453b1SGunnar Mills // service at https://www.dmtf.org/standards/redfish 475968caeeSMarri Devender Rao // "redfish standard registries". Need to modify after DMTF 485968caeeSMarri Devender Rao // publish Privilege details for certificate service 495968caeeSMarri Devender Rao 507e860f15SJohn Edward Broadbent inline void requestRoutesCertificateService(App& app) 515968caeeSMarri Devender Rao { 527e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/") 53ed398213SEd Tanous .privileges(redfish::privileges::getCertificateService) 54002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 55002d39b4SEd Tanous [&app](const crow::Request& req, 56002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 573ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 5845ca1b86SEd Tanous { 5945ca1b86SEd Tanous return; 6045ca1b86SEd Tanous } 611476687dSEd Tanous 621476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 631476687dSEd Tanous "#CertificateService.v1_0_0.CertificateService"; 641476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 651476687dSEd Tanous "/redfish/v1/CertificateService"; 661476687dSEd Tanous asyncResp->res.jsonValue["Id"] = "CertificateService"; 671476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "Certificate Service"; 681476687dSEd Tanous asyncResp->res.jsonValue["Description"] = 691476687dSEd Tanous "Actions available to manage certificates"; 7072048780SAbhishek Patel // /redfish/v1/CertificateService/CertificateLocations is something 7172048780SAbhishek Patel // only ConfigureManager can access then only display when the user 7272048780SAbhishek Patel // has permissions ConfigureManager 7372048780SAbhishek Patel Privileges effectiveUserPrivileges = 7472048780SAbhishek Patel redfish::getUserPrivileges(req.userRole); 7572048780SAbhishek Patel if (isOperationAllowedWithPrivileges({{"ConfigureManager"}}, 7672048780SAbhishek Patel effectiveUserPrivileges)) 7772048780SAbhishek Patel { 781476687dSEd Tanous asyncResp->res.jsonValue["CertificateLocations"]["@odata.id"] = 791476687dSEd Tanous "/redfish/v1/CertificateService/CertificateLocations"; 8072048780SAbhishek Patel } 810fda0f12SGeorge Liu asyncResp->res 82002d39b4SEd Tanous .jsonValue["Actions"]["#CertificateService.ReplaceCertificate"] = { 830fda0f12SGeorge Liu {"target", 840fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate"}, 855968caeeSMarri Devender Rao {"CertificateType@Redfish.AllowableValues", {"PEM"}}}; 867e860f15SJohn Edward Broadbent asyncResp->res 877e860f15SJohn Edward Broadbent .jsonValue["Actions"]["#CertificateService.GenerateCSR"] = { 880fda0f12SGeorge Liu {"target", 890fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR"}}; 907e860f15SJohn Edward Broadbent }); 917e860f15SJohn Edward Broadbent } // requestRoutesCertificateService 9237cce918SMarri Devender Rao 938d1b46d7Szhanghch05 inline std::string getCertificateFromReqBody( 948d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 9558eb238fSKowalski, Kamil const crow::Request& req) 9658eb238fSKowalski, Kamil { 9758eb238fSKowalski, Kamil nlohmann::json reqJson = nlohmann::json::parse(req.body, nullptr, false); 9858eb238fSKowalski, Kamil 9958eb238fSKowalski, Kamil if (reqJson.is_discarded()) 10058eb238fSKowalski, Kamil { 10158eb238fSKowalski, Kamil // We did not receive JSON request, proceed as it is RAW data 10258eb238fSKowalski, Kamil return req.body; 10358eb238fSKowalski, Kamil } 10458eb238fSKowalski, Kamil 10558eb238fSKowalski, Kamil std::string certificate; 10658eb238fSKowalski, Kamil std::optional<std::string> certificateType = "PEM"; 10758eb238fSKowalski, Kamil 10815ed6780SWilly Tu if (!json_util::readJsonPatch(req, asyncResp->res, "CertificateString", 10915ed6780SWilly Tu certificate, "CertificateType", 11015ed6780SWilly Tu certificateType)) 11158eb238fSKowalski, Kamil { 11258eb238fSKowalski, Kamil BMCWEB_LOG_ERROR << "Required parameters are missing"; 11358eb238fSKowalski, Kamil messages::internalError(asyncResp->res); 114abb93cddSEd Tanous return {}; 11558eb238fSKowalski, Kamil } 11658eb238fSKowalski, Kamil 11758eb238fSKowalski, Kamil if (*certificateType != "PEM") 11858eb238fSKowalski, Kamil { 11958eb238fSKowalski, Kamil messages::propertyValueNotInList(asyncResp->res, *certificateType, 12058eb238fSKowalski, Kamil "CertificateType"); 121abb93cddSEd Tanous return {}; 12258eb238fSKowalski, Kamil } 12358eb238fSKowalski, Kamil 12458eb238fSKowalski, Kamil return certificate; 12558eb238fSKowalski, Kamil } 12658eb238fSKowalski, Kamil 1275968caeeSMarri Devender Rao /** 1285968caeeSMarri Devender Rao * Class to create a temporary certificate file for uploading to system 1295968caeeSMarri Devender Rao */ 1305968caeeSMarri Devender Rao class CertificateFile 1315968caeeSMarri Devender Rao { 1325968caeeSMarri Devender Rao public: 1335968caeeSMarri Devender Rao CertificateFile() = delete; 1345968caeeSMarri Devender Rao CertificateFile(const CertificateFile&) = delete; 1355968caeeSMarri Devender Rao CertificateFile& operator=(const CertificateFile&) = delete; 1365968caeeSMarri Devender Rao CertificateFile(CertificateFile&&) = delete; 1375968caeeSMarri Devender Rao CertificateFile& operator=(CertificateFile&&) = delete; 1384e23a444SEd Tanous explicit CertificateFile(const std::string& certString) 1395968caeeSMarri Devender Rao { 14072d52d25SEd Tanous std::array<char, 18> dirTemplate = {'/', 't', 'm', 'p', '/', 'C', 1415207438cSEd Tanous 'e', 'r', 't', 's', '.', 'X', 1425207438cSEd Tanous 'X', 'X', 'X', 'X', 'X', '\0'}; 1435207438cSEd Tanous char* tempDirectory = mkdtemp(dirTemplate.data()); 144e662eae8SEd Tanous if (tempDirectory != nullptr) 1455968caeeSMarri Devender Rao { 1465968caeeSMarri Devender Rao certDirectory = tempDirectory; 1475968caeeSMarri Devender Rao certificateFile = certDirectory / "cert.pem"; 1485968caeeSMarri Devender Rao std::ofstream out(certificateFile, std::ofstream::out | 1495968caeeSMarri Devender Rao std::ofstream::binary | 1505968caeeSMarri Devender Rao std::ofstream::trunc); 1515968caeeSMarri Devender Rao out << certString; 1525968caeeSMarri Devender Rao out.close(); 1538cc8edecSEd Tanous BMCWEB_LOG_DEBUG << "Creating certificate file" 1548cc8edecSEd Tanous << certificateFile.string(); 1555968caeeSMarri Devender Rao } 1565968caeeSMarri Devender Rao } 1575968caeeSMarri Devender Rao ~CertificateFile() 1585968caeeSMarri Devender Rao { 1595968caeeSMarri Devender Rao if (std::filesystem::exists(certDirectory)) 1605968caeeSMarri Devender Rao { 1618cc8edecSEd Tanous BMCWEB_LOG_DEBUG << "Removing certificate file" 1628cc8edecSEd Tanous << certificateFile.string(); 16323a21a1cSEd Tanous std::error_code ec; 16423a21a1cSEd Tanous std::filesystem::remove_all(certDirectory, ec); 16523a21a1cSEd Tanous if (ec) 1665968caeeSMarri Devender Rao { 1675968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Failed to remove temp directory" 1688cc8edecSEd Tanous << certDirectory.string(); 1695968caeeSMarri Devender Rao } 1705968caeeSMarri Devender Rao } 1715968caeeSMarri Devender Rao } 1725968caeeSMarri Devender Rao std::string getCertFilePath() 1735968caeeSMarri Devender Rao { 1745968caeeSMarri Devender Rao return certificateFile; 1755968caeeSMarri Devender Rao } 1765968caeeSMarri Devender Rao 1775968caeeSMarri Devender Rao private: 1785968caeeSMarri Devender Rao std::filesystem::path certificateFile; 1795968caeeSMarri Devender Rao std::filesystem::path certDirectory; 1805968caeeSMarri Devender Rao }; 1815968caeeSMarri Devender Rao 18259d494eeSPatrick Williams static std::unique_ptr<sdbusplus::bus::match_t> csrMatcher; 18330215816SMarri Devender Rao /** 18430215816SMarri Devender Rao * @brief Read data from CSR D-bus object and set to response 18530215816SMarri Devender Rao * 18630215816SMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 18730215816SMarri Devender Rao * @param[in] certURI Link to certifiate collection URI 18830215816SMarri Devender Rao * @param[in] service D-Bus service name 18930215816SMarri Devender Rao * @param[in] certObjPath certificate D-Bus object path 19030215816SMarri Devender Rao * @param[in] csrObjPath CSR D-Bus object path 19130215816SMarri Devender Rao * @return None 19230215816SMarri Devender Rao */ 1938d1b46d7Szhanghch05 static void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 19430215816SMarri Devender Rao const std::string& certURI, const std::string& service, 19530215816SMarri Devender Rao const std::string& certObjPath, 19630215816SMarri Devender Rao const std::string& csrObjPath) 19730215816SMarri Devender Rao { 19830215816SMarri Devender Rao BMCWEB_LOG_DEBUG << "getCSR CertObjectPath" << certObjPath 19930215816SMarri Devender Rao << " CSRObjectPath=" << csrObjPath 20030215816SMarri Devender Rao << " service=" << service; 20130215816SMarri Devender Rao crow::connections::systemBus->async_method_call( 20230215816SMarri Devender Rao [asyncResp, certURI](const boost::system::error_code ec, 20330215816SMarri Devender Rao const std::string& csr) { 20430215816SMarri Devender Rao if (ec) 20530215816SMarri Devender Rao { 20630215816SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 20730215816SMarri Devender Rao messages::internalError(asyncResp->res); 20830215816SMarri Devender Rao return; 20930215816SMarri Devender Rao } 21030215816SMarri Devender Rao if (csr.empty()) 21130215816SMarri Devender Rao { 21230215816SMarri Devender Rao BMCWEB_LOG_ERROR << "CSR read is empty"; 21330215816SMarri Devender Rao messages::internalError(asyncResp->res); 21430215816SMarri Devender Rao return; 21530215816SMarri Devender Rao } 21630215816SMarri Devender Rao asyncResp->res.jsonValue["CSRString"] = csr; 2171476687dSEd Tanous asyncResp->res.jsonValue["CertificateCollection"]["@odata.id"] = 2181476687dSEd Tanous certURI; 21930215816SMarri Devender Rao }, 22030215816SMarri Devender Rao service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR"); 22130215816SMarri Devender Rao } 22230215816SMarri Devender Rao 22330215816SMarri Devender Rao /** 22430215816SMarri Devender Rao * Action to Generate CSR 22530215816SMarri Devender Rao */ 2267e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionGenerateCSR(App& app) 22730215816SMarri Devender Rao { 2280fda0f12SGeorge Liu BMCWEB_ROUTE( 2290fda0f12SGeorge Liu app, 2300fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR/") 2315344ab8eSAbhishek Patel .privileges(redfish::privileges::postCertificateService) 232002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 233002d39b4SEd Tanous [&app](const crow::Request& req, 2347e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 2353ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 23645ca1b86SEd Tanous { 23745ca1b86SEd Tanous return; 23845ca1b86SEd Tanous } 2392c70f800SEd Tanous static const int rsaKeyBitLength = 2048; 2408d1b46d7Szhanghch05 24130215816SMarri Devender Rao // Required parameters 24230215816SMarri Devender Rao std::string city; 24330215816SMarri Devender Rao std::string commonName; 24430215816SMarri Devender Rao std::string country; 24530215816SMarri Devender Rao std::string organization; 24630215816SMarri Devender Rao std::string organizationalUnit; 24730215816SMarri Devender Rao std::string state; 24830215816SMarri Devender Rao nlohmann::json certificateCollection; 24930215816SMarri Devender Rao 25030215816SMarri Devender Rao // Optional parameters 25130215816SMarri Devender Rao std::optional<std::vector<std::string>> optAlternativeNames = 25230215816SMarri Devender Rao std::vector<std::string>(); 25330215816SMarri Devender Rao std::optional<std::string> optContactPerson = ""; 25430215816SMarri Devender Rao std::optional<std::string> optChallengePassword = ""; 25530215816SMarri Devender Rao std::optional<std::string> optEmail = ""; 25630215816SMarri Devender Rao std::optional<std::string> optGivenName = ""; 25730215816SMarri Devender Rao std::optional<std::string> optInitials = ""; 2582c70f800SEd Tanous std::optional<int64_t> optKeyBitLength = rsaKeyBitLength; 259aaf3206fSVernon Mauery std::optional<std::string> optKeyCurveId = "secp384r1"; 26030215816SMarri Devender Rao std::optional<std::string> optKeyPairAlgorithm = "EC"; 26130215816SMarri Devender Rao std::optional<std::vector<std::string>> optKeyUsage = 26230215816SMarri Devender Rao std::vector<std::string>(); 26330215816SMarri Devender Rao std::optional<std::string> optSurname = ""; 26430215816SMarri Devender Rao std::optional<std::string> optUnstructuredName = ""; 26515ed6780SWilly Tu if (!json_util::readJsonAction( 2660fda0f12SGeorge Liu req, asyncResp->res, "City", city, "CommonName", commonName, 2670fda0f12SGeorge Liu "ContactPerson", optContactPerson, "Country", country, 2680fda0f12SGeorge Liu "Organization", organization, "OrganizationalUnit", 2690fda0f12SGeorge Liu organizationalUnit, "State", state, "CertificateCollection", 270002d39b4SEd Tanous certificateCollection, "AlternativeNames", optAlternativeNames, 271002d39b4SEd Tanous "ChallengePassword", optChallengePassword, "Email", optEmail, 272002d39b4SEd Tanous "GivenName", optGivenName, "Initials", optInitials, 273002d39b4SEd Tanous "KeyBitLength", optKeyBitLength, "KeyCurveId", optKeyCurveId, 2740fda0f12SGeorge Liu "KeyPairAlgorithm", optKeyPairAlgorithm, "KeyUsage", 2750fda0f12SGeorge Liu optKeyUsage, "Surname", optSurname, "UnstructuredName", 2760fda0f12SGeorge Liu optUnstructuredName)) 27730215816SMarri Devender Rao { 27830215816SMarri Devender Rao return; 27930215816SMarri Devender Rao } 28030215816SMarri Devender Rao 28130215816SMarri Devender Rao // bmcweb has no way to store or decode a private key challenge 2827e860f15SJohn Edward Broadbent // password, which will likely cause bmcweb to crash on startup 2837e860f15SJohn Edward Broadbent // if this is not set on a post so not allowing the user to set 2847e860f15SJohn Edward Broadbent // value 28526f6976fSEd Tanous if (!optChallengePassword->empty()) 28630215816SMarri Devender Rao { 287002d39b4SEd Tanous messages::actionParameterNotSupported(asyncResp->res, "GenerateCSR", 288002d39b4SEd Tanous "ChallengePassword"); 28930215816SMarri Devender Rao return; 29030215816SMarri Devender Rao } 29130215816SMarri Devender Rao 29230215816SMarri Devender Rao std::string certURI; 293002d39b4SEd Tanous if (!redfish::json_util::readJson(certificateCollection, asyncResp->res, 294002d39b4SEd Tanous "@odata.id", certURI)) 29530215816SMarri Devender Rao { 29630215816SMarri Devender Rao return; 29730215816SMarri Devender Rao } 29830215816SMarri Devender Rao 29930215816SMarri Devender Rao std::string objectPath; 30030215816SMarri Devender Rao std::string service; 30111ba3979SEd Tanous if (certURI.starts_with( 3020fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) 30330215816SMarri Devender Rao { 30430215816SMarri Devender Rao objectPath = certs::httpsObjectPath; 30530215816SMarri Devender Rao service = certs::httpsServiceName; 30630215816SMarri Devender Rao } 30711ba3979SEd Tanous else if (certURI.starts_with( 30811ba3979SEd Tanous "/redfish/v1/AccountService/LDAP/Certificates")) 3093b7f0149SMarri Devender Rao { 3103b7f0149SMarri Devender Rao objectPath = certs::ldapObjectPath; 3113b7f0149SMarri Devender Rao service = certs::ldapServiceName; 3123b7f0149SMarri Devender Rao } 31330215816SMarri Devender Rao else 31430215816SMarri Devender Rao { 31530215816SMarri Devender Rao messages::actionParameterNotSupported( 31630215816SMarri Devender Rao asyncResp->res, "CertificateCollection", "GenerateCSR"); 31730215816SMarri Devender Rao return; 31830215816SMarri Devender Rao } 31930215816SMarri Devender Rao 32030215816SMarri Devender Rao // supporting only EC and RSA algorithm 3210fda0f12SGeorge Liu if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA") 32230215816SMarri Devender Rao { 32330215816SMarri Devender Rao messages::actionParameterNotSupported( 32430215816SMarri Devender Rao asyncResp->res, "KeyPairAlgorithm", "GenerateCSR"); 32530215816SMarri Devender Rao return; 32630215816SMarri Devender Rao } 32730215816SMarri Devender Rao 3287e860f15SJohn Edward Broadbent // supporting only 2048 key bit length for RSA algorithm due to 3297e860f15SJohn Edward Broadbent // time consumed in generating private key 33030215816SMarri Devender Rao if (*optKeyPairAlgorithm == "RSA" && 3312c70f800SEd Tanous *optKeyBitLength != rsaKeyBitLength) 33230215816SMarri Devender Rao { 333002d39b4SEd Tanous messages::propertyValueNotInList(asyncResp->res, 334002d39b4SEd Tanous std::to_string(*optKeyBitLength), 33530215816SMarri Devender Rao "KeyBitLength"); 33630215816SMarri Devender Rao return; 33730215816SMarri Devender Rao } 33830215816SMarri Devender Rao 33930215816SMarri Devender Rao // validate KeyUsage supporting only 1 type based on URL 34011ba3979SEd Tanous if (certURI.starts_with( 3410fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) 34230215816SMarri Devender Rao { 34326f6976fSEd Tanous if (optKeyUsage->empty()) 34430215816SMarri Devender Rao { 34530215816SMarri Devender Rao optKeyUsage->push_back("ServerAuthentication"); 34630215816SMarri Devender Rao } 34730215816SMarri Devender Rao else if (optKeyUsage->size() == 1) 34830215816SMarri Devender Rao { 34930215816SMarri Devender Rao if ((*optKeyUsage)[0] != "ServerAuthentication") 35030215816SMarri Devender Rao { 35130215816SMarri Devender Rao messages::propertyValueNotInList( 35230215816SMarri Devender Rao asyncResp->res, (*optKeyUsage)[0], "KeyUsage"); 35330215816SMarri Devender Rao return; 35430215816SMarri Devender Rao } 35530215816SMarri Devender Rao } 35630215816SMarri Devender Rao else 35730215816SMarri Devender Rao { 35830215816SMarri Devender Rao messages::actionParameterNotSupported( 35930215816SMarri Devender Rao asyncResp->res, "KeyUsage", "GenerateCSR"); 36030215816SMarri Devender Rao return; 36130215816SMarri Devender Rao } 36230215816SMarri Devender Rao } 36311ba3979SEd Tanous else if (certURI.starts_with( 36411ba3979SEd Tanous "/redfish/v1/AccountService/LDAP/Certificates")) 3653b7f0149SMarri Devender Rao { 36626f6976fSEd Tanous if (optKeyUsage->empty()) 3673b7f0149SMarri Devender Rao { 3683b7f0149SMarri Devender Rao optKeyUsage->push_back("ClientAuthentication"); 3693b7f0149SMarri Devender Rao } 3703b7f0149SMarri Devender Rao else if (optKeyUsage->size() == 1) 3713b7f0149SMarri Devender Rao { 3723b7f0149SMarri Devender Rao if ((*optKeyUsage)[0] != "ClientAuthentication") 3733b7f0149SMarri Devender Rao { 3743b7f0149SMarri Devender Rao messages::propertyValueNotInList( 3753b7f0149SMarri Devender Rao asyncResp->res, (*optKeyUsage)[0], "KeyUsage"); 3763b7f0149SMarri Devender Rao return; 3773b7f0149SMarri Devender Rao } 3783b7f0149SMarri Devender Rao } 3793b7f0149SMarri Devender Rao else 3803b7f0149SMarri Devender Rao { 3813b7f0149SMarri Devender Rao messages::actionParameterNotSupported( 3823b7f0149SMarri Devender Rao asyncResp->res, "KeyUsage", "GenerateCSR"); 3833b7f0149SMarri Devender Rao return; 3843b7f0149SMarri Devender Rao } 3853b7f0149SMarri Devender Rao } 38630215816SMarri Devender Rao 3877e860f15SJohn Edward Broadbent // Only allow one CSR matcher at a time so setting retry 3887e860f15SJohn Edward Broadbent // time-out and timer expiry to 10 seconds for now. 3892c70f800SEd Tanous static const int timeOut = 10; 39030215816SMarri Devender Rao if (csrMatcher) 39130215816SMarri Devender Rao { 392002d39b4SEd Tanous messages::serviceTemporarilyUnavailable(asyncResp->res, 393002d39b4SEd Tanous std::to_string(timeOut)); 39430215816SMarri Devender Rao return; 39530215816SMarri Devender Rao } 39630215816SMarri Devender Rao 39730215816SMarri Devender Rao // Make this static so it survives outside this method 39830215816SMarri Devender Rao static boost::asio::steady_timer timeout(*req.ioService); 3992c70f800SEd Tanous timeout.expires_after(std::chrono::seconds(timeOut)); 400002d39b4SEd Tanous timeout.async_wait([asyncResp](const boost::system::error_code& ec) { 40130215816SMarri Devender Rao csrMatcher = nullptr; 40230215816SMarri Devender Rao if (ec) 40330215816SMarri Devender Rao { 4047e860f15SJohn Edward Broadbent // operation_aborted is expected if timer is canceled 4057e860f15SJohn Edward Broadbent // before completion. 40630215816SMarri Devender Rao if (ec != boost::asio::error::operation_aborted) 40730215816SMarri Devender Rao { 40830215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Async_wait failed " << ec; 40930215816SMarri Devender Rao } 41030215816SMarri Devender Rao return; 41130215816SMarri Devender Rao } 41230215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR"; 41330215816SMarri Devender Rao messages::internalError(asyncResp->res); 41430215816SMarri Devender Rao }); 41530215816SMarri Devender Rao 41630215816SMarri Devender Rao // create a matcher to wait on CSR object 41730215816SMarri Devender Rao BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath; 4180fda0f12SGeorge Liu std::string match("type='signal'," 41930215816SMarri Devender Rao "interface='org.freedesktop.DBus.ObjectManager'," 42030215816SMarri Devender Rao "path='" + 42130215816SMarri Devender Rao objectPath + 42230215816SMarri Devender Rao "'," 42330215816SMarri Devender Rao "member='InterfacesAdded'"); 42459d494eeSPatrick Williams csrMatcher = std::make_unique<sdbusplus::bus::match_t>( 42530215816SMarri Devender Rao *crow::connections::systemBus, match, 42659d494eeSPatrick Williams [asyncResp, service, objectPath, certURI](sdbusplus::message_t& m) { 427271584abSEd Tanous timeout.cancel(); 42830215816SMarri Devender Rao if (m.is_method_error()) 42930215816SMarri Devender Rao { 43030215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Dbus method error!!!"; 43130215816SMarri Devender Rao messages::internalError(asyncResp->res); 43230215816SMarri Devender Rao return; 43330215816SMarri Devender Rao } 434b9d36b47SEd Tanous 435b9d36b47SEd Tanous dbus::utility::DBusInteracesMap interfacesProperties; 436b9d36b47SEd Tanous 43730215816SMarri Devender Rao sdbusplus::message::object_path csrObjectPath; 43830215816SMarri Devender Rao m.read(csrObjectPath, interfacesProperties); 4390fda0f12SGeorge Liu BMCWEB_LOG_DEBUG << "CSR object added" << csrObjectPath.str; 44002cad96eSEd Tanous for (const auto& interface : interfacesProperties) 44130215816SMarri Devender Rao { 4420fda0f12SGeorge Liu if (interface.first == "xyz.openbmc_project.Certs.CSR") 44330215816SMarri Devender Rao { 44430215816SMarri Devender Rao getCSR(asyncResp, certURI, service, objectPath, 44530215816SMarri Devender Rao csrObjectPath.str); 44630215816SMarri Devender Rao break; 44730215816SMarri Devender Rao } 44830215816SMarri Devender Rao } 44930215816SMarri Devender Rao }); 45030215816SMarri Devender Rao crow::connections::systemBus->async_method_call( 451914e2d5dSEd Tanous [asyncResp](const boost::system::error_code ec, 452cb13a392SEd Tanous const std::string&) { 45330215816SMarri Devender Rao if (ec) 45430215816SMarri Devender Rao { 455002d39b4SEd Tanous BMCWEB_LOG_ERROR << "DBUS response error: " << ec.message(); 45630215816SMarri Devender Rao messages::internalError(asyncResp->res); 45730215816SMarri Devender Rao return; 45830215816SMarri Devender Rao } 45930215816SMarri Devender Rao }, 46030215816SMarri Devender Rao service, objectPath, "xyz.openbmc_project.Certs.CSR.Create", 461002d39b4SEd Tanous "GenerateCSR", *optAlternativeNames, *optChallengePassword, city, 462002d39b4SEd Tanous commonName, *optContactPerson, country, *optEmail, *optGivenName, 463002d39b4SEd Tanous *optInitials, *optKeyBitLength, *optKeyCurveId, 4640fda0f12SGeorge Liu *optKeyPairAlgorithm, *optKeyUsage, organization, 4650fda0f12SGeorge Liu organizationalUnit, state, *optSurname, *optUnstructuredName); 4667e860f15SJohn Edward Broadbent }); 4677e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionGenerateCSR 46830215816SMarri Devender Rao 4695968caeeSMarri Devender Rao /** 4704e0453b1SGunnar Mills * @brief Parse and update Certificate Issue/Subject property 4715968caeeSMarri Devender Rao * 4725968caeeSMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 4735968caeeSMarri Devender Rao * @param[in] str Issuer/Subject value in key=value pairs 4745968caeeSMarri Devender Rao * @param[in] type Issuer/Subject 4755968caeeSMarri Devender Rao * @return None 4765968caeeSMarri Devender Rao */ 4775968caeeSMarri Devender Rao static void updateCertIssuerOrSubject(nlohmann::json& out, 4785968caeeSMarri Devender Rao const std::string_view value) 4795968caeeSMarri Devender Rao { 4805968caeeSMarri Devender Rao // example: O=openbmc-project.xyz,CN=localhost 4815968caeeSMarri Devender Rao std::string_view::iterator i = value.begin(); 4825968caeeSMarri Devender Rao while (i != value.end()) 4835968caeeSMarri Devender Rao { 4845968caeeSMarri Devender Rao std::string_view::iterator tokenBegin = i; 4855968caeeSMarri Devender Rao while (i != value.end() && *i != '=') 4865968caeeSMarri Devender Rao { 48717a897dfSManojkiran Eda ++i; 4885968caeeSMarri Devender Rao } 4895968caeeSMarri Devender Rao if (i == value.end()) 4905968caeeSMarri Devender Rao { 4915968caeeSMarri Devender Rao break; 4925968caeeSMarri Devender Rao } 493271584abSEd Tanous const std::string_view key(tokenBegin, 494271584abSEd Tanous static_cast<size_t>(i - tokenBegin)); 49517a897dfSManojkiran Eda ++i; 4965968caeeSMarri Devender Rao tokenBegin = i; 4975968caeeSMarri Devender Rao while (i != value.end() && *i != ',') 4985968caeeSMarri Devender Rao { 49917a897dfSManojkiran Eda ++i; 5005968caeeSMarri Devender Rao } 501271584abSEd Tanous const std::string_view val(tokenBegin, 502271584abSEd Tanous static_cast<size_t>(i - tokenBegin)); 5035968caeeSMarri Devender Rao if (key == "L") 5045968caeeSMarri Devender Rao { 5055968caeeSMarri Devender Rao out["City"] = val; 5065968caeeSMarri Devender Rao } 5075968caeeSMarri Devender Rao else if (key == "CN") 5085968caeeSMarri Devender Rao { 5095968caeeSMarri Devender Rao out["CommonName"] = val; 5105968caeeSMarri Devender Rao } 5115968caeeSMarri Devender Rao else if (key == "C") 5125968caeeSMarri Devender Rao { 5135968caeeSMarri Devender Rao out["Country"] = val; 5145968caeeSMarri Devender Rao } 5155968caeeSMarri Devender Rao else if (key == "O") 5165968caeeSMarri Devender Rao { 5175968caeeSMarri Devender Rao out["Organization"] = val; 5185968caeeSMarri Devender Rao } 5195968caeeSMarri Devender Rao else if (key == "OU") 5205968caeeSMarri Devender Rao { 5215968caeeSMarri Devender Rao out["OrganizationalUnit"] = val; 5225968caeeSMarri Devender Rao } 5235968caeeSMarri Devender Rao else if (key == "ST") 5245968caeeSMarri Devender Rao { 5255968caeeSMarri Devender Rao out["State"] = val; 5265968caeeSMarri Devender Rao } 5275968caeeSMarri Devender Rao // skip comma character 5285968caeeSMarri Devender Rao if (i != value.end()) 5295968caeeSMarri Devender Rao { 53017a897dfSManojkiran Eda ++i; 5315968caeeSMarri Devender Rao } 5325968caeeSMarri Devender Rao } 5335968caeeSMarri Devender Rao } 5345968caeeSMarri Devender Rao 5355968caeeSMarri Devender Rao /** 536d3f92ce7SJiaqing Zhao * @brief Retrieve the installed certificate list 537d3f92ce7SJiaqing Zhao * 538d3f92ce7SJiaqing Zhao * @param[in] asyncResp Shared pointer to the response message 539d3f92ce7SJiaqing Zhao * @param[in] basePath DBus object path to search 540d3f92ce7SJiaqing Zhao * @param[in] listPtr Json pointer to the list in asyncResp 541d3f92ce7SJiaqing Zhao * @param[in] countPtr Json pointer to the count in asyncResp 542d3f92ce7SJiaqing Zhao * @return None 543d3f92ce7SJiaqing Zhao */ 544d3f92ce7SJiaqing Zhao static void 545d3f92ce7SJiaqing Zhao getCertificateList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 546d3f92ce7SJiaqing Zhao const std::string& basePath, 547d3f92ce7SJiaqing Zhao const nlohmann::json::json_pointer& listPtr, 548d3f92ce7SJiaqing Zhao const nlohmann::json::json_pointer& countPtr) 549d3f92ce7SJiaqing Zhao { 550d3f92ce7SJiaqing Zhao crow::connections::systemBus->async_method_call( 551d3f92ce7SJiaqing Zhao [asyncResp, listPtr, countPtr]( 552d3f92ce7SJiaqing Zhao const boost::system::error_code ec, 553d3f92ce7SJiaqing Zhao const dbus::utility::MapperGetSubTreePathsResponse& certPaths) { 554d3f92ce7SJiaqing Zhao if (ec) 555d3f92ce7SJiaqing Zhao { 556d3f92ce7SJiaqing Zhao BMCWEB_LOG_ERROR << "Certificate collection query failed: " << ec; 557d3f92ce7SJiaqing Zhao messages::internalError(asyncResp->res); 558d3f92ce7SJiaqing Zhao return; 559d3f92ce7SJiaqing Zhao } 560d3f92ce7SJiaqing Zhao 561d3f92ce7SJiaqing Zhao nlohmann::json& links = asyncResp->res.jsonValue[listPtr]; 562d3f92ce7SJiaqing Zhao links = nlohmann::json::array(); 563d3f92ce7SJiaqing Zhao for (const auto& certPath : certPaths) 564d3f92ce7SJiaqing Zhao { 565d3f92ce7SJiaqing Zhao sdbusplus::message::object_path objPath(certPath); 566d3f92ce7SJiaqing Zhao std::string certId = objPath.filename(); 567d3f92ce7SJiaqing Zhao if (certId.empty()) 568d3f92ce7SJiaqing Zhao { 569d3f92ce7SJiaqing Zhao BMCWEB_LOG_ERROR << "Invalid certificate objPath " << certPath; 570d3f92ce7SJiaqing Zhao continue; 571d3f92ce7SJiaqing Zhao } 572d3f92ce7SJiaqing Zhao 573d3f92ce7SJiaqing Zhao boost::urls::url certURL; 574d3f92ce7SJiaqing Zhao if (objPath.parent_path() == certs::httpsObjectPath) 575d3f92ce7SJiaqing Zhao { 576d3f92ce7SJiaqing Zhao certURL = crow::utility::urlFromPieces( 577d3f92ce7SJiaqing Zhao "redfish", "v1", "Managers", "bmc", "NetworkProtocol", 578d3f92ce7SJiaqing Zhao "HTTPS", "Certificates", certId); 579d3f92ce7SJiaqing Zhao } 580d3f92ce7SJiaqing Zhao else if (objPath.parent_path() == certs::ldapObjectPath) 581d3f92ce7SJiaqing Zhao { 582d3f92ce7SJiaqing Zhao certURL = crow::utility::urlFromPieces("redfish", "v1", 583d3f92ce7SJiaqing Zhao "AccountService", "LDAP", 584d3f92ce7SJiaqing Zhao "Certificates", certId); 585d3f92ce7SJiaqing Zhao } 586d3f92ce7SJiaqing Zhao else if (objPath.parent_path() == certs::authorityObjectPath) 587d3f92ce7SJiaqing Zhao { 588d3f92ce7SJiaqing Zhao certURL = crow::utility::urlFromPieces( 589d3f92ce7SJiaqing Zhao "redfish", "v1", "Managers", "bmc", "Truststore", 590d3f92ce7SJiaqing Zhao "Certificates", certId); 591d3f92ce7SJiaqing Zhao } 592d3f92ce7SJiaqing Zhao else 593d3f92ce7SJiaqing Zhao { 594d3f92ce7SJiaqing Zhao continue; 595d3f92ce7SJiaqing Zhao } 596d3f92ce7SJiaqing Zhao 597d3f92ce7SJiaqing Zhao nlohmann::json::object_t link; 598d3f92ce7SJiaqing Zhao link["@odata.id"] = certURL; 599d3f92ce7SJiaqing Zhao links.emplace_back(std::move(link)); 600d3f92ce7SJiaqing Zhao } 601d3f92ce7SJiaqing Zhao 602d3f92ce7SJiaqing Zhao asyncResp->res.jsonValue[countPtr] = links.size(); 603d3f92ce7SJiaqing Zhao }, 604d3f92ce7SJiaqing Zhao "xyz.openbmc_project.ObjectMapper", 605d3f92ce7SJiaqing Zhao "/xyz/openbmc_project/object_mapper", 606d3f92ce7SJiaqing Zhao "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", basePath, 0, 607d3f92ce7SJiaqing Zhao std::array<const char*, 1>{certs::certPropIntf}); 608d3f92ce7SJiaqing Zhao } 609d3f92ce7SJiaqing Zhao 610d3f92ce7SJiaqing Zhao /** 6115968caeeSMarri Devender Rao * @brief Retrieve the certificates properties and append to the response 6125968caeeSMarri Devender Rao * message 6135968caeeSMarri Devender Rao * 6145968caeeSMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 6155968caeeSMarri Devender Rao * @param[in] objectPath Path of the D-Bus service object 6165968caeeSMarri Devender Rao * @param[in] certId Id of the certificate 6175968caeeSMarri Devender Rao * @param[in] certURL URL of the certificate object 6185968caeeSMarri Devender Rao * @param[in] name name of the certificate 6195968caeeSMarri Devender Rao * @return None 6205968caeeSMarri Devender Rao */ 6215968caeeSMarri Devender Rao static void getCertificateProperties( 6228d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 623e19e97e2SJiaqing Zhao const std::string& objectPath, const std::string& service, 6241e312598SJiaqing Zhao const std::string& certId, const boost::urls::url& certURL, 625e19e97e2SJiaqing Zhao const std::string& name) 6265968caeeSMarri Devender Rao { 6275968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "getCertificateProperties Path=" << objectPath 6285968caeeSMarri Devender Rao << " certId=" << certId << " certURl=" << certURL; 6299b12d1f9SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 6309b12d1f9SKrzysztof Grobelny *crow::connections::systemBus, service, objectPath, certs::certPropIntf, 631b9d36b47SEd Tanous [asyncResp, certURL, certId, 632b9d36b47SEd Tanous name](const boost::system::error_code ec, 633b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& properties) { 6345968caeeSMarri Devender Rao if (ec) 6355968caeeSMarri Devender Rao { 6365968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 637*d8a5d5d8SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "Certificate", certId); 6385968caeeSMarri Devender Rao return; 6395968caeeSMarri Devender Rao } 6409b12d1f9SKrzysztof Grobelny 6419b12d1f9SKrzysztof Grobelny const std::string* certificateString = nullptr; 6429b12d1f9SKrzysztof Grobelny const std::vector<std::string>* keyUsage = nullptr; 6439b12d1f9SKrzysztof Grobelny const std::string* issuer = nullptr; 6449b12d1f9SKrzysztof Grobelny const std::string* subject = nullptr; 6459b12d1f9SKrzysztof Grobelny const uint64_t* validNotAfter = nullptr; 6469b12d1f9SKrzysztof Grobelny const uint64_t* validNotBefore = nullptr; 6479b12d1f9SKrzysztof Grobelny 6489b12d1f9SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 6499b12d1f9SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "CertificateString", 6509b12d1f9SKrzysztof Grobelny certificateString, "KeyUsage", keyUsage, "Issuer", issuer, 6519b12d1f9SKrzysztof Grobelny "Subject", subject, "ValidNotAfter", validNotAfter, 6529b12d1f9SKrzysztof Grobelny "ValidNotBefore", validNotBefore); 6539b12d1f9SKrzysztof Grobelny 6549b12d1f9SKrzysztof Grobelny if (!success) 6559b12d1f9SKrzysztof Grobelny { 6569b12d1f9SKrzysztof Grobelny messages::internalError(asyncResp->res); 6579b12d1f9SKrzysztof Grobelny return; 6589b12d1f9SKrzysztof Grobelny } 6599b12d1f9SKrzysztof Grobelny 6601476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = certURL; 6611476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 6621476687dSEd Tanous "#Certificate.v1_0_0.Certificate"; 663e19e97e2SJiaqing Zhao asyncResp->res.jsonValue["Id"] = certId; 6641476687dSEd Tanous asyncResp->res.jsonValue["Name"] = name; 6651476687dSEd Tanous asyncResp->res.jsonValue["Description"] = name; 6665968caeeSMarri Devender Rao asyncResp->res.jsonValue["CertificateString"] = ""; 6679b12d1f9SKrzysztof Grobelny asyncResp->res.jsonValue["KeyUsage"] = nlohmann::json::array(); 6689b12d1f9SKrzysztof Grobelny 6699b12d1f9SKrzysztof Grobelny if (certificateString != nullptr) 6705968caeeSMarri Devender Rao { 6719b12d1f9SKrzysztof Grobelny asyncResp->res.jsonValue["CertificateString"] = *certificateString; 6725968caeeSMarri Devender Rao } 6739b12d1f9SKrzysztof Grobelny 6749b12d1f9SKrzysztof Grobelny if (keyUsage != nullptr) 6755968caeeSMarri Devender Rao { 6769b12d1f9SKrzysztof Grobelny asyncResp->res.jsonValue["KeyUsage"] = *keyUsage; 6775968caeeSMarri Devender Rao } 6789b12d1f9SKrzysztof Grobelny 6799b12d1f9SKrzysztof Grobelny if (issuer != nullptr) 6805968caeeSMarri Devender Rao { 6819b12d1f9SKrzysztof Grobelny updateCertIssuerOrSubject(asyncResp->res.jsonValue["Issuer"], 6829b12d1f9SKrzysztof Grobelny *issuer); 6835968caeeSMarri Devender Rao } 6849b12d1f9SKrzysztof Grobelny 6859b12d1f9SKrzysztof Grobelny if (subject != nullptr) 6865968caeeSMarri Devender Rao { 6879b12d1f9SKrzysztof Grobelny updateCertIssuerOrSubject(asyncResp->res.jsonValue["Subject"], 6889b12d1f9SKrzysztof Grobelny *subject); 6895968caeeSMarri Devender Rao } 6909b12d1f9SKrzysztof Grobelny 6919b12d1f9SKrzysztof Grobelny if (validNotAfter != nullptr) 6925968caeeSMarri Devender Rao { 6935968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotAfter"] = 6949b12d1f9SKrzysztof Grobelny redfish::time_utils::getDateTimeUint(*validNotAfter); 6955968caeeSMarri Devender Rao } 6969b12d1f9SKrzysztof Grobelny 6979b12d1f9SKrzysztof Grobelny if (validNotBefore != nullptr) 6985968caeeSMarri Devender Rao { 6995968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotBefore"] = 7009b12d1f9SKrzysztof Grobelny redfish::time_utils::getDateTimeUint(*validNotBefore); 7015968caeeSMarri Devender Rao } 7029b12d1f9SKrzysztof Grobelny 7031e312598SJiaqing Zhao asyncResp->res.addHeader( 704d9f6c621SEd Tanous boost::beast::http::field::location, 705d9f6c621SEd Tanous std::string_view(certURL.data(), certURL.size())); 7069b12d1f9SKrzysztof Grobelny }); 7075968caeeSMarri Devender Rao } 7085968caeeSMarri Devender Rao 7095968caeeSMarri Devender Rao /** 7105968caeeSMarri Devender Rao * Action to replace an existing certificate 7115968caeeSMarri Devender Rao */ 7127e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionsReplaceCertificate(App& app) 7135968caeeSMarri Devender Rao { 7140fda0f12SGeorge Liu BMCWEB_ROUTE( 7150fda0f12SGeorge Liu app, 7160fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate/") 717ed398213SEd Tanous .privileges(redfish::privileges::postCertificateService) 718002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 719002d39b4SEd Tanous [&app](const crow::Request& req, 7207e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 7213ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 72245ca1b86SEd Tanous { 72345ca1b86SEd Tanous return; 72445ca1b86SEd Tanous } 7255968caeeSMarri Devender Rao std::string certificate; 7265968caeeSMarri Devender Rao nlohmann::json certificateUri; 7275968caeeSMarri Devender Rao std::optional<std::string> certificateType = "PEM"; 7288d1b46d7Szhanghch05 729002d39b4SEd Tanous if (!json_util::readJsonAction(req, asyncResp->res, "CertificateString", 730002d39b4SEd Tanous certificate, "CertificateUri", 731002d39b4SEd Tanous certificateUri, "CertificateType", 732002d39b4SEd Tanous certificateType)) 7335968caeeSMarri Devender Rao { 7345968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Required parameters are missing"; 7355968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 7365968caeeSMarri Devender Rao return; 7375968caeeSMarri Devender Rao } 7385968caeeSMarri Devender Rao 7395968caeeSMarri Devender Rao if (!certificateType) 7405968caeeSMarri Devender Rao { 7415968caeeSMarri Devender Rao // should never happen, but it never hurts to be paranoid. 7425968caeeSMarri Devender Rao return; 7435968caeeSMarri Devender Rao } 7445968caeeSMarri Devender Rao if (certificateType != "PEM") 7455968caeeSMarri Devender Rao { 7465968caeeSMarri Devender Rao messages::actionParameterNotSupported( 7475968caeeSMarri Devender Rao asyncResp->res, "CertificateType", "ReplaceCertificate"); 7485968caeeSMarri Devender Rao return; 7495968caeeSMarri Devender Rao } 7505968caeeSMarri Devender Rao 7515968caeeSMarri Devender Rao std::string certURI; 7525968caeeSMarri Devender Rao if (!redfish::json_util::readJson(certificateUri, asyncResp->res, 7535968caeeSMarri Devender Rao "@odata.id", certURI)) 7545968caeeSMarri Devender Rao { 7555968caeeSMarri Devender Rao messages::actionParameterMissing( 7565968caeeSMarri Devender Rao asyncResp->res, "ReplaceCertificate", "CertificateUri"); 7575968caeeSMarri Devender Rao return; 7585968caeeSMarri Devender Rao } 75975b63a2cSJiaqing Zhao BMCWEB_LOG_INFO << "Certificate URI to replace: " << certURI; 7605968caeeSMarri Devender Rao 76175b63a2cSJiaqing Zhao boost::urls::result<boost::urls::url_view> parsedUrl = 76275b63a2cSJiaqing Zhao boost::urls::parse_relative_ref(certURI); 76375b63a2cSJiaqing Zhao if (!parsedUrl) 7645968caeeSMarri Devender Rao { 765002d39b4SEd Tanous messages::actionParameterValueFormatError(asyncResp->res, certURI, 766002d39b4SEd Tanous "CertificateUri", 7675968caeeSMarri Devender Rao "ReplaceCertificate"); 7685968caeeSMarri Devender Rao return; 7695968caeeSMarri Devender Rao } 77075b63a2cSJiaqing Zhao 77175b63a2cSJiaqing Zhao std::string id; 77275b63a2cSJiaqing Zhao sdbusplus::message::object_path objectPath; 7735968caeeSMarri Devender Rao std::string name; 77437cce918SMarri Devender Rao std::string service; 77575b63a2cSJiaqing Zhao if (crow::utility::readUrlSegments( 77675b63a2cSJiaqing Zhao *parsedUrl, "redfish", "v1", "Managers", "bmc", 77775b63a2cSJiaqing Zhao "NetworkProtocol", "HTTPS", "Certificates", std::ref(id))) 7785968caeeSMarri Devender Rao { 779002d39b4SEd Tanous objectPath = 78075b63a2cSJiaqing Zhao sdbusplus::message::object_path(certs::httpsObjectPath) / id; 7815968caeeSMarri Devender Rao name = "HTTPS certificate"; 78237cce918SMarri Devender Rao service = certs::httpsServiceName; 78337cce918SMarri Devender Rao } 78475b63a2cSJiaqing Zhao else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1", 78575b63a2cSJiaqing Zhao "AccountService", "LDAP", 78675b63a2cSJiaqing Zhao "Certificates", std::ref(id))) 78737cce918SMarri Devender Rao { 788002d39b4SEd Tanous objectPath = 78975b63a2cSJiaqing Zhao sdbusplus::message::object_path(certs::ldapObjectPath) / id; 79037cce918SMarri Devender Rao name = "LDAP certificate"; 79137cce918SMarri Devender Rao service = certs::ldapServiceName; 7925968caeeSMarri Devender Rao } 79375b63a2cSJiaqing Zhao else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1", 79475b63a2cSJiaqing Zhao "Managers", "bmc", "Truststore", 79575b63a2cSJiaqing Zhao "Certificates", std::ref(id))) 796cfcd5f6bSMarri Devender Rao { 79775b63a2cSJiaqing Zhao objectPath = 79875b63a2cSJiaqing Zhao sdbusplus::message::object_path(certs::authorityObjectPath) / 79975b63a2cSJiaqing Zhao id; 800cfcd5f6bSMarri Devender Rao name = "TrustStore certificate"; 801cfcd5f6bSMarri Devender Rao service = certs::authorityServiceName; 802cfcd5f6bSMarri Devender Rao } 8035968caeeSMarri Devender Rao else 8045968caeeSMarri Devender Rao { 8055968caeeSMarri Devender Rao messages::actionParameterNotSupported( 8065968caeeSMarri Devender Rao asyncResp->res, "CertificateUri", "ReplaceCertificate"); 8075968caeeSMarri Devender Rao return; 8085968caeeSMarri Devender Rao } 8095968caeeSMarri Devender Rao 8105968caeeSMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 8115968caeeSMarri Devender Rao std::make_shared<CertificateFile>(certificate); 8125968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 8131e312598SJiaqing Zhao [asyncResp, certFile, objectPath, service, url{*parsedUrl}, id, 8145968caeeSMarri Devender Rao name](const boost::system::error_code ec) { 8155968caeeSMarri Devender Rao if (ec) 8165968caeeSMarri Devender Rao { 8175968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 81890d2d1e8SJiaqing Zhao if (ec.value() == 81990d2d1e8SJiaqing Zhao boost::system::linux_error::bad_request_descriptor) 82090d2d1e8SJiaqing Zhao { 821*d8a5d5d8SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "Certificate", 822*d8a5d5d8SJiaqing Zhao id); 8235968caeeSMarri Devender Rao return; 8245968caeeSMarri Devender Rao } 82590d2d1e8SJiaqing Zhao messages::internalError(asyncResp->res); 82690d2d1e8SJiaqing Zhao return; 82790d2d1e8SJiaqing Zhao } 8281e312598SJiaqing Zhao getCertificateProperties(asyncResp, objectPath, service, id, url, 8291e312598SJiaqing Zhao 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) 8491e312598SJiaqing Zhao .methods(boost::beast::http::verb::get)( 8501e312598SJiaqing Zhao [&app](const crow::Request& req, 8517e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 852717b9802SJiaqing Zhao const std::string& id) -> void { 8533ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 85445ca1b86SEd Tanous { 85545ca1b86SEd Tanous return; 85645ca1b86SEd Tanous } 8575968caeeSMarri Devender Rao 858717b9802SJiaqing Zhao BMCWEB_LOG_DEBUG << "HTTPS Certificate ID=" << id; 8591e312598SJiaqing Zhao const boost::urls::url certURL = crow::utility::urlFromPieces( 8601e312598SJiaqing Zhao "redfish", "v1", "Managers", "bmc", "NetworkProtocol", 8611e312598SJiaqing Zhao "HTTPS", "Certificates", id); 862717b9802SJiaqing Zhao std::string objPath = 8631e312598SJiaqing Zhao sdbusplus::message::object_path(certs::httpsObjectPath) / 8641e312598SJiaqing Zhao 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(); 9391e312598SJiaqing Zhao const boost::urls::url certURL = crow::utility::urlFromPieces( 9401e312598SJiaqing Zhao "redfish", "v1", "Managers", "bmc", "NetworkProtocol", "HTTPS", 9411e312598SJiaqing Zhao "Certificates", 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(); 10461e312598SJiaqing Zhao const boost::urls::url certURL = 10471e312598SJiaqing Zhao crow::utility::urlFromPieces("redfish", "v1", "AccountService", 10481e312598SJiaqing Zhao "LDAP", "Certificates", certId); 1049717b9802SJiaqing Zhao getCertificateProperties(asyncResp, objectPath, 1050717b9802SJiaqing Zhao certs::ldapServiceName, certId, certURL, 1051717b9802SJiaqing Zhao "LDAP Certificate"); 105237cce918SMarri Devender Rao BMCWEB_LOG_DEBUG << "LDAP certificate install file=" 105337cce918SMarri Devender Rao << certFile->getCertFilePath(); 105437cce918SMarri Devender Rao }, 105537cce918SMarri Devender Rao certs::ldapServiceName, certs::ldapObjectPath, 1056002d39b4SEd Tanous certs::certInstallIntf, "Install", certFile->getCertFilePath()); 10577e860f15SJohn Edward Broadbent }); 10587e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificateCollection 105937cce918SMarri Devender Rao 106037cce918SMarri Devender Rao /** 106137cce918SMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 106237cce918SMarri Devender Rao * of a component, account or service. 106337cce918SMarri Devender Rao */ 10647e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificate(App& app) 106537cce918SMarri Devender Rao { 10667e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/") 1067ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 10687e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 106945ca1b86SEd Tanous [&app](const crow::Request& req, 10707e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1071717b9802SJiaqing Zhao const std::string& id) { 10723ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 107345ca1b86SEd Tanous { 107445ca1b86SEd Tanous return; 107545ca1b86SEd Tanous } 1076717b9802SJiaqing Zhao 1077717b9802SJiaqing Zhao BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" << id; 10781e312598SJiaqing Zhao const boost::urls::url certURL = crow::utility::urlFromPieces( 10791e312598SJiaqing Zhao "redfish", "v1", "AccountService", "LDAP", "Certificates", id); 1080717b9802SJiaqing Zhao std::string objPath = 1081717b9802SJiaqing Zhao sdbusplus::message::object_path(certs::ldapObjectPath) / id; 1082717b9802SJiaqing Zhao getCertificateProperties(asyncResp, objPath, certs::ldapServiceName, id, 1083717b9802SJiaqing Zhao certURL, "LDAP Certificate"); 10847e860f15SJohn Edward Broadbent }); 10857e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificate 1086cfcd5f6bSMarri Devender Rao /** 1087cfcd5f6bSMarri Devender Rao * Collection of TrustStoreCertificate certificates 1088cfcd5f6bSMarri Devender Rao */ 10897e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificateCollection(App& app) 1090cfcd5f6bSMarri Devender Rao { 10917e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/") 1092ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 1093002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1094002d39b4SEd Tanous [&app](const crow::Request& req, 1095002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 10963ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 109745ca1b86SEd Tanous { 109845ca1b86SEd Tanous return; 109945ca1b86SEd Tanous } 11001476687dSEd Tanous 11011476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 11021476687dSEd Tanous "/redfish/v1/Managers/bmc/Truststore/Certificates/"; 11031476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 11041476687dSEd Tanous "#CertificateCollection.CertificateCollection"; 1105002d39b4SEd Tanous asyncResp->res.jsonValue["Name"] = "TrustStore Certificates Collection"; 11061476687dSEd Tanous asyncResp->res.jsonValue["Description"] = 11071476687dSEd Tanous "A Collection of TrustStore certificate instances"; 11088d1b46d7Szhanghch05 1109d3f92ce7SJiaqing Zhao getCertificateList(asyncResp, certs::authorityObjectPath, 1110d3f92ce7SJiaqing Zhao "/Members"_json_pointer, 1111d3f92ce7SJiaqing Zhao "/Members@odata.count"_json_pointer); 11127e860f15SJohn Edward Broadbent }); 1113cfcd5f6bSMarri Devender Rao 11147e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/") 1115ed398213SEd Tanous .privileges(redfish::privileges::postCertificateCollection) 1116002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 1117002d39b4SEd Tanous [&app](const crow::Request& req, 11187e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 11193ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 112045ca1b86SEd Tanous { 112145ca1b86SEd Tanous return; 112245ca1b86SEd Tanous } 1123002d39b4SEd Tanous std::string certFileBody = getCertificateFromReqBody(asyncResp, req); 1124a08752f5SZbigniew Kurzynski 1125a08752f5SZbigniew Kurzynski if (certFileBody.empty()) 1126a08752f5SZbigniew Kurzynski { 11270fda0f12SGeorge Liu BMCWEB_LOG_ERROR << "Cannot get certificate from request body."; 1128a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 1129a08752f5SZbigniew Kurzynski return; 1130a08752f5SZbigniew Kurzynski } 1131a08752f5SZbigniew Kurzynski 1132a08752f5SZbigniew Kurzynski std::shared_ptr<CertificateFile> certFile = 1133a08752f5SZbigniew Kurzynski std::make_shared<CertificateFile>(certFileBody); 1134cfcd5f6bSMarri Devender Rao crow::connections::systemBus->async_method_call( 1135656ec7e3SZbigniew Kurzynski [asyncResp, certFile](const boost::system::error_code ec, 1136656ec7e3SZbigniew Kurzynski const std::string& objectPath) { 1137cfcd5f6bSMarri Devender Rao if (ec) 1138cfcd5f6bSMarri Devender Rao { 1139cfcd5f6bSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 1140cfcd5f6bSMarri Devender Rao messages::internalError(asyncResp->res); 1141cfcd5f6bSMarri Devender Rao return; 1142cfcd5f6bSMarri Devender Rao } 1143656ec7e3SZbigniew Kurzynski 1144717b9802SJiaqing Zhao sdbusplus::message::object_path path(objectPath); 1145717b9802SJiaqing Zhao std::string certId = path.filename(); 11461e312598SJiaqing Zhao const boost::urls::url certURL = crow::utility::urlFromPieces( 11471e312598SJiaqing Zhao "redfish", "v1", "Managers", "bmc", "Truststore", 11481e312598SJiaqing Zhao "Certificates", certId); 1149717b9802SJiaqing Zhao getCertificateProperties(asyncResp, objectPath, 1150717b9802SJiaqing Zhao certs::authorityServiceName, certId, 1151717b9802SJiaqing Zhao certURL, "TrustStore Certificate"); 11520fda0f12SGeorge Liu BMCWEB_LOG_DEBUG << "TrustStore certificate install file=" 1153cfcd5f6bSMarri Devender Rao << certFile->getCertFilePath(); 1154cfcd5f6bSMarri Devender Rao }, 1155cfcd5f6bSMarri Devender Rao certs::authorityServiceName, certs::authorityObjectPath, 11560fda0f12SGeorge Liu certs::certInstallIntf, "Install", certFile->getCertFilePath()); 11577e860f15SJohn Edward Broadbent }); 11587e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificateCollection 1159cfcd5f6bSMarri Devender Rao 1160cfcd5f6bSMarri Devender Rao /** 1161cfcd5f6bSMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 1162cfcd5f6bSMarri Devender Rao * of a component, account or service. 1163cfcd5f6bSMarri Devender Rao */ 11647e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificate(App& app) 1165cfcd5f6bSMarri Devender Rao { 11667e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/") 1167ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 11687e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 116945ca1b86SEd Tanous [&app](const crow::Request& req, 11707e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1171717b9802SJiaqing Zhao const std::string& id) { 11723ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 117345ca1b86SEd Tanous { 117445ca1b86SEd Tanous return; 117545ca1b86SEd Tanous } 1176717b9802SJiaqing Zhao 1177717b9802SJiaqing Zhao BMCWEB_LOG_DEBUG << "Truststore Certificate ID=" << id; 11781e312598SJiaqing Zhao const boost::urls::url certURL = 11791e312598SJiaqing Zhao crow::utility::urlFromPieces("redfish", "v1", "Managers", "bmc", 11801e312598SJiaqing Zhao "Truststore", "Certificates", id); 1181717b9802SJiaqing Zhao std::string objPath = 1182717b9802SJiaqing Zhao sdbusplus::message::object_path(certs::authorityObjectPath) / id; 1183717b9802SJiaqing Zhao getCertificateProperties(asyncResp, objPath, 1184717b9802SJiaqing Zhao certs::authorityServiceName, id, certURL, 1185717b9802SJiaqing Zhao "TrustStore Certificate"); 11867e860f15SJohn Edward Broadbent }); 118707a60299SZbigniew Kurzynski 11887e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/") 1189ed398213SEd Tanous .privileges(redfish::privileges::deleteCertificate) 11907e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::delete_)( 119145ca1b86SEd Tanous [&app](const crow::Request& req, 11927e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1193717b9802SJiaqing Zhao const std::string& id) { 11943ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 119545ca1b86SEd Tanous { 119645ca1b86SEd Tanous return; 119745ca1b86SEd Tanous } 119807a60299SZbigniew Kurzynski 1199717b9802SJiaqing Zhao BMCWEB_LOG_DEBUG << "Delete TrustStore Certificate ID=" << id; 1200717b9802SJiaqing Zhao std::string objPath = 1201717b9802SJiaqing Zhao sdbusplus::message::object_path(certs::authorityObjectPath) / id; 120207a60299SZbigniew Kurzynski 120307a60299SZbigniew Kurzynski crow::connections::systemBus->async_method_call( 120407a60299SZbigniew Kurzynski [asyncResp, id](const boost::system::error_code ec) { 120507a60299SZbigniew Kurzynski if (ec) 120607a60299SZbigniew Kurzynski { 1207*d8a5d5d8SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "Certificate", id); 120807a60299SZbigniew Kurzynski return; 120907a60299SZbigniew Kurzynski } 121007a60299SZbigniew Kurzynski BMCWEB_LOG_INFO << "Certificate deleted"; 1211002d39b4SEd Tanous asyncResp->res.result(boost::beast::http::status::no_content); 121207a60299SZbigniew Kurzynski }, 1213717b9802SJiaqing Zhao certs::authorityServiceName, objPath, certs::objDeleteIntf, 121407a60299SZbigniew Kurzynski "Delete"); 12157e860f15SJohn Edward Broadbent }); 12167e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificate 12175968caeeSMarri Devender Rao } // namespace redfish 1218