15968caeeSMarri Devender Rao #pragma once 25968caeeSMarri Devender Rao 37e860f15SJohn Edward Broadbent #include <app.hpp> 4e6604b11SIwona Klimaszewska #include <boost/convert.hpp> 5e6604b11SIwona Klimaszewska #include <boost/convert/strtol.hpp> 690d2d1e8SJiaqing Zhao #include <boost/system/linux_error.hpp> 7168e20c1SEd Tanous #include <dbus_utility.hpp> 845ca1b86SEd Tanous #include <query.hpp> 9ed398213SEd Tanous #include <registries/privilege_registry.hpp> 101214b7e7SGunnar Mills 115968caeeSMarri Devender Rao namespace redfish 125968caeeSMarri Devender Rao { 135968caeeSMarri Devender Rao namespace certs 145968caeeSMarri Devender Rao { 155968caeeSMarri Devender Rao constexpr char const* httpsObjectPath = 165968caeeSMarri Devender Rao "/xyz/openbmc_project/certs/server/https"; 175968caeeSMarri Devender Rao constexpr char const* certInstallIntf = "xyz.openbmc_project.Certs.Install"; 185968caeeSMarri Devender Rao constexpr char const* certReplaceIntf = "xyz.openbmc_project.Certs.Replace"; 1907a60299SZbigniew Kurzynski constexpr char const* objDeleteIntf = "xyz.openbmc_project.Object.Delete"; 205968caeeSMarri Devender Rao constexpr char const* certPropIntf = "xyz.openbmc_project.Certs.Certificate"; 215968caeeSMarri Devender Rao constexpr char const* dbusPropIntf = "org.freedesktop.DBus.Properties"; 225968caeeSMarri Devender Rao constexpr char const* dbusObjManagerIntf = "org.freedesktop.DBus.ObjectManager"; 2337cce918SMarri Devender Rao constexpr char const* ldapObjectPath = "/xyz/openbmc_project/certs/client/ldap"; 2437cce918SMarri Devender Rao constexpr char const* httpsServiceName = 2537cce918SMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Server.Https"; 2637cce918SMarri Devender Rao constexpr char const* ldapServiceName = 2737cce918SMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Client.Ldap"; 28cfcd5f6bSMarri Devender Rao constexpr char const* authorityServiceName = 29cfcd5f6bSMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Authority.Ldap"; 30cfcd5f6bSMarri Devender Rao constexpr char const* authorityObjectPath = 31cfcd5f6bSMarri Devender Rao "/xyz/openbmc_project/certs/authority/ldap"; 325968caeeSMarri Devender Rao } // namespace certs 335968caeeSMarri Devender Rao 345968caeeSMarri Devender Rao /** 355968caeeSMarri Devender Rao * The Certificate schema defines a Certificate Service which represents the 365968caeeSMarri Devender Rao * actions available to manage certificates and links to where certificates 375968caeeSMarri Devender Rao * are installed. 385968caeeSMarri Devender Rao */ 397e860f15SJohn Edward Broadbent 405968caeeSMarri Devender Rao // TODO: Issue#61 No entries are available for Certificate 414e0453b1SGunnar Mills // service at https://www.dmtf.org/standards/redfish 425968caeeSMarri Devender Rao // "redfish standard registries". Need to modify after DMTF 435968caeeSMarri Devender Rao // publish Privilege details for certificate service 445968caeeSMarri Devender Rao 457e860f15SJohn Edward Broadbent inline void requestRoutesCertificateService(App& app) 465968caeeSMarri Devender Rao { 477e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/") 48ed398213SEd Tanous .privileges(redfish::privileges::getCertificateService) 49002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 50002d39b4SEd Tanous [&app](const crow::Request& req, 51002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 52*3ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 5345ca1b86SEd Tanous { 5445ca1b86SEd Tanous return; 5545ca1b86SEd Tanous } 561476687dSEd Tanous 571476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 581476687dSEd Tanous "#CertificateService.v1_0_0.CertificateService"; 591476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 601476687dSEd Tanous "/redfish/v1/CertificateService"; 611476687dSEd Tanous asyncResp->res.jsonValue["Id"] = "CertificateService"; 621476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "Certificate Service"; 631476687dSEd Tanous asyncResp->res.jsonValue["Description"] = 641476687dSEd Tanous "Actions available to manage certificates"; 6572048780SAbhishek Patel // /redfish/v1/CertificateService/CertificateLocations is something 6672048780SAbhishek Patel // only ConfigureManager can access then only display when the user 6772048780SAbhishek Patel // has permissions ConfigureManager 6872048780SAbhishek Patel Privileges effectiveUserPrivileges = 6972048780SAbhishek Patel redfish::getUserPrivileges(req.userRole); 7072048780SAbhishek Patel if (isOperationAllowedWithPrivileges({{"ConfigureManager"}}, 7172048780SAbhishek Patel effectiveUserPrivileges)) 7272048780SAbhishek Patel { 731476687dSEd Tanous asyncResp->res.jsonValue["CertificateLocations"]["@odata.id"] = 741476687dSEd Tanous "/redfish/v1/CertificateService/CertificateLocations"; 7572048780SAbhishek Patel } 760fda0f12SGeorge Liu asyncResp->res 77002d39b4SEd Tanous .jsonValue["Actions"]["#CertificateService.ReplaceCertificate"] = { 780fda0f12SGeorge Liu {"target", 790fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate"}, 805968caeeSMarri Devender Rao {"CertificateType@Redfish.AllowableValues", {"PEM"}}}; 817e860f15SJohn Edward Broadbent asyncResp->res 827e860f15SJohn Edward Broadbent .jsonValue["Actions"]["#CertificateService.GenerateCSR"] = { 830fda0f12SGeorge Liu {"target", 840fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR"}}; 857e860f15SJohn Edward Broadbent }); 867e860f15SJohn Edward Broadbent } // requestRoutesCertificateService 8737cce918SMarri Devender Rao 885968caeeSMarri Devender Rao /** 895968caeeSMarri Devender Rao * @brief Find the ID specified in the URL 905968caeeSMarri Devender Rao * Finds the numbers specified after the last "/" in the URL and returns. 915968caeeSMarri Devender Rao * @param[in] path URL 925968caeeSMarri Devender Rao * @return -1 on failure and number on success 935968caeeSMarri Devender Rao */ 9423a21a1cSEd Tanous inline long getIDFromURL(const std::string_view url) 955968caeeSMarri Devender Rao { 96f23b7296SEd Tanous std::size_t found = url.rfind('/'); 975968caeeSMarri Devender Rao if (found == std::string::npos) 985968caeeSMarri Devender Rao { 995968caeeSMarri Devender Rao return -1; 1005968caeeSMarri Devender Rao } 101e6604b11SIwona Klimaszewska 1025968caeeSMarri Devender Rao if ((found + 1) < url.length()) 1035968caeeSMarri Devender Rao { 1045968caeeSMarri Devender Rao std::string_view str = url.substr(found + 1); 105e6604b11SIwona Klimaszewska 106e6604b11SIwona Klimaszewska return boost::convert<long>(str, boost::cnv::strtol()).value_or(-1); 1075968caeeSMarri Devender Rao } 108e6604b11SIwona Klimaszewska 1095968caeeSMarri Devender Rao return -1; 1105968caeeSMarri Devender Rao } 1115968caeeSMarri Devender Rao 1128d1b46d7Szhanghch05 inline std::string getCertificateFromReqBody( 1138d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 11458eb238fSKowalski, Kamil const crow::Request& req) 11558eb238fSKowalski, Kamil { 11658eb238fSKowalski, Kamil nlohmann::json reqJson = nlohmann::json::parse(req.body, nullptr, false); 11758eb238fSKowalski, Kamil 11858eb238fSKowalski, Kamil if (reqJson.is_discarded()) 11958eb238fSKowalski, Kamil { 12058eb238fSKowalski, Kamil // We did not receive JSON request, proceed as it is RAW data 12158eb238fSKowalski, Kamil return req.body; 12258eb238fSKowalski, Kamil } 12358eb238fSKowalski, Kamil 12458eb238fSKowalski, Kamil std::string certificate; 12558eb238fSKowalski, Kamil std::optional<std::string> certificateType = "PEM"; 12658eb238fSKowalski, Kamil 12715ed6780SWilly Tu if (!json_util::readJsonPatch(req, asyncResp->res, "CertificateString", 12815ed6780SWilly Tu certificate, "CertificateType", 12915ed6780SWilly Tu certificateType)) 13058eb238fSKowalski, Kamil { 13158eb238fSKowalski, Kamil BMCWEB_LOG_ERROR << "Required parameters are missing"; 13258eb238fSKowalski, Kamil messages::internalError(asyncResp->res); 133abb93cddSEd Tanous return {}; 13458eb238fSKowalski, Kamil } 13558eb238fSKowalski, Kamil 13658eb238fSKowalski, Kamil if (*certificateType != "PEM") 13758eb238fSKowalski, Kamil { 13858eb238fSKowalski, Kamil messages::propertyValueNotInList(asyncResp->res, *certificateType, 13958eb238fSKowalski, Kamil "CertificateType"); 140abb93cddSEd Tanous return {}; 14158eb238fSKowalski, Kamil } 14258eb238fSKowalski, Kamil 14358eb238fSKowalski, Kamil return certificate; 14458eb238fSKowalski, Kamil } 14558eb238fSKowalski, Kamil 1465968caeeSMarri Devender Rao /** 1475968caeeSMarri Devender Rao * Class to create a temporary certificate file for uploading to system 1485968caeeSMarri Devender Rao */ 1495968caeeSMarri Devender Rao class CertificateFile 1505968caeeSMarri Devender Rao { 1515968caeeSMarri Devender Rao public: 1525968caeeSMarri Devender Rao CertificateFile() = delete; 1535968caeeSMarri Devender Rao CertificateFile(const CertificateFile&) = delete; 1545968caeeSMarri Devender Rao CertificateFile& operator=(const CertificateFile&) = delete; 1555968caeeSMarri Devender Rao CertificateFile(CertificateFile&&) = delete; 1565968caeeSMarri Devender Rao CertificateFile& operator=(CertificateFile&&) = delete; 1575968caeeSMarri Devender Rao CertificateFile(const std::string& certString) 1585968caeeSMarri Devender Rao { 15972d52d25SEd Tanous std::array<char, 18> dirTemplate = {'/', 't', 'm', 'p', '/', 'C', 1605207438cSEd Tanous 'e', 'r', 't', 's', '.', 'X', 1615207438cSEd Tanous 'X', 'X', 'X', 'X', 'X', '\0'}; 1625207438cSEd Tanous char* tempDirectory = mkdtemp(dirTemplate.data()); 163e662eae8SEd Tanous if (tempDirectory != nullptr) 1645968caeeSMarri Devender Rao { 1655968caeeSMarri Devender Rao certDirectory = tempDirectory; 1665968caeeSMarri Devender Rao certificateFile = certDirectory / "cert.pem"; 1675968caeeSMarri Devender Rao std::ofstream out(certificateFile, std::ofstream::out | 1685968caeeSMarri Devender Rao std::ofstream::binary | 1695968caeeSMarri Devender Rao std::ofstream::trunc); 1705968caeeSMarri Devender Rao out << certString; 1715968caeeSMarri Devender Rao out.close(); 1728cc8edecSEd Tanous BMCWEB_LOG_DEBUG << "Creating certificate file" 1738cc8edecSEd Tanous << certificateFile.string(); 1745968caeeSMarri Devender Rao } 1755968caeeSMarri Devender Rao } 1765968caeeSMarri Devender Rao ~CertificateFile() 1775968caeeSMarri Devender Rao { 1785968caeeSMarri Devender Rao if (std::filesystem::exists(certDirectory)) 1795968caeeSMarri Devender Rao { 1808cc8edecSEd Tanous BMCWEB_LOG_DEBUG << "Removing certificate file" 1818cc8edecSEd Tanous << certificateFile.string(); 18223a21a1cSEd Tanous std::error_code ec; 18323a21a1cSEd Tanous std::filesystem::remove_all(certDirectory, ec); 18423a21a1cSEd Tanous if (ec) 1855968caeeSMarri Devender Rao { 1865968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Failed to remove temp directory" 1878cc8edecSEd Tanous << certDirectory.string(); 1885968caeeSMarri Devender Rao } 1895968caeeSMarri Devender Rao } 1905968caeeSMarri Devender Rao } 1915968caeeSMarri Devender Rao std::string getCertFilePath() 1925968caeeSMarri Devender Rao { 1935968caeeSMarri Devender Rao return certificateFile; 1945968caeeSMarri Devender Rao } 1955968caeeSMarri Devender Rao 1965968caeeSMarri Devender Rao private: 1975968caeeSMarri Devender Rao std::filesystem::path certificateFile; 1985968caeeSMarri Devender Rao std::filesystem::path certDirectory; 1995968caeeSMarri Devender Rao }; 2005968caeeSMarri Devender Rao 20130215816SMarri Devender Rao static std::unique_ptr<sdbusplus::bus::match::match> csrMatcher; 20230215816SMarri Devender Rao /** 20330215816SMarri Devender Rao * @brief Read data from CSR D-bus object and set to response 20430215816SMarri Devender Rao * 20530215816SMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 20630215816SMarri Devender Rao * @param[in] certURI Link to certifiate collection URI 20730215816SMarri Devender Rao * @param[in] service D-Bus service name 20830215816SMarri Devender Rao * @param[in] certObjPath certificate D-Bus object path 20930215816SMarri Devender Rao * @param[in] csrObjPath CSR D-Bus object path 21030215816SMarri Devender Rao * @return None 21130215816SMarri Devender Rao */ 2128d1b46d7Szhanghch05 static void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 21330215816SMarri Devender Rao const std::string& certURI, const std::string& service, 21430215816SMarri Devender Rao const std::string& certObjPath, 21530215816SMarri Devender Rao const std::string& csrObjPath) 21630215816SMarri Devender Rao { 21730215816SMarri Devender Rao BMCWEB_LOG_DEBUG << "getCSR CertObjectPath" << certObjPath 21830215816SMarri Devender Rao << " CSRObjectPath=" << csrObjPath 21930215816SMarri Devender Rao << " service=" << service; 22030215816SMarri Devender Rao crow::connections::systemBus->async_method_call( 22130215816SMarri Devender Rao [asyncResp, certURI](const boost::system::error_code ec, 22230215816SMarri Devender Rao const std::string& csr) { 22330215816SMarri Devender Rao if (ec) 22430215816SMarri Devender Rao { 22530215816SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 22630215816SMarri Devender Rao messages::internalError(asyncResp->res); 22730215816SMarri Devender Rao return; 22830215816SMarri Devender Rao } 22930215816SMarri Devender Rao if (csr.empty()) 23030215816SMarri Devender Rao { 23130215816SMarri Devender Rao BMCWEB_LOG_ERROR << "CSR read is empty"; 23230215816SMarri Devender Rao messages::internalError(asyncResp->res); 23330215816SMarri Devender Rao return; 23430215816SMarri Devender Rao } 23530215816SMarri Devender Rao asyncResp->res.jsonValue["CSRString"] = csr; 2361476687dSEd Tanous asyncResp->res.jsonValue["CertificateCollection"]["@odata.id"] = 2371476687dSEd Tanous certURI; 23830215816SMarri Devender Rao }, 23930215816SMarri Devender Rao service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR"); 24030215816SMarri Devender Rao } 24130215816SMarri Devender Rao 24230215816SMarri Devender Rao /** 24330215816SMarri Devender Rao * Action to Generate CSR 24430215816SMarri Devender Rao */ 2457e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionGenerateCSR(App& app) 24630215816SMarri Devender Rao { 2470fda0f12SGeorge Liu BMCWEB_ROUTE( 2480fda0f12SGeorge Liu app, 2490fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR/") 2505344ab8eSAbhishek Patel .privileges(redfish::privileges::postCertificateService) 251002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 252002d39b4SEd Tanous [&app](const crow::Request& req, 2537e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 254*3ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 25545ca1b86SEd Tanous { 25645ca1b86SEd Tanous return; 25745ca1b86SEd Tanous } 2582c70f800SEd Tanous static const int rsaKeyBitLength = 2048; 2598d1b46d7Szhanghch05 26030215816SMarri Devender Rao // Required parameters 26130215816SMarri Devender Rao std::string city; 26230215816SMarri Devender Rao std::string commonName; 26330215816SMarri Devender Rao std::string country; 26430215816SMarri Devender Rao std::string organization; 26530215816SMarri Devender Rao std::string organizationalUnit; 26630215816SMarri Devender Rao std::string state; 26730215816SMarri Devender Rao nlohmann::json certificateCollection; 26830215816SMarri Devender Rao 26930215816SMarri Devender Rao // Optional parameters 27030215816SMarri Devender Rao std::optional<std::vector<std::string>> optAlternativeNames = 27130215816SMarri Devender Rao std::vector<std::string>(); 27230215816SMarri Devender Rao std::optional<std::string> optContactPerson = ""; 27330215816SMarri Devender Rao std::optional<std::string> optChallengePassword = ""; 27430215816SMarri Devender Rao std::optional<std::string> optEmail = ""; 27530215816SMarri Devender Rao std::optional<std::string> optGivenName = ""; 27630215816SMarri Devender Rao std::optional<std::string> optInitials = ""; 2772c70f800SEd Tanous std::optional<int64_t> optKeyBitLength = rsaKeyBitLength; 278aaf3206fSVernon Mauery std::optional<std::string> optKeyCurveId = "secp384r1"; 27930215816SMarri Devender Rao std::optional<std::string> optKeyPairAlgorithm = "EC"; 28030215816SMarri Devender Rao std::optional<std::vector<std::string>> optKeyUsage = 28130215816SMarri Devender Rao std::vector<std::string>(); 28230215816SMarri Devender Rao std::optional<std::string> optSurname = ""; 28330215816SMarri Devender Rao std::optional<std::string> optUnstructuredName = ""; 28415ed6780SWilly Tu if (!json_util::readJsonAction( 2850fda0f12SGeorge Liu req, asyncResp->res, "City", city, "CommonName", commonName, 2860fda0f12SGeorge Liu "ContactPerson", optContactPerson, "Country", country, 2870fda0f12SGeorge Liu "Organization", organization, "OrganizationalUnit", 2880fda0f12SGeorge Liu organizationalUnit, "State", state, "CertificateCollection", 289002d39b4SEd Tanous certificateCollection, "AlternativeNames", optAlternativeNames, 290002d39b4SEd Tanous "ChallengePassword", optChallengePassword, "Email", optEmail, 291002d39b4SEd Tanous "GivenName", optGivenName, "Initials", optInitials, 292002d39b4SEd Tanous "KeyBitLength", optKeyBitLength, "KeyCurveId", optKeyCurveId, 2930fda0f12SGeorge Liu "KeyPairAlgorithm", optKeyPairAlgorithm, "KeyUsage", 2940fda0f12SGeorge Liu optKeyUsage, "Surname", optSurname, "UnstructuredName", 2950fda0f12SGeorge Liu optUnstructuredName)) 29630215816SMarri Devender Rao { 29730215816SMarri Devender Rao return; 29830215816SMarri Devender Rao } 29930215816SMarri Devender Rao 30030215816SMarri Devender Rao // bmcweb has no way to store or decode a private key challenge 3017e860f15SJohn Edward Broadbent // password, which will likely cause bmcweb to crash on startup 3027e860f15SJohn Edward Broadbent // if this is not set on a post so not allowing the user to set 3037e860f15SJohn Edward Broadbent // value 30426f6976fSEd Tanous if (!optChallengePassword->empty()) 30530215816SMarri Devender Rao { 306002d39b4SEd Tanous messages::actionParameterNotSupported(asyncResp->res, "GenerateCSR", 307002d39b4SEd Tanous "ChallengePassword"); 30830215816SMarri Devender Rao return; 30930215816SMarri Devender Rao } 31030215816SMarri Devender Rao 31130215816SMarri Devender Rao std::string certURI; 312002d39b4SEd Tanous if (!redfish::json_util::readJson(certificateCollection, asyncResp->res, 313002d39b4SEd Tanous "@odata.id", certURI)) 31430215816SMarri Devender Rao { 31530215816SMarri Devender Rao return; 31630215816SMarri Devender Rao } 31730215816SMarri Devender Rao 31830215816SMarri Devender Rao std::string objectPath; 31930215816SMarri Devender Rao std::string service; 3200fda0f12SGeorge Liu if (boost::starts_with( 3210fda0f12SGeorge Liu certURI, 3220fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) 32330215816SMarri Devender Rao { 32430215816SMarri Devender Rao objectPath = certs::httpsObjectPath; 32530215816SMarri Devender Rao service = certs::httpsServiceName; 32630215816SMarri Devender Rao } 3273b7f0149SMarri Devender Rao else if (boost::starts_with( 328002d39b4SEd Tanous certURI, "/redfish/v1/AccountService/LDAP/Certificates")) 3293b7f0149SMarri Devender Rao { 3303b7f0149SMarri Devender Rao objectPath = certs::ldapObjectPath; 3313b7f0149SMarri Devender Rao service = certs::ldapServiceName; 3323b7f0149SMarri Devender Rao } 33330215816SMarri Devender Rao else 33430215816SMarri Devender Rao { 33530215816SMarri Devender Rao messages::actionParameterNotSupported( 33630215816SMarri Devender Rao asyncResp->res, "CertificateCollection", "GenerateCSR"); 33730215816SMarri Devender Rao return; 33830215816SMarri Devender Rao } 33930215816SMarri Devender Rao 34030215816SMarri Devender Rao // supporting only EC and RSA algorithm 3410fda0f12SGeorge Liu if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA") 34230215816SMarri Devender Rao { 34330215816SMarri Devender Rao messages::actionParameterNotSupported( 34430215816SMarri Devender Rao asyncResp->res, "KeyPairAlgorithm", "GenerateCSR"); 34530215816SMarri Devender Rao return; 34630215816SMarri Devender Rao } 34730215816SMarri Devender Rao 3487e860f15SJohn Edward Broadbent // supporting only 2048 key bit length for RSA algorithm due to 3497e860f15SJohn Edward Broadbent // time consumed in generating private key 35030215816SMarri Devender Rao if (*optKeyPairAlgorithm == "RSA" && 3512c70f800SEd Tanous *optKeyBitLength != rsaKeyBitLength) 35230215816SMarri Devender Rao { 353002d39b4SEd Tanous messages::propertyValueNotInList(asyncResp->res, 354002d39b4SEd Tanous std::to_string(*optKeyBitLength), 35530215816SMarri Devender Rao "KeyBitLength"); 35630215816SMarri Devender Rao return; 35730215816SMarri Devender Rao } 35830215816SMarri Devender Rao 35930215816SMarri Devender Rao // validate KeyUsage supporting only 1 type based on URL 3600fda0f12SGeorge Liu if (boost::starts_with( 3610fda0f12SGeorge Liu certURI, 3620fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) 36330215816SMarri Devender Rao { 36426f6976fSEd Tanous if (optKeyUsage->empty()) 36530215816SMarri Devender Rao { 36630215816SMarri Devender Rao optKeyUsage->push_back("ServerAuthentication"); 36730215816SMarri Devender Rao } 36830215816SMarri Devender Rao else if (optKeyUsage->size() == 1) 36930215816SMarri Devender Rao { 37030215816SMarri Devender Rao if ((*optKeyUsage)[0] != "ServerAuthentication") 37130215816SMarri Devender Rao { 37230215816SMarri Devender Rao messages::propertyValueNotInList( 37330215816SMarri Devender Rao asyncResp->res, (*optKeyUsage)[0], "KeyUsage"); 37430215816SMarri Devender Rao return; 37530215816SMarri Devender Rao } 37630215816SMarri Devender Rao } 37730215816SMarri Devender Rao else 37830215816SMarri Devender Rao { 37930215816SMarri Devender Rao messages::actionParameterNotSupported( 38030215816SMarri Devender Rao asyncResp->res, "KeyUsage", "GenerateCSR"); 38130215816SMarri Devender Rao return; 38230215816SMarri Devender Rao } 38330215816SMarri Devender Rao } 3843b7f0149SMarri Devender Rao else if (boost::starts_with( 385002d39b4SEd Tanous certURI, "/redfish/v1/AccountService/LDAP/Certificates")) 3863b7f0149SMarri Devender Rao { 38726f6976fSEd Tanous if (optKeyUsage->empty()) 3883b7f0149SMarri Devender Rao { 3893b7f0149SMarri Devender Rao optKeyUsage->push_back("ClientAuthentication"); 3903b7f0149SMarri Devender Rao } 3913b7f0149SMarri Devender Rao else if (optKeyUsage->size() == 1) 3923b7f0149SMarri Devender Rao { 3933b7f0149SMarri Devender Rao if ((*optKeyUsage)[0] != "ClientAuthentication") 3943b7f0149SMarri Devender Rao { 3953b7f0149SMarri Devender Rao messages::propertyValueNotInList( 3963b7f0149SMarri Devender Rao asyncResp->res, (*optKeyUsage)[0], "KeyUsage"); 3973b7f0149SMarri Devender Rao return; 3983b7f0149SMarri Devender Rao } 3993b7f0149SMarri Devender Rao } 4003b7f0149SMarri Devender Rao else 4013b7f0149SMarri Devender Rao { 4023b7f0149SMarri Devender Rao messages::actionParameterNotSupported( 4033b7f0149SMarri Devender Rao asyncResp->res, "KeyUsage", "GenerateCSR"); 4043b7f0149SMarri Devender Rao return; 4053b7f0149SMarri Devender Rao } 4063b7f0149SMarri Devender Rao } 40730215816SMarri Devender Rao 4087e860f15SJohn Edward Broadbent // Only allow one CSR matcher at a time so setting retry 4097e860f15SJohn Edward Broadbent // time-out and timer expiry to 10 seconds for now. 4102c70f800SEd Tanous static const int timeOut = 10; 41130215816SMarri Devender Rao if (csrMatcher) 41230215816SMarri Devender Rao { 413002d39b4SEd Tanous messages::serviceTemporarilyUnavailable(asyncResp->res, 414002d39b4SEd Tanous std::to_string(timeOut)); 41530215816SMarri Devender Rao return; 41630215816SMarri Devender Rao } 41730215816SMarri Devender Rao 41830215816SMarri Devender Rao // Make this static so it survives outside this method 41930215816SMarri Devender Rao static boost::asio::steady_timer timeout(*req.ioService); 4202c70f800SEd Tanous timeout.expires_after(std::chrono::seconds(timeOut)); 421002d39b4SEd Tanous timeout.async_wait([asyncResp](const boost::system::error_code& ec) { 42230215816SMarri Devender Rao csrMatcher = nullptr; 42330215816SMarri Devender Rao if (ec) 42430215816SMarri Devender Rao { 4257e860f15SJohn Edward Broadbent // operation_aborted is expected if timer is canceled 4267e860f15SJohn Edward Broadbent // before completion. 42730215816SMarri Devender Rao if (ec != boost::asio::error::operation_aborted) 42830215816SMarri Devender Rao { 42930215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Async_wait failed " << ec; 43030215816SMarri Devender Rao } 43130215816SMarri Devender Rao return; 43230215816SMarri Devender Rao } 43330215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR"; 43430215816SMarri Devender Rao messages::internalError(asyncResp->res); 43530215816SMarri Devender Rao }); 43630215816SMarri Devender Rao 43730215816SMarri Devender Rao // create a matcher to wait on CSR object 43830215816SMarri Devender Rao BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath; 4390fda0f12SGeorge Liu std::string match("type='signal'," 44030215816SMarri Devender Rao "interface='org.freedesktop.DBus.ObjectManager'," 44130215816SMarri Devender Rao "path='" + 44230215816SMarri Devender Rao objectPath + 44330215816SMarri Devender Rao "'," 44430215816SMarri Devender Rao "member='InterfacesAdded'"); 44530215816SMarri Devender Rao csrMatcher = std::make_unique<sdbusplus::bus::match::match>( 44630215816SMarri Devender Rao *crow::connections::systemBus, match, 44730215816SMarri Devender Rao [asyncResp, service, objectPath, 44830215816SMarri Devender Rao certURI](sdbusplus::message::message& m) { 449271584abSEd Tanous timeout.cancel(); 45030215816SMarri Devender Rao if (m.is_method_error()) 45130215816SMarri Devender Rao { 45230215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Dbus method error!!!"; 45330215816SMarri Devender Rao messages::internalError(asyncResp->res); 45430215816SMarri Devender Rao return; 45530215816SMarri Devender Rao } 456b9d36b47SEd Tanous 457b9d36b47SEd Tanous dbus::utility::DBusInteracesMap interfacesProperties; 458b9d36b47SEd Tanous 45930215816SMarri Devender Rao sdbusplus::message::object_path csrObjectPath; 46030215816SMarri Devender Rao m.read(csrObjectPath, interfacesProperties); 4610fda0f12SGeorge Liu BMCWEB_LOG_DEBUG << "CSR object added" << csrObjectPath.str; 46230215816SMarri Devender Rao for (auto& interface : interfacesProperties) 46330215816SMarri Devender Rao { 4640fda0f12SGeorge Liu if (interface.first == "xyz.openbmc_project.Certs.CSR") 46530215816SMarri Devender Rao { 46630215816SMarri Devender Rao getCSR(asyncResp, certURI, service, objectPath, 46730215816SMarri Devender Rao csrObjectPath.str); 46830215816SMarri Devender Rao break; 46930215816SMarri Devender Rao } 47030215816SMarri Devender Rao } 47130215816SMarri Devender Rao }); 47230215816SMarri Devender Rao crow::connections::systemBus->async_method_call( 473914e2d5dSEd Tanous [asyncResp](const boost::system::error_code ec, 474cb13a392SEd Tanous const std::string&) { 47530215816SMarri Devender Rao if (ec) 47630215816SMarri Devender Rao { 477002d39b4SEd Tanous BMCWEB_LOG_ERROR << "DBUS response error: " << ec.message(); 47830215816SMarri Devender Rao messages::internalError(asyncResp->res); 47930215816SMarri Devender Rao return; 48030215816SMarri Devender Rao } 48130215816SMarri Devender Rao }, 48230215816SMarri Devender Rao service, objectPath, "xyz.openbmc_project.Certs.CSR.Create", 483002d39b4SEd Tanous "GenerateCSR", *optAlternativeNames, *optChallengePassword, city, 484002d39b4SEd Tanous commonName, *optContactPerson, country, *optEmail, *optGivenName, 485002d39b4SEd Tanous *optInitials, *optKeyBitLength, *optKeyCurveId, 4860fda0f12SGeorge Liu *optKeyPairAlgorithm, *optKeyUsage, organization, 4870fda0f12SGeorge Liu organizationalUnit, state, *optSurname, *optUnstructuredName); 4887e860f15SJohn Edward Broadbent }); 4897e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionGenerateCSR 49030215816SMarri Devender Rao 4915968caeeSMarri Devender Rao /** 4924e0453b1SGunnar Mills * @brief Parse and update Certificate Issue/Subject property 4935968caeeSMarri Devender Rao * 4945968caeeSMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 4955968caeeSMarri Devender Rao * @param[in] str Issuer/Subject value in key=value pairs 4965968caeeSMarri Devender Rao * @param[in] type Issuer/Subject 4975968caeeSMarri Devender Rao * @return None 4985968caeeSMarri Devender Rao */ 4995968caeeSMarri Devender Rao static void updateCertIssuerOrSubject(nlohmann::json& out, 5005968caeeSMarri Devender Rao const std::string_view value) 5015968caeeSMarri Devender Rao { 5025968caeeSMarri Devender Rao // example: O=openbmc-project.xyz,CN=localhost 5035968caeeSMarri Devender Rao std::string_view::iterator i = value.begin(); 5045968caeeSMarri Devender Rao while (i != value.end()) 5055968caeeSMarri Devender Rao { 5065968caeeSMarri Devender Rao std::string_view::iterator tokenBegin = i; 5075968caeeSMarri Devender Rao while (i != value.end() && *i != '=') 5085968caeeSMarri Devender Rao { 50917a897dfSManojkiran Eda ++i; 5105968caeeSMarri Devender Rao } 5115968caeeSMarri Devender Rao if (i == value.end()) 5125968caeeSMarri Devender Rao { 5135968caeeSMarri Devender Rao break; 5145968caeeSMarri Devender Rao } 515271584abSEd Tanous const std::string_view key(tokenBegin, 516271584abSEd Tanous static_cast<size_t>(i - tokenBegin)); 51717a897dfSManojkiran Eda ++i; 5185968caeeSMarri Devender Rao tokenBegin = i; 5195968caeeSMarri Devender Rao while (i != value.end() && *i != ',') 5205968caeeSMarri Devender Rao { 52117a897dfSManojkiran Eda ++i; 5225968caeeSMarri Devender Rao } 523271584abSEd Tanous const std::string_view val(tokenBegin, 524271584abSEd Tanous static_cast<size_t>(i - tokenBegin)); 5255968caeeSMarri Devender Rao if (key == "L") 5265968caeeSMarri Devender Rao { 5275968caeeSMarri Devender Rao out["City"] = val; 5285968caeeSMarri Devender Rao } 5295968caeeSMarri Devender Rao else if (key == "CN") 5305968caeeSMarri Devender Rao { 5315968caeeSMarri Devender Rao out["CommonName"] = val; 5325968caeeSMarri Devender Rao } 5335968caeeSMarri Devender Rao else if (key == "C") 5345968caeeSMarri Devender Rao { 5355968caeeSMarri Devender Rao out["Country"] = val; 5365968caeeSMarri Devender Rao } 5375968caeeSMarri Devender Rao else if (key == "O") 5385968caeeSMarri Devender Rao { 5395968caeeSMarri Devender Rao out["Organization"] = val; 5405968caeeSMarri Devender Rao } 5415968caeeSMarri Devender Rao else if (key == "OU") 5425968caeeSMarri Devender Rao { 5435968caeeSMarri Devender Rao out["OrganizationalUnit"] = val; 5445968caeeSMarri Devender Rao } 5455968caeeSMarri Devender Rao else if (key == "ST") 5465968caeeSMarri Devender Rao { 5475968caeeSMarri Devender Rao out["State"] = val; 5485968caeeSMarri Devender Rao } 5495968caeeSMarri Devender Rao // skip comma character 5505968caeeSMarri Devender Rao if (i != value.end()) 5515968caeeSMarri Devender Rao { 55217a897dfSManojkiran Eda ++i; 5535968caeeSMarri Devender Rao } 5545968caeeSMarri Devender Rao } 5555968caeeSMarri Devender Rao } 5565968caeeSMarri Devender Rao 5575968caeeSMarri Devender Rao /** 5585968caeeSMarri Devender Rao * @brief Retrieve the certificates properties and append to the response 5595968caeeSMarri Devender Rao * message 5605968caeeSMarri Devender Rao * 5615968caeeSMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 5625968caeeSMarri Devender Rao * @param[in] objectPath Path of the D-Bus service object 5635968caeeSMarri Devender Rao * @param[in] certId Id of the certificate 5645968caeeSMarri Devender Rao * @param[in] certURL URL of the certificate object 5655968caeeSMarri Devender Rao * @param[in] name name of the certificate 5665968caeeSMarri Devender Rao * @return None 5675968caeeSMarri Devender Rao */ 5685968caeeSMarri Devender Rao static void getCertificateProperties( 5698d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 5708d1b46d7Szhanghch05 const std::string& objectPath, const std::string& service, long certId, 5718d1b46d7Szhanghch05 const std::string& certURL, const std::string& name) 5725968caeeSMarri Devender Rao { 5735968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "getCertificateProperties Path=" << objectPath 5745968caeeSMarri Devender Rao << " certId=" << certId << " certURl=" << certURL; 5755968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 576b9d36b47SEd Tanous [asyncResp, certURL, certId, 577b9d36b47SEd Tanous name](const boost::system::error_code ec, 578b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& properties) { 5795968caeeSMarri Devender Rao if (ec) 5805968caeeSMarri Devender Rao { 5815968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 5828aae75adSMarri Devender Rao messages::resourceNotFound(asyncResp->res, name, 5838aae75adSMarri Devender Rao std::to_string(certId)); 5845968caeeSMarri Devender Rao return; 5855968caeeSMarri Devender Rao } 5861476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = certURL; 5871476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 5881476687dSEd Tanous "#Certificate.v1_0_0.Certificate"; 5891476687dSEd Tanous asyncResp->res.jsonValue["Id"] = std::to_string(certId); 5901476687dSEd Tanous asyncResp->res.jsonValue["Name"] = name; 5911476687dSEd Tanous asyncResp->res.jsonValue["Description"] = name; 5925968caeeSMarri Devender Rao for (const auto& property : properties) 5935968caeeSMarri Devender Rao { 5945968caeeSMarri Devender Rao if (property.first == "CertificateString") 5955968caeeSMarri Devender Rao { 5965968caeeSMarri Devender Rao asyncResp->res.jsonValue["CertificateString"] = ""; 5975968caeeSMarri Devender Rao const std::string* value = 5985968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 599e662eae8SEd Tanous if (value != nullptr) 6005968caeeSMarri Devender Rao { 60137cce918SMarri Devender Rao asyncResp->res.jsonValue["CertificateString"] = *value; 6025968caeeSMarri Devender Rao } 6035968caeeSMarri Devender Rao } 6045968caeeSMarri Devender Rao else if (property.first == "KeyUsage") 6055968caeeSMarri Devender Rao { 606002d39b4SEd Tanous nlohmann::json& keyUsage = asyncResp->res.jsonValue["KeyUsage"]; 6075968caeeSMarri Devender Rao keyUsage = nlohmann::json::array(); 6085968caeeSMarri Devender Rao const std::vector<std::string>* value = 60937cce918SMarri Devender Rao std::get_if<std::vector<std::string>>(&property.second); 610e662eae8SEd Tanous if (value != nullptr) 6115968caeeSMarri Devender Rao { 6125968caeeSMarri Devender Rao for (const std::string& usage : *value) 6135968caeeSMarri Devender Rao { 6145968caeeSMarri Devender Rao keyUsage.push_back(usage); 6155968caeeSMarri Devender Rao } 6165968caeeSMarri Devender Rao } 6175968caeeSMarri Devender Rao } 6185968caeeSMarri Devender Rao else if (property.first == "Issuer") 6195968caeeSMarri Devender Rao { 6205968caeeSMarri Devender Rao const std::string* value = 6215968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 622e662eae8SEd Tanous if (value != nullptr) 6235968caeeSMarri Devender Rao { 6245968caeeSMarri Devender Rao updateCertIssuerOrSubject( 6255968caeeSMarri Devender Rao asyncResp->res.jsonValue["Issuer"], *value); 6265968caeeSMarri Devender Rao } 6275968caeeSMarri Devender Rao } 6285968caeeSMarri Devender Rao else if (property.first == "Subject") 6295968caeeSMarri Devender Rao { 6305968caeeSMarri Devender Rao const std::string* value = 6315968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 632e662eae8SEd Tanous if (value != nullptr) 6335968caeeSMarri Devender Rao { 6345968caeeSMarri Devender Rao updateCertIssuerOrSubject( 63537cce918SMarri Devender Rao asyncResp->res.jsonValue["Subject"], *value); 6365968caeeSMarri Devender Rao } 6375968caeeSMarri Devender Rao } 6385968caeeSMarri Devender Rao else if (property.first == "ValidNotAfter") 6395968caeeSMarri Devender Rao { 640002d39b4SEd Tanous const uint64_t* value = std::get_if<uint64_t>(&property.second); 641e662eae8SEd Tanous if (value != nullptr) 6425968caeeSMarri Devender Rao { 6435968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotAfter"] = 6441d8782e7SNan Zhou crow::utility::getDateTimeUint(*value); 6455968caeeSMarri Devender Rao } 6465968caeeSMarri Devender Rao } 6475968caeeSMarri Devender Rao else if (property.first == "ValidNotBefore") 6485968caeeSMarri Devender Rao { 649002d39b4SEd Tanous const uint64_t* value = std::get_if<uint64_t>(&property.second); 650e662eae8SEd Tanous if (value != nullptr) 6515968caeeSMarri Devender Rao { 6525968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotBefore"] = 6531d8782e7SNan Zhou crow::utility::getDateTimeUint(*value); 6545968caeeSMarri Devender Rao } 6555968caeeSMarri Devender Rao } 6565968caeeSMarri Devender Rao } 6575968caeeSMarri Devender Rao asyncResp->res.addHeader("Location", certURL); 6585968caeeSMarri Devender Rao }, 6595968caeeSMarri Devender Rao service, objectPath, certs::dbusPropIntf, "GetAll", 6605968caeeSMarri Devender Rao certs::certPropIntf); 6615968caeeSMarri Devender Rao } 6625968caeeSMarri Devender Rao 6635968caeeSMarri Devender Rao /** 6645968caeeSMarri Devender Rao * Action to replace an existing certificate 6655968caeeSMarri Devender Rao */ 6667e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionsReplaceCertificate(App& app) 6675968caeeSMarri Devender Rao { 6680fda0f12SGeorge Liu BMCWEB_ROUTE( 6690fda0f12SGeorge Liu app, 6700fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate/") 671ed398213SEd Tanous .privileges(redfish::privileges::postCertificateService) 672002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 673002d39b4SEd Tanous [&app](const crow::Request& req, 6747e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 675*3ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 67645ca1b86SEd Tanous { 67745ca1b86SEd Tanous return; 67845ca1b86SEd Tanous } 6795968caeeSMarri Devender Rao std::string certificate; 6805968caeeSMarri Devender Rao nlohmann::json certificateUri; 6815968caeeSMarri Devender Rao std::optional<std::string> certificateType = "PEM"; 6828d1b46d7Szhanghch05 683002d39b4SEd Tanous if (!json_util::readJsonAction(req, asyncResp->res, "CertificateString", 684002d39b4SEd Tanous certificate, "CertificateUri", 685002d39b4SEd Tanous certificateUri, "CertificateType", 686002d39b4SEd Tanous certificateType)) 6875968caeeSMarri Devender Rao { 6885968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Required parameters are missing"; 6895968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 6905968caeeSMarri Devender Rao return; 6915968caeeSMarri Devender Rao } 6925968caeeSMarri Devender Rao 6935968caeeSMarri Devender Rao if (!certificateType) 6945968caeeSMarri Devender Rao { 6955968caeeSMarri Devender Rao // should never happen, but it never hurts to be paranoid. 6965968caeeSMarri Devender Rao return; 6975968caeeSMarri Devender Rao } 6985968caeeSMarri Devender Rao if (certificateType != "PEM") 6995968caeeSMarri Devender Rao { 7005968caeeSMarri Devender Rao messages::actionParameterNotSupported( 7015968caeeSMarri Devender Rao asyncResp->res, "CertificateType", "ReplaceCertificate"); 7025968caeeSMarri Devender Rao return; 7035968caeeSMarri Devender Rao } 7045968caeeSMarri Devender Rao 7055968caeeSMarri Devender Rao std::string certURI; 7065968caeeSMarri Devender Rao if (!redfish::json_util::readJson(certificateUri, asyncResp->res, 7075968caeeSMarri Devender Rao "@odata.id", certURI)) 7085968caeeSMarri Devender Rao { 7095968caeeSMarri Devender Rao messages::actionParameterMissing( 7105968caeeSMarri Devender Rao asyncResp->res, "ReplaceCertificate", "CertificateUri"); 7115968caeeSMarri Devender Rao return; 7125968caeeSMarri Devender Rao } 7135968caeeSMarri Devender Rao 7145968caeeSMarri Devender Rao BMCWEB_LOG_INFO << "Certificate URI to replace" << certURI; 7155968caeeSMarri Devender Rao long id = getIDFromURL(certURI); 7165968caeeSMarri Devender Rao if (id < 0) 7175968caeeSMarri Devender Rao { 718002d39b4SEd Tanous messages::actionParameterValueFormatError(asyncResp->res, certURI, 719002d39b4SEd Tanous "CertificateUri", 7205968caeeSMarri Devender Rao "ReplaceCertificate"); 7215968caeeSMarri Devender Rao return; 7225968caeeSMarri Devender Rao } 7235968caeeSMarri Devender Rao std::string objectPath; 7245968caeeSMarri Devender Rao std::string name; 72537cce918SMarri Devender Rao std::string service; 7260fda0f12SGeorge Liu if (boost::starts_with( 7270fda0f12SGeorge Liu certURI, 7280fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")) 7295968caeeSMarri Devender Rao { 730002d39b4SEd Tanous objectPath = 731002d39b4SEd Tanous std::string(certs::httpsObjectPath) + "/" + std::to_string(id); 7325968caeeSMarri Devender Rao name = "HTTPS certificate"; 73337cce918SMarri Devender Rao service = certs::httpsServiceName; 73437cce918SMarri Devender Rao } 73537cce918SMarri Devender Rao else if (boost::starts_with( 736002d39b4SEd Tanous certURI, "/redfish/v1/AccountService/LDAP/Certificates/")) 73737cce918SMarri Devender Rao { 738002d39b4SEd Tanous objectPath = 739002d39b4SEd Tanous std::string(certs::ldapObjectPath) + "/" + std::to_string(id); 74037cce918SMarri Devender Rao name = "LDAP certificate"; 74137cce918SMarri Devender Rao service = certs::ldapServiceName; 7425968caeeSMarri Devender Rao } 743cfcd5f6bSMarri Devender Rao else if (boost::starts_with( 744cfcd5f6bSMarri Devender Rao certURI, 745cfcd5f6bSMarri Devender Rao "/redfish/v1/Managers/bmc/Truststore/Certificates/")) 746cfcd5f6bSMarri Devender Rao { 747cfcd5f6bSMarri Devender Rao objectPath = std::string(certs::authorityObjectPath) + "/" + 748cfcd5f6bSMarri Devender Rao std::to_string(id); 749cfcd5f6bSMarri Devender Rao name = "TrustStore certificate"; 750cfcd5f6bSMarri Devender Rao service = certs::authorityServiceName; 751cfcd5f6bSMarri Devender Rao } 7525968caeeSMarri Devender Rao else 7535968caeeSMarri Devender Rao { 7545968caeeSMarri Devender Rao messages::actionParameterNotSupported( 7555968caeeSMarri Devender Rao asyncResp->res, "CertificateUri", "ReplaceCertificate"); 7565968caeeSMarri Devender Rao return; 7575968caeeSMarri Devender Rao } 7585968caeeSMarri Devender Rao 7595968caeeSMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 7605968caeeSMarri Devender Rao std::make_shared<CertificateFile>(certificate); 7615968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 76237cce918SMarri Devender Rao [asyncResp, certFile, objectPath, service, certURI, id, 7635968caeeSMarri Devender Rao name](const boost::system::error_code ec) { 7645968caeeSMarri Devender Rao if (ec) 7655968caeeSMarri Devender Rao { 7665968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 76790d2d1e8SJiaqing Zhao if (ec.value() == 76890d2d1e8SJiaqing Zhao boost::system::linux_error::bad_request_descriptor) 76990d2d1e8SJiaqing Zhao { 7708aae75adSMarri Devender Rao messages::resourceNotFound(asyncResp->res, name, 7718aae75adSMarri Devender Rao std::to_string(id)); 7725968caeeSMarri Devender Rao return; 7735968caeeSMarri Devender Rao } 77490d2d1e8SJiaqing Zhao messages::internalError(asyncResp->res); 77590d2d1e8SJiaqing Zhao return; 77690d2d1e8SJiaqing Zhao } 77737cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, service, id, 7785968caeeSMarri Devender Rao certURI, name); 7795968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" 7805968caeeSMarri Devender Rao << certFile->getCertFilePath(); 7815968caeeSMarri Devender Rao }, 7825968caeeSMarri Devender Rao service, objectPath, certs::certReplaceIntf, "Replace", 7835968caeeSMarri Devender Rao certFile->getCertFilePath()); 7847e860f15SJohn Edward Broadbent }); 7857e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionsReplaceCertificate 7865968caeeSMarri Devender Rao 7875968caeeSMarri Devender Rao /** 7885968caeeSMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 7895968caeeSMarri Devender Rao * of a component, account or service. 7905968caeeSMarri Devender Rao */ 7915968caeeSMarri Devender Rao 7927e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificate(App& app) 7935968caeeSMarri Devender Rao { 7947e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 7957e860f15SJohn Edward Broadbent app, 7967e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/<str>/") 797ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 7987e860f15SJohn Edward Broadbent .methods( 7997e860f15SJohn Edward Broadbent boost::beast::http::verb:: 80045ca1b86SEd Tanous get)([&app](const crow::Request& req, 8017e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 8027e860f15SJohn Edward Broadbent const std::string& param) -> void { 803*3ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 80445ca1b86SEd Tanous { 80545ca1b86SEd Tanous return; 80645ca1b86SEd Tanous } 8077e860f15SJohn Edward Broadbent if (param.empty()) 8085968caeeSMarri Devender Rao { 8095968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 8105968caeeSMarri Devender Rao return; 8115968caeeSMarri Devender Rao } 8125968caeeSMarri Devender Rao long id = getIDFromURL(req.url); 8135968caeeSMarri Devender Rao 8147e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG << "HTTPSCertificate::doGet ID=" 8157e860f15SJohn Edward Broadbent << std::to_string(id); 8165968caeeSMarri Devender Rao std::string certURL = 8175968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" + 8185968caeeSMarri Devender Rao std::to_string(id); 8195968caeeSMarri Devender Rao std::string objectPath = certs::httpsObjectPath; 8205968caeeSMarri Devender Rao objectPath += "/"; 8215968caeeSMarri Devender Rao objectPath += std::to_string(id); 8227e860f15SJohn Edward Broadbent getCertificateProperties(asyncResp, objectPath, 8237e860f15SJohn Edward Broadbent certs::httpsServiceName, id, certURL, 8247e860f15SJohn Edward Broadbent "HTTPS Certificate"); 8257e860f15SJohn Edward Broadbent }); 8265968caeeSMarri Devender Rao } 8275968caeeSMarri Devender Rao 8285968caeeSMarri Devender Rao /** 8295968caeeSMarri Devender Rao * Collection of HTTPS certificates 8305968caeeSMarri Devender Rao */ 8317e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificateCollection(App& app) 8325968caeeSMarri Devender Rao { 8337e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 8345968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/") 835ed398213SEd Tanous .privileges(redfish::privileges::getCertificateCollection) 836002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 837002d39b4SEd Tanous [&app](const crow::Request& req, 838002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 839*3ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 84045ca1b86SEd Tanous { 84145ca1b86SEd Tanous return; 84245ca1b86SEd Tanous } 8431476687dSEd Tanous 8441476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 8451476687dSEd Tanous "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"; 8461476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 8471476687dSEd Tanous "#CertificateCollection.CertificateCollection"; 8481476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "HTTPS Certificates Collection"; 8491476687dSEd Tanous asyncResp->res.jsonValue["Description"] = 8501476687dSEd Tanous "A Collection of HTTPS certificate instances"; 8518d1b46d7Szhanghch05 8525968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 8535968caeeSMarri Devender Rao [asyncResp](const boost::system::error_code ec, 854711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& certs) { 8555968caeeSMarri Devender Rao if (ec) 8565968caeeSMarri Devender Rao { 8575968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 8585968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 8595968caeeSMarri Devender Rao return; 8605968caeeSMarri Devender Rao } 861002d39b4SEd Tanous nlohmann::json& members = asyncResp->res.jsonValue["Members"]; 8625968caeeSMarri Devender Rao members = nlohmann::json::array(); 8635968caeeSMarri Devender Rao for (const auto& cert : certs) 8645968caeeSMarri Devender Rao { 8655968caeeSMarri Devender Rao long id = getIDFromURL(cert.first.str); 86637cce918SMarri Devender Rao if (id >= 0) 8675968caeeSMarri Devender Rao { 8681476687dSEd Tanous nlohmann::json::object_t member; 8691476687dSEd Tanous member["@odata.id"] = 8700fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" + 8711476687dSEd Tanous std::to_string(id); 8721476687dSEd Tanous members.push_back(std::move(member)); 8735968caeeSMarri Devender Rao } 8745968caeeSMarri Devender Rao } 875002d39b4SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = members.size(); 8765968caeeSMarri Devender Rao }, 87737cce918SMarri Devender Rao certs::httpsServiceName, certs::httpsObjectPath, 87837cce918SMarri Devender Rao certs::dbusObjManagerIntf, "GetManagedObjects"); 8797e860f15SJohn Edward Broadbent }); 8805968caeeSMarri Devender Rao 8817e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 8827e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/") 883ed398213SEd Tanous .privileges(redfish::privileges::postCertificateCollection) 884002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 885002d39b4SEd Tanous [&app](const crow::Request& req, 8867e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 887*3ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 88845ca1b86SEd Tanous { 88945ca1b86SEd Tanous return; 89045ca1b86SEd Tanous } 8915968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost"; 8928d1b46d7Szhanghch05 8931476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "HTTPS Certificate"; 8941476687dSEd Tanous asyncResp->res.jsonValue["Description"] = "HTTPS Certificate"; 8955968caeeSMarri Devender Rao 896002d39b4SEd Tanous std::string certFileBody = getCertificateFromReqBody(asyncResp, req); 89758eb238fSKowalski, Kamil 89858eb238fSKowalski, Kamil if (certFileBody.empty()) 89958eb238fSKowalski, Kamil { 9000fda0f12SGeorge Liu BMCWEB_LOG_ERROR << "Cannot get certificate from request body."; 901a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 90258eb238fSKowalski, Kamil return; 90358eb238fSKowalski, Kamil } 90458eb238fSKowalski, Kamil 9055968caeeSMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 90658eb238fSKowalski, Kamil std::make_shared<CertificateFile>(certFileBody); 9075968caeeSMarri Devender Rao 9085968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 909656ec7e3SZbigniew Kurzynski [asyncResp, certFile](const boost::system::error_code ec, 910656ec7e3SZbigniew Kurzynski const std::string& objectPath) { 9115968caeeSMarri Devender Rao if (ec) 9125968caeeSMarri Devender Rao { 9135968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 9145968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 9155968caeeSMarri Devender Rao return; 9165968caeeSMarri Devender Rao } 917656ec7e3SZbigniew Kurzynski long certId = getIDFromURL(objectPath); 918656ec7e3SZbigniew Kurzynski if (certId < 0) 919656ec7e3SZbigniew Kurzynski { 920002d39b4SEd Tanous BMCWEB_LOG_ERROR << "Invalid objectPath value" << objectPath; 921656ec7e3SZbigniew Kurzynski messages::internalError(asyncResp->res); 922656ec7e3SZbigniew Kurzynski return; 923656ec7e3SZbigniew Kurzynski } 9245968caeeSMarri Devender Rao std::string certURL = 9250fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" + 9265968caeeSMarri Devender Rao std::to_string(certId); 9270fda0f12SGeorge Liu getCertificateProperties(asyncResp, objectPath, 928002d39b4SEd Tanous certs::httpsServiceName, certId, certURL, 929002d39b4SEd Tanous "HTTPS Certificate"); 9305968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" 9315968caeeSMarri Devender Rao << certFile->getCertFilePath(); 9325968caeeSMarri Devender Rao }, 93337cce918SMarri Devender Rao certs::httpsServiceName, certs::httpsObjectPath, 9340fda0f12SGeorge Liu certs::certInstallIntf, "Install", certFile->getCertFilePath()); 9357e860f15SJohn Edward Broadbent }); 9367e860f15SJohn Edward Broadbent } // requestRoutesHTTPSCertificateCollection 9375968caeeSMarri Devender Rao 9385968caeeSMarri Devender Rao /** 93937cce918SMarri Devender Rao * @brief Retrieve the certificates installed list and append to the 94037cce918SMarri Devender Rao * response 94137cce918SMarri Devender Rao * 94237cce918SMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 94337cce918SMarri Devender Rao * @param[in] certURL Path of the certificate object 94437cce918SMarri Devender Rao * @param[in] path Path of the D-Bus service object 94537cce918SMarri Devender Rao * @return None 94637cce918SMarri Devender Rao */ 9474f48d5f6SEd Tanous inline void 9484f48d5f6SEd Tanous getCertificateLocations(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 9498d1b46d7Szhanghch05 const std::string& certURL, const std::string& path, 95037cce918SMarri Devender Rao const std::string& service) 95137cce918SMarri Devender Rao { 95237cce918SMarri Devender Rao BMCWEB_LOG_DEBUG << "getCertificateLocations URI=" << certURL 95337cce918SMarri Devender Rao << " Path=" << path << " service= " << service; 95437cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 95537cce918SMarri Devender Rao [asyncResp, certURL](const boost::system::error_code ec, 956711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& certs) { 95737cce918SMarri Devender Rao if (ec) 95837cce918SMarri Devender Rao { 959002d39b4SEd Tanous BMCWEB_LOG_WARNING << "Certificate collection query failed: " << ec 9609c8e039eSJonathan Doman << ", skipping " << certURL; 96137cce918SMarri Devender Rao return; 96237cce918SMarri Devender Rao } 96337cce918SMarri Devender Rao nlohmann::json& links = 96437cce918SMarri Devender Rao asyncResp->res.jsonValue["Links"]["Certificates"]; 9659eb808c1SEd Tanous for (const auto& cert : certs) 96637cce918SMarri Devender Rao { 96737cce918SMarri Devender Rao long id = getIDFromURL(cert.first.str); 96837cce918SMarri Devender Rao if (id >= 0) 96937cce918SMarri Devender Rao { 9701476687dSEd Tanous nlohmann::json::object_t link; 9711476687dSEd Tanous link["@odata.id"] = certURL + std::to_string(id); 9721476687dSEd Tanous links.push_back(std::move(link)); 97337cce918SMarri Devender Rao } 97437cce918SMarri Devender Rao } 97537cce918SMarri Devender Rao asyncResp->res.jsonValue["Links"]["Certificates@odata.count"] = 97637cce918SMarri Devender Rao links.size(); 97737cce918SMarri Devender Rao }, 97837cce918SMarri Devender Rao service, path, certs::dbusObjManagerIntf, "GetManagedObjects"); 9795968caeeSMarri Devender Rao } 9807e860f15SJohn Edward Broadbent 9817e860f15SJohn Edward Broadbent /** 9827e860f15SJohn Edward Broadbent * The certificate location schema defines a resource that an administrator 9837e860f15SJohn Edward Broadbent * can use in order to locate all certificates installed on a given service. 9847e860f15SJohn Edward Broadbent */ 9857e860f15SJohn Edward Broadbent inline void requestRoutesCertificateLocations(App& app) 9867e860f15SJohn Edward Broadbent { 9877e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/") 988ed398213SEd Tanous .privileges(redfish::privileges::getCertificateLocations) 989002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 990002d39b4SEd Tanous [&app](const crow::Request& req, 991002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 992*3ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 99345ca1b86SEd Tanous { 99445ca1b86SEd Tanous return; 99545ca1b86SEd Tanous } 9961476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 9971476687dSEd Tanous "/redfish/v1/CertificateService/CertificateLocations"; 9981476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 9991476687dSEd Tanous "#CertificateLocations.v1_0_0.CertificateLocations"; 10001476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "Certificate Locations"; 10011476687dSEd Tanous asyncResp->res.jsonValue["Id"] = "CertificateLocations"; 10021476687dSEd Tanous asyncResp->res.jsonValue["Description"] = 10037e860f15SJohn Edward Broadbent "Defines a resource that an administrator can use in order to " 10041476687dSEd Tanous "locate all certificates installed on a given service"; 10057e860f15SJohn Edward Broadbent 10067e860f15SJohn Edward Broadbent nlohmann::json& links = 10077e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Links"]["Certificates"]; 10087e860f15SJohn Edward Broadbent links = nlohmann::json::array(); 10097e860f15SJohn Edward Broadbent getCertificateLocations( 10107e860f15SJohn Edward Broadbent asyncResp, 10117e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/", 10127e860f15SJohn Edward Broadbent certs::httpsObjectPath, certs::httpsServiceName); 1013002d39b4SEd Tanous getCertificateLocations(asyncResp, 1014002d39b4SEd Tanous "/redfish/v1/AccountService/LDAP/Certificates/", 10157e860f15SJohn Edward Broadbent certs::ldapObjectPath, certs::ldapServiceName); 10167e860f15SJohn Edward Broadbent getCertificateLocations( 10177e860f15SJohn Edward Broadbent asyncResp, "/redfish/v1/Managers/bmc/Truststore/Certificates/", 10187e860f15SJohn Edward Broadbent certs::authorityObjectPath, certs::authorityServiceName); 10197e860f15SJohn Edward Broadbent }); 10207e860f15SJohn Edward Broadbent } 10217e860f15SJohn Edward Broadbent // requestRoutesCertificateLocations 102237cce918SMarri Devender Rao 102337cce918SMarri Devender Rao /** 102437cce918SMarri Devender Rao * Collection of LDAP certificates 102537cce918SMarri Devender Rao */ 10267e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificateCollection(App& app) 102737cce918SMarri Devender Rao { 10287e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/") 1029ed398213SEd Tanous .privileges(redfish::privileges::getCertificateCollection) 1030002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1031002d39b4SEd Tanous [&app](const crow::Request& req, 1032002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 1033*3ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 103445ca1b86SEd Tanous { 103545ca1b86SEd Tanous return; 103645ca1b86SEd Tanous } 10371476687dSEd Tanous 10381476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 10391476687dSEd Tanous "/redfish/v1/AccountService/LDAP/Certificates"; 10401476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 10411476687dSEd Tanous "#CertificateCollection.CertificateCollection"; 10421476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "LDAP Certificates Collection"; 10431476687dSEd Tanous asyncResp->res.jsonValue["Description"] = 10441476687dSEd Tanous "A Collection of LDAP certificate instances"; 10458d1b46d7Szhanghch05 104637cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 104737cce918SMarri Devender Rao [asyncResp](const boost::system::error_code ec, 1048711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& certs) { 1049002d39b4SEd Tanous nlohmann::json& members = asyncResp->res.jsonValue["Members"]; 10509c8e039eSJonathan Doman nlohmann::json& count = 10519c8e039eSJonathan Doman asyncResp->res.jsonValue["Members@odata.count"]; 10529c8e039eSJonathan Doman members = nlohmann::json::array(); 10539c8e039eSJonathan Doman count = 0; 105437cce918SMarri Devender Rao if (ec) 105537cce918SMarri Devender Rao { 1056002d39b4SEd Tanous BMCWEB_LOG_WARNING << "LDAP certificate query failed: " << ec; 105737cce918SMarri Devender Rao return; 105837cce918SMarri Devender Rao } 105937cce918SMarri Devender Rao for (const auto& cert : certs) 106037cce918SMarri Devender Rao { 106137cce918SMarri Devender Rao long id = getIDFromURL(cert.first.str); 106237cce918SMarri Devender Rao if (id >= 0) 106337cce918SMarri Devender Rao { 10641476687dSEd Tanous nlohmann::json::object_t member; 10651476687dSEd Tanous member["@odata.id"] = 10660fda0f12SGeorge Liu "/redfish/v1/AccountService/LDAP/Certificates/" + 10671476687dSEd Tanous std::to_string(id); 10681476687dSEd Tanous members.push_back(std::move(member)); 106937cce918SMarri Devender Rao } 107037cce918SMarri Devender Rao } 10719c8e039eSJonathan Doman count = members.size(); 107237cce918SMarri Devender Rao }, 107337cce918SMarri Devender Rao certs::ldapServiceName, certs::ldapObjectPath, 107437cce918SMarri Devender Rao certs::dbusObjManagerIntf, "GetManagedObjects"); 10757e860f15SJohn Edward Broadbent }); 107637cce918SMarri Devender Rao 10777e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/") 1078ed398213SEd Tanous .privileges(redfish::privileges::postCertificateCollection) 10797e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 108045ca1b86SEd Tanous [&app](const crow::Request& req, 10817e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 1082*3ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 108345ca1b86SEd Tanous { 108445ca1b86SEd Tanous return; 108545ca1b86SEd Tanous } 1086002d39b4SEd Tanous std::string certFileBody = getCertificateFromReqBody(asyncResp, req); 108758eb238fSKowalski, Kamil 108858eb238fSKowalski, Kamil if (certFileBody.empty()) 108958eb238fSKowalski, Kamil { 1090002d39b4SEd Tanous BMCWEB_LOG_ERROR << "Cannot get certificate from request body."; 1091a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 109258eb238fSKowalski, Kamil return; 109358eb238fSKowalski, Kamil } 109458eb238fSKowalski, Kamil 109558eb238fSKowalski, Kamil std::shared_ptr<CertificateFile> certFile = 109658eb238fSKowalski, Kamil std::make_shared<CertificateFile>(certFileBody); 109758eb238fSKowalski, Kamil 109837cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 1099656ec7e3SZbigniew Kurzynski [asyncResp, certFile](const boost::system::error_code ec, 1100656ec7e3SZbigniew Kurzynski const std::string& objectPath) { 110137cce918SMarri Devender Rao if (ec) 110237cce918SMarri Devender Rao { 110337cce918SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 110437cce918SMarri Devender Rao messages::internalError(asyncResp->res); 110537cce918SMarri Devender Rao return; 110637cce918SMarri Devender Rao } 1107656ec7e3SZbigniew Kurzynski long certId = getIDFromURL(objectPath); 1108656ec7e3SZbigniew Kurzynski if (certId < 0) 1109656ec7e3SZbigniew Kurzynski { 1110002d39b4SEd Tanous BMCWEB_LOG_ERROR << "Invalid objectPath value" << objectPath; 1111656ec7e3SZbigniew Kurzynski messages::internalError(asyncResp->res); 1112656ec7e3SZbigniew Kurzynski return; 1113656ec7e3SZbigniew Kurzynski } 111437cce918SMarri Devender Rao std::string certURL = 111537cce918SMarri Devender Rao "/redfish/v1/AccountService/LDAP/Certificates/" + 111637cce918SMarri Devender Rao std::to_string(certId); 111737cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, 1118002d39b4SEd Tanous certs::ldapServiceName, certId, certURL, 1119002d39b4SEd Tanous "LDAP Certificate"); 112037cce918SMarri Devender Rao BMCWEB_LOG_DEBUG << "LDAP certificate install file=" 112137cce918SMarri Devender Rao << certFile->getCertFilePath(); 112237cce918SMarri Devender Rao }, 112337cce918SMarri Devender Rao certs::ldapServiceName, certs::ldapObjectPath, 1124002d39b4SEd Tanous certs::certInstallIntf, "Install", certFile->getCertFilePath()); 11257e860f15SJohn Edward Broadbent }); 11267e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificateCollection 112737cce918SMarri Devender Rao 112837cce918SMarri Devender Rao /** 112937cce918SMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 113037cce918SMarri Devender Rao * of a component, account or service. 113137cce918SMarri Devender Rao */ 11327e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificate(App& app) 113337cce918SMarri Devender Rao { 11347e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/") 1135ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 11367e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 113745ca1b86SEd Tanous [&app](const crow::Request& req, 11387e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 11397e860f15SJohn Edward Broadbent const std::string&) { 1140*3ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 114145ca1b86SEd Tanous { 114245ca1b86SEd Tanous return; 114345ca1b86SEd Tanous } 114437cce918SMarri Devender Rao long id = getIDFromURL(req.url); 114537cce918SMarri Devender Rao if (id < 0) 114637cce918SMarri Devender Rao { 114737cce918SMarri Devender Rao BMCWEB_LOG_ERROR << "Invalid url value" << req.url; 114837cce918SMarri Devender Rao messages::internalError(asyncResp->res); 114937cce918SMarri Devender Rao return; 115037cce918SMarri Devender Rao } 1151002d39b4SEd Tanous BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" << std::to_string(id); 1152002d39b4SEd Tanous std::string certURL = "/redfish/v1/AccountService/LDAP/Certificates/" + 115337cce918SMarri Devender Rao std::to_string(id); 115437cce918SMarri Devender Rao std::string objectPath = certs::ldapObjectPath; 115537cce918SMarri Devender Rao objectPath += "/"; 115637cce918SMarri Devender Rao objectPath += std::to_string(id); 1157002d39b4SEd Tanous getCertificateProperties(asyncResp, objectPath, certs::ldapServiceName, 1158002d39b4SEd Tanous id, certURL, "LDAP Certificate"); 11597e860f15SJohn Edward Broadbent }); 11607e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificate 1161cfcd5f6bSMarri Devender Rao /** 1162cfcd5f6bSMarri Devender Rao * Collection of TrustStoreCertificate certificates 1163cfcd5f6bSMarri Devender Rao */ 11647e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificateCollection(App& app) 1165cfcd5f6bSMarri Devender Rao { 11667e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/") 1167ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 1168002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1169002d39b4SEd Tanous [&app](const crow::Request& req, 1170002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 1171*3ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 117245ca1b86SEd Tanous { 117345ca1b86SEd Tanous return; 117445ca1b86SEd Tanous } 11751476687dSEd Tanous 11761476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 11771476687dSEd Tanous "/redfish/v1/Managers/bmc/Truststore/Certificates/"; 11781476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 11791476687dSEd Tanous "#CertificateCollection.CertificateCollection"; 1180002d39b4SEd Tanous asyncResp->res.jsonValue["Name"] = "TrustStore Certificates Collection"; 11811476687dSEd Tanous asyncResp->res.jsonValue["Description"] = 11821476687dSEd Tanous "A Collection of TrustStore certificate instances"; 11838d1b46d7Szhanghch05 1184cfcd5f6bSMarri Devender Rao crow::connections::systemBus->async_method_call( 1185cfcd5f6bSMarri Devender Rao [asyncResp](const boost::system::error_code ec, 1186711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& certs) { 1187cfcd5f6bSMarri Devender Rao if (ec) 1188cfcd5f6bSMarri Devender Rao { 1189cfcd5f6bSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 1190cfcd5f6bSMarri Devender Rao messages::internalError(asyncResp->res); 1191cfcd5f6bSMarri Devender Rao return; 1192cfcd5f6bSMarri Devender Rao } 1193002d39b4SEd Tanous nlohmann::json& members = asyncResp->res.jsonValue["Members"]; 1194cfcd5f6bSMarri Devender Rao members = nlohmann::json::array(); 1195cfcd5f6bSMarri Devender Rao for (const auto& cert : certs) 1196cfcd5f6bSMarri Devender Rao { 1197cfcd5f6bSMarri Devender Rao long id = getIDFromURL(cert.first.str); 1198cfcd5f6bSMarri Devender Rao if (id >= 0) 1199cfcd5f6bSMarri Devender Rao { 12001476687dSEd Tanous nlohmann::json::object_t member; 12011476687dSEd Tanous member["@odata.id"] = 12020fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/Truststore/Certificates/" + 12031476687dSEd Tanous std::to_string(id); 12041476687dSEd Tanous members.push_back(std::move(member)); 1205cfcd5f6bSMarri Devender Rao } 1206cfcd5f6bSMarri Devender Rao } 1207002d39b4SEd Tanous asyncResp->res.jsonValue["Members@odata.count"] = members.size(); 1208cfcd5f6bSMarri Devender Rao }, 1209cfcd5f6bSMarri Devender Rao certs::authorityServiceName, certs::authorityObjectPath, 1210cfcd5f6bSMarri Devender Rao certs::dbusObjManagerIntf, "GetManagedObjects"); 12117e860f15SJohn Edward Broadbent }); 1212cfcd5f6bSMarri Devender Rao 12137e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/") 1214ed398213SEd Tanous .privileges(redfish::privileges::postCertificateCollection) 1215002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 1216002d39b4SEd Tanous [&app](const crow::Request& req, 12177e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 1218*3ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 121945ca1b86SEd Tanous { 122045ca1b86SEd Tanous return; 122145ca1b86SEd Tanous } 1222002d39b4SEd Tanous std::string certFileBody = getCertificateFromReqBody(asyncResp, req); 1223a08752f5SZbigniew Kurzynski 1224a08752f5SZbigniew Kurzynski if (certFileBody.empty()) 1225a08752f5SZbigniew Kurzynski { 12260fda0f12SGeorge Liu BMCWEB_LOG_ERROR << "Cannot get certificate from request body."; 1227a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 1228a08752f5SZbigniew Kurzynski return; 1229a08752f5SZbigniew Kurzynski } 1230a08752f5SZbigniew Kurzynski 1231a08752f5SZbigniew Kurzynski std::shared_ptr<CertificateFile> certFile = 1232a08752f5SZbigniew Kurzynski std::make_shared<CertificateFile>(certFileBody); 1233cfcd5f6bSMarri Devender Rao crow::connections::systemBus->async_method_call( 1234656ec7e3SZbigniew Kurzynski [asyncResp, certFile](const boost::system::error_code ec, 1235656ec7e3SZbigniew Kurzynski const std::string& objectPath) { 1236cfcd5f6bSMarri Devender Rao if (ec) 1237cfcd5f6bSMarri Devender Rao { 1238cfcd5f6bSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 1239cfcd5f6bSMarri Devender Rao messages::internalError(asyncResp->res); 1240cfcd5f6bSMarri Devender Rao return; 1241cfcd5f6bSMarri Devender Rao } 1242656ec7e3SZbigniew Kurzynski long certId = getIDFromURL(objectPath); 1243656ec7e3SZbigniew Kurzynski if (certId < 0) 1244656ec7e3SZbigniew Kurzynski { 1245002d39b4SEd Tanous BMCWEB_LOG_ERROR << "Invalid objectPath value" << objectPath; 1246656ec7e3SZbigniew Kurzynski messages::internalError(asyncResp->res); 1247656ec7e3SZbigniew Kurzynski return; 1248656ec7e3SZbigniew Kurzynski } 12490fda0f12SGeorge Liu std::string certURL = 12500fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/Truststore/Certificates/" + 1251cfcd5f6bSMarri Devender Rao std::to_string(certId); 1252656ec7e3SZbigniew Kurzynski 1253002d39b4SEd Tanous getCertificateProperties(asyncResp, objectPath, 1254002d39b4SEd Tanous certs::authorityServiceName, certId, 1255002d39b4SEd Tanous certURL, "TrustStore Certificate"); 12560fda0f12SGeorge Liu BMCWEB_LOG_DEBUG << "TrustStore certificate install file=" 1257cfcd5f6bSMarri Devender Rao << certFile->getCertFilePath(); 1258cfcd5f6bSMarri Devender Rao }, 1259cfcd5f6bSMarri Devender Rao certs::authorityServiceName, certs::authorityObjectPath, 12600fda0f12SGeorge Liu certs::certInstallIntf, "Install", certFile->getCertFilePath()); 12617e860f15SJohn Edward Broadbent }); 12627e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificateCollection 1263cfcd5f6bSMarri Devender Rao 1264cfcd5f6bSMarri Devender Rao /** 1265cfcd5f6bSMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 1266cfcd5f6bSMarri Devender Rao * of a component, account or service. 1267cfcd5f6bSMarri Devender Rao */ 12687e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificate(App& app) 1269cfcd5f6bSMarri Devender Rao { 12707e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/") 1271ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 12727e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 127345ca1b86SEd Tanous [&app](const crow::Request& req, 12747e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 12757e860f15SJohn Edward Broadbent const std::string&) { 1276*3ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 127745ca1b86SEd Tanous { 127845ca1b86SEd Tanous return; 127945ca1b86SEd Tanous } 1280cfcd5f6bSMarri Devender Rao long id = getIDFromURL(req.url); 1281cfcd5f6bSMarri Devender Rao if (id < 0) 1282cfcd5f6bSMarri Devender Rao { 1283cfcd5f6bSMarri Devender Rao BMCWEB_LOG_ERROR << "Invalid url value" << req.url; 1284cfcd5f6bSMarri Devender Rao messages::internalError(asyncResp->res); 1285cfcd5f6bSMarri Devender Rao return; 1286cfcd5f6bSMarri Devender Rao } 1287cfcd5f6bSMarri Devender Rao BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doGet ID=" 1288cfcd5f6bSMarri Devender Rao << std::to_string(id); 1289cfcd5f6bSMarri Devender Rao std::string certURL = 1290cfcd5f6bSMarri Devender Rao "/redfish/v1/Managers/bmc/Truststore/Certificates/" + 1291cfcd5f6bSMarri Devender Rao std::to_string(id); 1292cfcd5f6bSMarri Devender Rao std::string objectPath = certs::authorityObjectPath; 1293cfcd5f6bSMarri Devender Rao objectPath += "/"; 1294cfcd5f6bSMarri Devender Rao objectPath += std::to_string(id); 1295cfcd5f6bSMarri Devender Rao getCertificateProperties(asyncResp, objectPath, 1296002d39b4SEd Tanous certs::authorityServiceName, id, certURL, 1297002d39b4SEd Tanous "TrustStore Certificate"); 12987e860f15SJohn Edward Broadbent }); 129907a60299SZbigniew Kurzynski 13007e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/") 1301ed398213SEd Tanous .privileges(redfish::privileges::deleteCertificate) 13027e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::delete_)( 130345ca1b86SEd Tanous [&app](const crow::Request& req, 13047e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 13057e860f15SJohn Edward Broadbent const std::string& param) { 1306*3ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 130745ca1b86SEd Tanous { 130845ca1b86SEd Tanous return; 130945ca1b86SEd Tanous } 13107e860f15SJohn Edward Broadbent if (param.empty()) 131107a60299SZbigniew Kurzynski { 131207a60299SZbigniew Kurzynski messages::internalError(asyncResp->res); 131307a60299SZbigniew Kurzynski return; 131407a60299SZbigniew Kurzynski } 131507a60299SZbigniew Kurzynski 131607a60299SZbigniew Kurzynski long id = getIDFromURL(req.url); 131707a60299SZbigniew Kurzynski if (id < 0) 131807a60299SZbigniew Kurzynski { 131907a60299SZbigniew Kurzynski BMCWEB_LOG_ERROR << "Invalid url value: " << req.url; 1320002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "TrustStore Certificate", 132107a60299SZbigniew Kurzynski std::string(req.url)); 132207a60299SZbigniew Kurzynski return; 132307a60299SZbigniew Kurzynski } 132407a60299SZbigniew Kurzynski BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doDelete ID=" 132507a60299SZbigniew Kurzynski << std::to_string(id); 132607a60299SZbigniew Kurzynski std::string certPath = certs::authorityObjectPath; 132707a60299SZbigniew Kurzynski certPath += "/"; 132807a60299SZbigniew Kurzynski certPath += std::to_string(id); 132907a60299SZbigniew Kurzynski 133007a60299SZbigniew Kurzynski crow::connections::systemBus->async_method_call( 133107a60299SZbigniew Kurzynski [asyncResp, id](const boost::system::error_code ec) { 133207a60299SZbigniew Kurzynski if (ec) 133307a60299SZbigniew Kurzynski { 133407a60299SZbigniew Kurzynski messages::resourceNotFound(asyncResp->res, 133507a60299SZbigniew Kurzynski "TrustStore Certificate", 133607a60299SZbigniew Kurzynski std::to_string(id)); 133707a60299SZbigniew Kurzynski return; 133807a60299SZbigniew Kurzynski } 133907a60299SZbigniew Kurzynski BMCWEB_LOG_INFO << "Certificate deleted"; 1340002d39b4SEd Tanous asyncResp->res.result(boost::beast::http::status::no_content); 134107a60299SZbigniew Kurzynski }, 134207a60299SZbigniew Kurzynski certs::authorityServiceName, certPath, certs::objDeleteIntf, 134307a60299SZbigniew Kurzynski "Delete"); 13447e860f15SJohn Edward Broadbent }); 13457e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificate 13465968caeeSMarri Devender Rao } // namespace redfish 1347