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> 6*168e20c1SEd Tanous #include <dbus_utility.hpp> 7ed398213SEd Tanous #include <registries/privilege_registry.hpp> 81214b7e7SGunnar Mills 95968caeeSMarri Devender Rao namespace redfish 105968caeeSMarri Devender Rao { 115968caeeSMarri Devender Rao namespace certs 125968caeeSMarri Devender Rao { 135968caeeSMarri Devender Rao constexpr char const* httpsObjectPath = 145968caeeSMarri Devender Rao "/xyz/openbmc_project/certs/server/https"; 155968caeeSMarri Devender Rao constexpr char const* certInstallIntf = "xyz.openbmc_project.Certs.Install"; 165968caeeSMarri Devender Rao constexpr char const* certReplaceIntf = "xyz.openbmc_project.Certs.Replace"; 1707a60299SZbigniew Kurzynski constexpr char const* objDeleteIntf = "xyz.openbmc_project.Object.Delete"; 185968caeeSMarri Devender Rao constexpr char const* certPropIntf = "xyz.openbmc_project.Certs.Certificate"; 195968caeeSMarri Devender Rao constexpr char const* dbusPropIntf = "org.freedesktop.DBus.Properties"; 205968caeeSMarri Devender Rao constexpr char const* dbusObjManagerIntf = "org.freedesktop.DBus.ObjectManager"; 2137cce918SMarri Devender Rao constexpr char const* ldapObjectPath = "/xyz/openbmc_project/certs/client/ldap"; 2237cce918SMarri Devender Rao constexpr char const* httpsServiceName = 2337cce918SMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Server.Https"; 2437cce918SMarri Devender Rao constexpr char const* ldapServiceName = 2537cce918SMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Client.Ldap"; 26cfcd5f6bSMarri Devender Rao constexpr char const* authorityServiceName = 27cfcd5f6bSMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Authority.Ldap"; 28cfcd5f6bSMarri Devender Rao constexpr char const* authorityObjectPath = 29cfcd5f6bSMarri Devender Rao "/xyz/openbmc_project/certs/authority/ldap"; 305968caeeSMarri Devender Rao } // namespace certs 315968caeeSMarri Devender Rao 325968caeeSMarri Devender Rao /** 335968caeeSMarri Devender Rao * The Certificate schema defines a Certificate Service which represents the 345968caeeSMarri Devender Rao * actions available to manage certificates and links to where certificates 355968caeeSMarri Devender Rao * are installed. 365968caeeSMarri Devender Rao */ 377e860f15SJohn Edward Broadbent 385968caeeSMarri Devender Rao // TODO: Issue#61 No entries are available for Certificate 394e0453b1SGunnar Mills // service at https://www.dmtf.org/standards/redfish 405968caeeSMarri Devender Rao // "redfish standard registries". Need to modify after DMTF 415968caeeSMarri Devender Rao // publish Privilege details for certificate service 425968caeeSMarri Devender Rao 437e860f15SJohn Edward Broadbent inline void requestRoutesCertificateService(App& app) 445968caeeSMarri Devender Rao { 457e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/") 46ed398213SEd Tanous .privileges(redfish::privileges::getCertificateService) 4772048780SAbhishek Patel .methods( 4872048780SAbhishek Patel boost::beast::http::verb:: 4972048780SAbhishek Patel get)([](const crow::Request& req, 507e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 518d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 527e860f15SJohn Edward Broadbent {"@odata.type", 537e860f15SJohn Edward Broadbent "#CertificateService.v1_0_0.CertificateService"}, 545968caeeSMarri Devender Rao {"@odata.id", "/redfish/v1/CertificateService"}, 555968caeeSMarri Devender Rao {"Id", "CertificateService"}, 565968caeeSMarri Devender Rao {"Name", "Certificate Service"}, 5772048780SAbhishek Patel {"Description", "Actions available to manage certificates"}}; 5872048780SAbhishek Patel // /redfish/v1/CertificateService/CertificateLocations is something 5972048780SAbhishek Patel // only ConfigureManager can access then only display when the user 6072048780SAbhishek Patel // has permissions ConfigureManager 6172048780SAbhishek Patel Privileges effectiveUserPrivileges = 6272048780SAbhishek Patel redfish::getUserPrivileges(req.userRole); 6372048780SAbhishek Patel if (isOperationAllowedWithPrivileges({{"ConfigureManager"}}, 6472048780SAbhishek Patel effectiveUserPrivileges)) 6572048780SAbhishek Patel { 668d1b46d7Szhanghch05 asyncResp->res.jsonValue["CertificateLocations"] = { 675968caeeSMarri Devender Rao {"@odata.id", 685968caeeSMarri Devender Rao "/redfish/v1/CertificateService/CertificateLocations"}}; 6972048780SAbhishek Patel } 700fda0f12SGeorge Liu asyncResp->res 710fda0f12SGeorge Liu .jsonValue["Actions"] 720fda0f12SGeorge Liu ["#CertificateService.ReplaceCertificate"] = { 730fda0f12SGeorge Liu {"target", 740fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate"}, 755968caeeSMarri Devender Rao {"CertificateType@Redfish.AllowableValues", {"PEM"}}}; 767e860f15SJohn Edward Broadbent asyncResp->res 777e860f15SJohn Edward Broadbent .jsonValue["Actions"]["#CertificateService.GenerateCSR"] = { 780fda0f12SGeorge Liu {"target", 790fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR"}}; 807e860f15SJohn Edward Broadbent }); 817e860f15SJohn Edward Broadbent } // requestRoutesCertificateService 8237cce918SMarri Devender Rao 835968caeeSMarri Devender Rao /** 845968caeeSMarri Devender Rao * @brief Find the ID specified in the URL 855968caeeSMarri Devender Rao * Finds the numbers specified after the last "/" in the URL and returns. 865968caeeSMarri Devender Rao * @param[in] path URL 875968caeeSMarri Devender Rao * @return -1 on failure and number on success 885968caeeSMarri Devender Rao */ 8923a21a1cSEd Tanous inline long getIDFromURL(const std::string_view url) 905968caeeSMarri Devender Rao { 91f23b7296SEd Tanous std::size_t found = url.rfind('/'); 925968caeeSMarri Devender Rao if (found == std::string::npos) 935968caeeSMarri Devender Rao { 945968caeeSMarri Devender Rao return -1; 955968caeeSMarri Devender Rao } 96e6604b11SIwona Klimaszewska 975968caeeSMarri Devender Rao if ((found + 1) < url.length()) 985968caeeSMarri Devender Rao { 995968caeeSMarri Devender Rao std::string_view str = url.substr(found + 1); 100e6604b11SIwona Klimaszewska 101e6604b11SIwona Klimaszewska return boost::convert<long>(str, boost::cnv::strtol()).value_or(-1); 1025968caeeSMarri Devender Rao } 103e6604b11SIwona Klimaszewska 1045968caeeSMarri Devender Rao return -1; 1055968caeeSMarri Devender Rao } 1065968caeeSMarri Devender Rao 1078d1b46d7Szhanghch05 inline std::string getCertificateFromReqBody( 1088d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 10958eb238fSKowalski, Kamil const crow::Request& req) 11058eb238fSKowalski, Kamil { 11158eb238fSKowalski, Kamil nlohmann::json reqJson = nlohmann::json::parse(req.body, nullptr, false); 11258eb238fSKowalski, Kamil 11358eb238fSKowalski, Kamil if (reqJson.is_discarded()) 11458eb238fSKowalski, Kamil { 11558eb238fSKowalski, Kamil // We did not receive JSON request, proceed as it is RAW data 11658eb238fSKowalski, Kamil return req.body; 11758eb238fSKowalski, Kamil } 11858eb238fSKowalski, Kamil 11958eb238fSKowalski, Kamil std::string certificate; 12058eb238fSKowalski, Kamil std::optional<std::string> certificateType = "PEM"; 12158eb238fSKowalski, Kamil 12258eb238fSKowalski, Kamil if (!json_util::readJson(reqJson, asyncResp->res, "CertificateString", 12358eb238fSKowalski, Kamil certificate, "CertificateType", certificateType)) 12458eb238fSKowalski, Kamil { 12558eb238fSKowalski, Kamil BMCWEB_LOG_ERROR << "Required parameters are missing"; 12658eb238fSKowalski, Kamil messages::internalError(asyncResp->res); 127abb93cddSEd Tanous return {}; 12858eb238fSKowalski, Kamil } 12958eb238fSKowalski, Kamil 13058eb238fSKowalski, Kamil if (*certificateType != "PEM") 13158eb238fSKowalski, Kamil { 13258eb238fSKowalski, Kamil messages::propertyValueNotInList(asyncResp->res, *certificateType, 13358eb238fSKowalski, Kamil "CertificateType"); 134abb93cddSEd Tanous return {}; 13558eb238fSKowalski, Kamil } 13658eb238fSKowalski, Kamil 13758eb238fSKowalski, Kamil return certificate; 13858eb238fSKowalski, Kamil } 13958eb238fSKowalski, Kamil 1405968caeeSMarri Devender Rao /** 1415968caeeSMarri Devender Rao * Class to create a temporary certificate file for uploading to system 1425968caeeSMarri Devender Rao */ 1435968caeeSMarri Devender Rao class CertificateFile 1445968caeeSMarri Devender Rao { 1455968caeeSMarri Devender Rao public: 1465968caeeSMarri Devender Rao CertificateFile() = delete; 1475968caeeSMarri Devender Rao CertificateFile(const CertificateFile&) = delete; 1485968caeeSMarri Devender Rao CertificateFile& operator=(const CertificateFile&) = delete; 1495968caeeSMarri Devender Rao CertificateFile(CertificateFile&&) = delete; 1505968caeeSMarri Devender Rao CertificateFile& operator=(CertificateFile&&) = delete; 1515968caeeSMarri Devender Rao CertificateFile(const std::string& certString) 1525968caeeSMarri Devender Rao { 15372d52d25SEd Tanous std::array<char, 18> dirTemplate = {'/', 't', 'm', 'p', '/', 'C', 1545207438cSEd Tanous 'e', 'r', 't', 's', '.', 'X', 1555207438cSEd Tanous 'X', 'X', 'X', 'X', 'X', '\0'}; 1565207438cSEd Tanous char* tempDirectory = mkdtemp(dirTemplate.data()); 1575968caeeSMarri Devender Rao if (tempDirectory) 1585968caeeSMarri Devender Rao { 1595968caeeSMarri Devender Rao certDirectory = tempDirectory; 1605968caeeSMarri Devender Rao certificateFile = certDirectory / "cert.pem"; 1615968caeeSMarri Devender Rao std::ofstream out(certificateFile, std::ofstream::out | 1625968caeeSMarri Devender Rao std::ofstream::binary | 1635968caeeSMarri Devender Rao std::ofstream::trunc); 1645968caeeSMarri Devender Rao out << certString; 1655968caeeSMarri Devender Rao out.close(); 1665968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "Creating certificate file" << certificateFile; 1675968caeeSMarri Devender Rao } 1685968caeeSMarri Devender Rao } 1695968caeeSMarri Devender Rao ~CertificateFile() 1705968caeeSMarri Devender Rao { 1715968caeeSMarri Devender Rao if (std::filesystem::exists(certDirectory)) 1725968caeeSMarri Devender Rao { 1735968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "Removing certificate file" << certificateFile; 17423a21a1cSEd Tanous std::error_code ec; 17523a21a1cSEd Tanous std::filesystem::remove_all(certDirectory, ec); 17623a21a1cSEd Tanous if (ec) 1775968caeeSMarri Devender Rao { 1785968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Failed to remove temp directory" 1795968caeeSMarri Devender Rao << certDirectory; 1805968caeeSMarri Devender Rao } 1815968caeeSMarri Devender Rao } 1825968caeeSMarri Devender Rao } 1835968caeeSMarri Devender Rao std::string getCertFilePath() 1845968caeeSMarri Devender Rao { 1855968caeeSMarri Devender Rao return certificateFile; 1865968caeeSMarri Devender Rao } 1875968caeeSMarri Devender Rao 1885968caeeSMarri Devender Rao private: 1895968caeeSMarri Devender Rao std::filesystem::path certificateFile; 1905968caeeSMarri Devender Rao std::filesystem::path certDirectory; 1915968caeeSMarri Devender Rao }; 1925968caeeSMarri Devender Rao 19330215816SMarri Devender Rao static std::unique_ptr<sdbusplus::bus::match::match> csrMatcher; 19430215816SMarri Devender Rao /** 19530215816SMarri Devender Rao * @brief Read data from CSR D-bus object and set to response 19630215816SMarri Devender Rao * 19730215816SMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 19830215816SMarri Devender Rao * @param[in] certURI Link to certifiate collection URI 19930215816SMarri Devender Rao * @param[in] service D-Bus service name 20030215816SMarri Devender Rao * @param[in] certObjPath certificate D-Bus object path 20130215816SMarri Devender Rao * @param[in] csrObjPath CSR D-Bus object path 20230215816SMarri Devender Rao * @return None 20330215816SMarri Devender Rao */ 2048d1b46d7Szhanghch05 static void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 20530215816SMarri Devender Rao const std::string& certURI, const std::string& service, 20630215816SMarri Devender Rao const std::string& certObjPath, 20730215816SMarri Devender Rao const std::string& csrObjPath) 20830215816SMarri Devender Rao { 20930215816SMarri Devender Rao BMCWEB_LOG_DEBUG << "getCSR CertObjectPath" << certObjPath 21030215816SMarri Devender Rao << " CSRObjectPath=" << csrObjPath 21130215816SMarri Devender Rao << " service=" << service; 21230215816SMarri Devender Rao crow::connections::systemBus->async_method_call( 21330215816SMarri Devender Rao [asyncResp, certURI](const boost::system::error_code ec, 21430215816SMarri Devender Rao const std::string& csr) { 21530215816SMarri Devender Rao if (ec) 21630215816SMarri Devender Rao { 21730215816SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 21830215816SMarri Devender Rao messages::internalError(asyncResp->res); 21930215816SMarri Devender Rao return; 22030215816SMarri Devender Rao } 22130215816SMarri Devender Rao if (csr.empty()) 22230215816SMarri Devender Rao { 22330215816SMarri Devender Rao BMCWEB_LOG_ERROR << "CSR read is empty"; 22430215816SMarri Devender Rao messages::internalError(asyncResp->res); 22530215816SMarri Devender Rao return; 22630215816SMarri Devender Rao } 22730215816SMarri Devender Rao asyncResp->res.jsonValue["CSRString"] = csr; 22830215816SMarri Devender Rao asyncResp->res.jsonValue["CertificateCollection"] = { 22930215816SMarri Devender Rao {"@odata.id", certURI}}; 23030215816SMarri Devender Rao }, 23130215816SMarri Devender Rao service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR"); 23230215816SMarri Devender Rao } 23330215816SMarri Devender Rao 23430215816SMarri Devender Rao /** 23530215816SMarri Devender Rao * Action to Generate CSR 23630215816SMarri Devender Rao */ 2377e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionGenerateCSR(App& app) 23830215816SMarri Devender Rao { 2390fda0f12SGeorge Liu BMCWEB_ROUTE( 2400fda0f12SGeorge Liu app, 2410fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR/") 242ed398213SEd Tanous // Incorrect Privilege; Should be ConfigureManager 243ed398213SEd Tanous //.privileges(redfish::privileges::postCertificateService) 244432a890cSEd Tanous .privileges({{"ConfigureComponents"}}) 2450fda0f12SGeorge Liu .methods( 2460fda0f12SGeorge Liu boost::beast::http::verb:: 2470fda0f12SGeorge Liu post)([](const crow::Request& req, 2487e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 2492c70f800SEd Tanous static const int rsaKeyBitLength = 2048; 2508d1b46d7Szhanghch05 25130215816SMarri Devender Rao // Required parameters 25230215816SMarri Devender Rao std::string city; 25330215816SMarri Devender Rao std::string commonName; 25430215816SMarri Devender Rao std::string country; 25530215816SMarri Devender Rao std::string organization; 25630215816SMarri Devender Rao std::string organizationalUnit; 25730215816SMarri Devender Rao std::string state; 25830215816SMarri Devender Rao nlohmann::json certificateCollection; 25930215816SMarri Devender Rao 26030215816SMarri Devender Rao // Optional parameters 26130215816SMarri Devender Rao std::optional<std::vector<std::string>> optAlternativeNames = 26230215816SMarri Devender Rao std::vector<std::string>(); 26330215816SMarri Devender Rao std::optional<std::string> optContactPerson = ""; 26430215816SMarri Devender Rao std::optional<std::string> optChallengePassword = ""; 26530215816SMarri Devender Rao std::optional<std::string> optEmail = ""; 26630215816SMarri Devender Rao std::optional<std::string> optGivenName = ""; 26730215816SMarri Devender Rao std::optional<std::string> optInitials = ""; 2682c70f800SEd Tanous std::optional<int64_t> optKeyBitLength = rsaKeyBitLength; 269aaf3206fSVernon Mauery std::optional<std::string> optKeyCurveId = "secp384r1"; 27030215816SMarri Devender Rao std::optional<std::string> optKeyPairAlgorithm = "EC"; 27130215816SMarri Devender Rao std::optional<std::vector<std::string>> optKeyUsage = 27230215816SMarri Devender Rao std::vector<std::string>(); 27330215816SMarri Devender Rao std::optional<std::string> optSurname = ""; 27430215816SMarri Devender Rao std::optional<std::string> optUnstructuredName = ""; 27530215816SMarri Devender Rao if (!json_util::readJson( 2760fda0f12SGeorge Liu req, asyncResp->res, "City", city, "CommonName", commonName, 2770fda0f12SGeorge Liu "ContactPerson", optContactPerson, "Country", country, 2780fda0f12SGeorge Liu "Organization", organization, "OrganizationalUnit", 2790fda0f12SGeorge Liu organizationalUnit, "State", state, "CertificateCollection", 2800fda0f12SGeorge Liu certificateCollection, "AlternativeNames", 2810fda0f12SGeorge Liu optAlternativeNames, "ChallengePassword", 2820fda0f12SGeorge Liu optChallengePassword, "Email", optEmail, "GivenName", 2830fda0f12SGeorge Liu optGivenName, "Initials", optInitials, "KeyBitLength", 2840fda0f12SGeorge Liu optKeyBitLength, "KeyCurveId", optKeyCurveId, 2850fda0f12SGeorge Liu "KeyPairAlgorithm", optKeyPairAlgorithm, "KeyUsage", 2860fda0f12SGeorge Liu optKeyUsage, "Surname", optSurname, "UnstructuredName", 2870fda0f12SGeorge Liu optUnstructuredName)) 28830215816SMarri Devender Rao { 28930215816SMarri Devender Rao return; 29030215816SMarri Devender Rao } 29130215816SMarri Devender Rao 29230215816SMarri Devender Rao // bmcweb has no way to store or decode a private key challenge 2937e860f15SJohn Edward Broadbent // password, which will likely cause bmcweb to crash on startup 2947e860f15SJohn Edward Broadbent // if this is not set on a post so not allowing the user to set 2957e860f15SJohn Edward Broadbent // value 29630215816SMarri Devender Rao if (*optChallengePassword != "") 29730215816SMarri Devender Rao { 2987e860f15SJohn Edward Broadbent messages::actionParameterNotSupported( 2997e860f15SJohn Edward Broadbent asyncResp->res, "GenerateCSR", "ChallengePassword"); 30030215816SMarri Devender Rao return; 30130215816SMarri Devender Rao } 30230215816SMarri Devender Rao 30330215816SMarri Devender Rao std::string certURI; 3047e860f15SJohn Edward Broadbent if (!redfish::json_util::readJson(certificateCollection, 3057e860f15SJohn Edward Broadbent asyncResp->res, "@odata.id", 3067e860f15SJohn Edward Broadbent certURI)) 30730215816SMarri Devender Rao { 30830215816SMarri Devender Rao return; 30930215816SMarri Devender Rao } 31030215816SMarri Devender Rao 31130215816SMarri Devender Rao std::string objectPath; 31230215816SMarri Devender Rao std::string service; 3130fda0f12SGeorge Liu if (boost::starts_with( 3140fda0f12SGeorge Liu certURI, 3150fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) 31630215816SMarri Devender Rao { 31730215816SMarri Devender Rao objectPath = certs::httpsObjectPath; 31830215816SMarri Devender Rao service = certs::httpsServiceName; 31930215816SMarri Devender Rao } 3203b7f0149SMarri Devender Rao else if (boost::starts_with( 3217e860f15SJohn Edward Broadbent certURI, 3227e860f15SJohn Edward Broadbent "/redfish/v1/AccountService/LDAP/Certificates")) 3233b7f0149SMarri Devender Rao { 3243b7f0149SMarri Devender Rao objectPath = certs::ldapObjectPath; 3253b7f0149SMarri Devender Rao service = certs::ldapServiceName; 3263b7f0149SMarri Devender Rao } 32730215816SMarri Devender Rao else 32830215816SMarri Devender Rao { 32930215816SMarri Devender Rao messages::actionParameterNotSupported( 33030215816SMarri Devender Rao asyncResp->res, "CertificateCollection", "GenerateCSR"); 33130215816SMarri Devender Rao return; 33230215816SMarri Devender Rao } 33330215816SMarri Devender Rao 33430215816SMarri Devender Rao // supporting only EC and RSA algorithm 3350fda0f12SGeorge Liu if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA") 33630215816SMarri Devender Rao { 33730215816SMarri Devender Rao messages::actionParameterNotSupported( 33830215816SMarri Devender Rao asyncResp->res, "KeyPairAlgorithm", "GenerateCSR"); 33930215816SMarri Devender Rao return; 34030215816SMarri Devender Rao } 34130215816SMarri Devender Rao 3427e860f15SJohn Edward Broadbent // supporting only 2048 key bit length for RSA algorithm due to 3437e860f15SJohn Edward Broadbent // time consumed in generating private key 34430215816SMarri Devender Rao if (*optKeyPairAlgorithm == "RSA" && 3452c70f800SEd Tanous *optKeyBitLength != rsaKeyBitLength) 34630215816SMarri Devender Rao { 3477e860f15SJohn Edward Broadbent messages::propertyValueNotInList( 3487e860f15SJohn Edward Broadbent asyncResp->res, std::to_string(*optKeyBitLength), 34930215816SMarri Devender Rao "KeyBitLength"); 35030215816SMarri Devender Rao return; 35130215816SMarri Devender Rao } 35230215816SMarri Devender Rao 35330215816SMarri Devender Rao // validate KeyUsage supporting only 1 type based on URL 3540fda0f12SGeorge Liu if (boost::starts_with( 3550fda0f12SGeorge Liu certURI, 3560fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) 35730215816SMarri Devender Rao { 35830215816SMarri Devender Rao if (optKeyUsage->size() == 0) 35930215816SMarri Devender Rao { 36030215816SMarri Devender Rao optKeyUsage->push_back("ServerAuthentication"); 36130215816SMarri Devender Rao } 36230215816SMarri Devender Rao else if (optKeyUsage->size() == 1) 36330215816SMarri Devender Rao { 36430215816SMarri Devender Rao if ((*optKeyUsage)[0] != "ServerAuthentication") 36530215816SMarri Devender Rao { 36630215816SMarri Devender Rao messages::propertyValueNotInList( 36730215816SMarri Devender Rao asyncResp->res, (*optKeyUsage)[0], "KeyUsage"); 36830215816SMarri Devender Rao return; 36930215816SMarri Devender Rao } 37030215816SMarri Devender Rao } 37130215816SMarri Devender Rao else 37230215816SMarri Devender Rao { 37330215816SMarri Devender Rao messages::actionParameterNotSupported( 37430215816SMarri Devender Rao asyncResp->res, "KeyUsage", "GenerateCSR"); 37530215816SMarri Devender Rao return; 37630215816SMarri Devender Rao } 37730215816SMarri Devender Rao } 3783b7f0149SMarri Devender Rao else if (boost::starts_with( 3797e860f15SJohn Edward Broadbent certURI, 3807e860f15SJohn Edward Broadbent "/redfish/v1/AccountService/LDAP/Certificates")) 3813b7f0149SMarri Devender Rao { 3823b7f0149SMarri Devender Rao if (optKeyUsage->size() == 0) 3833b7f0149SMarri Devender Rao { 3843b7f0149SMarri Devender Rao optKeyUsage->push_back("ClientAuthentication"); 3853b7f0149SMarri Devender Rao } 3863b7f0149SMarri Devender Rao else if (optKeyUsage->size() == 1) 3873b7f0149SMarri Devender Rao { 3883b7f0149SMarri Devender Rao if ((*optKeyUsage)[0] != "ClientAuthentication") 3893b7f0149SMarri Devender Rao { 3903b7f0149SMarri Devender Rao messages::propertyValueNotInList( 3913b7f0149SMarri Devender Rao asyncResp->res, (*optKeyUsage)[0], "KeyUsage"); 3923b7f0149SMarri Devender Rao return; 3933b7f0149SMarri Devender Rao } 3943b7f0149SMarri Devender Rao } 3953b7f0149SMarri Devender Rao else 3963b7f0149SMarri Devender Rao { 3973b7f0149SMarri Devender Rao messages::actionParameterNotSupported( 3983b7f0149SMarri Devender Rao asyncResp->res, "KeyUsage", "GenerateCSR"); 3993b7f0149SMarri Devender Rao return; 4003b7f0149SMarri Devender Rao } 4013b7f0149SMarri Devender Rao } 40230215816SMarri Devender Rao 4037e860f15SJohn Edward Broadbent // Only allow one CSR matcher at a time so setting retry 4047e860f15SJohn Edward Broadbent // time-out and timer expiry to 10 seconds for now. 4052c70f800SEd Tanous static const int timeOut = 10; 40630215816SMarri Devender Rao if (csrMatcher) 40730215816SMarri Devender Rao { 4087e860f15SJohn Edward Broadbent messages::serviceTemporarilyUnavailable( 4097e860f15SJohn Edward Broadbent asyncResp->res, std::to_string(timeOut)); 41030215816SMarri Devender Rao return; 41130215816SMarri Devender Rao } 41230215816SMarri Devender Rao 41330215816SMarri Devender Rao // Make this static so it survives outside this method 41430215816SMarri Devender Rao static boost::asio::steady_timer timeout(*req.ioService); 4152c70f800SEd Tanous timeout.expires_after(std::chrono::seconds(timeOut)); 4160fda0f12SGeorge Liu timeout.async_wait( 4170fda0f12SGeorge Liu [asyncResp](const boost::system::error_code& ec) { 41830215816SMarri Devender Rao csrMatcher = nullptr; 41930215816SMarri Devender Rao if (ec) 42030215816SMarri Devender Rao { 4217e860f15SJohn Edward Broadbent // operation_aborted is expected if timer is canceled 4227e860f15SJohn Edward Broadbent // before completion. 42330215816SMarri Devender Rao if (ec != boost::asio::error::operation_aborted) 42430215816SMarri Devender Rao { 42530215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Async_wait failed " << ec; 42630215816SMarri Devender Rao } 42730215816SMarri Devender Rao return; 42830215816SMarri Devender Rao } 42930215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR"; 43030215816SMarri Devender Rao messages::internalError(asyncResp->res); 43130215816SMarri Devender Rao }); 43230215816SMarri Devender Rao 43330215816SMarri Devender Rao // create a matcher to wait on CSR object 43430215816SMarri Devender Rao BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath; 4350fda0f12SGeorge Liu std::string match("type='signal'," 43630215816SMarri Devender Rao "interface='org.freedesktop.DBus.ObjectManager'," 43730215816SMarri Devender Rao "path='" + 43830215816SMarri Devender Rao objectPath + 43930215816SMarri Devender Rao "'," 44030215816SMarri Devender Rao "member='InterfacesAdded'"); 44130215816SMarri Devender Rao csrMatcher = std::make_unique<sdbusplus::bus::match::match>( 44230215816SMarri Devender Rao *crow::connections::systemBus, match, 44330215816SMarri Devender Rao [asyncResp, service, objectPath, 44430215816SMarri Devender Rao certURI](sdbusplus::message::message& m) { 445271584abSEd Tanous timeout.cancel(); 44630215816SMarri Devender Rao if (m.is_method_error()) 44730215816SMarri Devender Rao { 44830215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Dbus method error!!!"; 44930215816SMarri Devender Rao messages::internalError(asyncResp->res); 45030215816SMarri Devender Rao return; 45130215816SMarri Devender Rao } 45230215816SMarri Devender Rao std::vector<std::pair< 453*168e20c1SEd Tanous std::string, 454*168e20c1SEd Tanous std::vector<std::pair<std::string, 455*168e20c1SEd Tanous dbus::utility::DbusVariantType>>>> 45630215816SMarri Devender Rao interfacesProperties; 45730215816SMarri Devender Rao sdbusplus::message::object_path csrObjectPath; 45830215816SMarri Devender Rao m.read(csrObjectPath, interfacesProperties); 4590fda0f12SGeorge Liu BMCWEB_LOG_DEBUG << "CSR object added" << csrObjectPath.str; 46030215816SMarri Devender Rao for (auto& interface : interfacesProperties) 46130215816SMarri Devender Rao { 4620fda0f12SGeorge Liu if (interface.first == "xyz.openbmc_project.Certs.CSR") 46330215816SMarri Devender Rao { 46430215816SMarri Devender Rao getCSR(asyncResp, certURI, service, objectPath, 46530215816SMarri Devender Rao csrObjectPath.str); 46630215816SMarri Devender Rao break; 46730215816SMarri Devender Rao } 46830215816SMarri Devender Rao } 46930215816SMarri Devender Rao }); 47030215816SMarri Devender Rao crow::connections::systemBus->async_method_call( 471271584abSEd Tanous [asyncResp](const boost::system::error_code& ec, 472cb13a392SEd Tanous const std::string&) { 47330215816SMarri Devender Rao if (ec) 47430215816SMarri Devender Rao { 4757e860f15SJohn Edward Broadbent BMCWEB_LOG_ERROR << "DBUS response error: " 4767e860f15SJohn Edward Broadbent << ec.message(); 47730215816SMarri Devender Rao messages::internalError(asyncResp->res); 47830215816SMarri Devender Rao return; 47930215816SMarri Devender Rao } 48030215816SMarri Devender Rao }, 48130215816SMarri Devender Rao service, objectPath, "xyz.openbmc_project.Certs.CSR.Create", 4827e860f15SJohn Edward Broadbent "GenerateCSR", *optAlternativeNames, *optChallengePassword, 4837e860f15SJohn Edward Broadbent city, commonName, *optContactPerson, country, *optEmail, 4840fda0f12SGeorge Liu *optGivenName, *optInitials, *optKeyBitLength, *optKeyCurveId, 4850fda0f12SGeorge Liu *optKeyPairAlgorithm, *optKeyUsage, organization, 4860fda0f12SGeorge Liu organizationalUnit, state, *optSurname, *optUnstructuredName); 4877e860f15SJohn Edward Broadbent }); 4887e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionGenerateCSR 48930215816SMarri Devender Rao 4905968caeeSMarri Devender Rao /** 4914e0453b1SGunnar Mills * @brief Parse and update Certificate Issue/Subject property 4925968caeeSMarri Devender Rao * 4935968caeeSMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 4945968caeeSMarri Devender Rao * @param[in] str Issuer/Subject value in key=value pairs 4955968caeeSMarri Devender Rao * @param[in] type Issuer/Subject 4965968caeeSMarri Devender Rao * @return None 4975968caeeSMarri Devender Rao */ 4985968caeeSMarri Devender Rao static void updateCertIssuerOrSubject(nlohmann::json& out, 4995968caeeSMarri Devender Rao const std::string_view value) 5005968caeeSMarri Devender Rao { 5015968caeeSMarri Devender Rao // example: O=openbmc-project.xyz,CN=localhost 5025968caeeSMarri Devender Rao std::string_view::iterator i = value.begin(); 5035968caeeSMarri Devender Rao while (i != value.end()) 5045968caeeSMarri Devender Rao { 5055968caeeSMarri Devender Rao std::string_view::iterator tokenBegin = i; 5065968caeeSMarri Devender Rao while (i != value.end() && *i != '=') 5075968caeeSMarri Devender Rao { 50817a897dfSManojkiran Eda ++i; 5095968caeeSMarri Devender Rao } 5105968caeeSMarri Devender Rao if (i == value.end()) 5115968caeeSMarri Devender Rao { 5125968caeeSMarri Devender Rao break; 5135968caeeSMarri Devender Rao } 514271584abSEd Tanous const std::string_view key(tokenBegin, 515271584abSEd Tanous static_cast<size_t>(i - tokenBegin)); 51617a897dfSManojkiran Eda ++i; 5175968caeeSMarri Devender Rao tokenBegin = i; 5185968caeeSMarri Devender Rao while (i != value.end() && *i != ',') 5195968caeeSMarri Devender Rao { 52017a897dfSManojkiran Eda ++i; 5215968caeeSMarri Devender Rao } 522271584abSEd Tanous const std::string_view val(tokenBegin, 523271584abSEd Tanous static_cast<size_t>(i - tokenBegin)); 5245968caeeSMarri Devender Rao if (key == "L") 5255968caeeSMarri Devender Rao { 5265968caeeSMarri Devender Rao out["City"] = val; 5275968caeeSMarri Devender Rao } 5285968caeeSMarri Devender Rao else if (key == "CN") 5295968caeeSMarri Devender Rao { 5305968caeeSMarri Devender Rao out["CommonName"] = val; 5315968caeeSMarri Devender Rao } 5325968caeeSMarri Devender Rao else if (key == "C") 5335968caeeSMarri Devender Rao { 5345968caeeSMarri Devender Rao out["Country"] = val; 5355968caeeSMarri Devender Rao } 5365968caeeSMarri Devender Rao else if (key == "O") 5375968caeeSMarri Devender Rao { 5385968caeeSMarri Devender Rao out["Organization"] = val; 5395968caeeSMarri Devender Rao } 5405968caeeSMarri Devender Rao else if (key == "OU") 5415968caeeSMarri Devender Rao { 5425968caeeSMarri Devender Rao out["OrganizationalUnit"] = val; 5435968caeeSMarri Devender Rao } 5445968caeeSMarri Devender Rao else if (key == "ST") 5455968caeeSMarri Devender Rao { 5465968caeeSMarri Devender Rao out["State"] = val; 5475968caeeSMarri Devender Rao } 5485968caeeSMarri Devender Rao // skip comma character 5495968caeeSMarri Devender Rao if (i != value.end()) 5505968caeeSMarri Devender Rao { 55117a897dfSManojkiran Eda ++i; 5525968caeeSMarri Devender Rao } 5535968caeeSMarri Devender Rao } 5545968caeeSMarri Devender Rao } 5555968caeeSMarri Devender Rao 5565968caeeSMarri Devender Rao /** 5575968caeeSMarri Devender Rao * @brief Retrieve the certificates properties and append to the response 5585968caeeSMarri Devender Rao * message 5595968caeeSMarri Devender Rao * 5605968caeeSMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 5615968caeeSMarri Devender Rao * @param[in] objectPath Path of the D-Bus service object 5625968caeeSMarri Devender Rao * @param[in] certId Id of the certificate 5635968caeeSMarri Devender Rao * @param[in] certURL URL of the certificate object 5645968caeeSMarri Devender Rao * @param[in] name name of the certificate 5655968caeeSMarri Devender Rao * @return None 5665968caeeSMarri Devender Rao */ 5675968caeeSMarri Devender Rao static void getCertificateProperties( 5688d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 5698d1b46d7Szhanghch05 const std::string& objectPath, const std::string& service, long certId, 5708d1b46d7Szhanghch05 const std::string& certURL, const std::string& name) 5715968caeeSMarri Devender Rao { 572*168e20c1SEd Tanous using PropertiesMap = 573*168e20c1SEd Tanous boost::container::flat_map<std::string, dbus::utility::DbusVariantType>; 5745968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "getCertificateProperties Path=" << objectPath 5755968caeeSMarri Devender Rao << " certId=" << certId << " certURl=" << certURL; 5765968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 57737cce918SMarri Devender Rao [asyncResp, certURL, certId, name](const boost::system::error_code ec, 5785968caeeSMarri Devender Rao const PropertiesMap& 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 } 5865968caeeSMarri Devender Rao asyncResp->res.jsonValue = { 5875968caeeSMarri Devender Rao {"@odata.id", certURL}, 5885968caeeSMarri Devender Rao {"@odata.type", "#Certificate.v1_0_0.Certificate"}, 5895968caeeSMarri Devender Rao {"Id", std::to_string(certId)}, 5905968caeeSMarri Devender Rao {"Name", name}, 5915968caeeSMarri Devender Rao {"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); 5995968caeeSMarri Devender Rao if (value) 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 { 6065968caeeSMarri Devender Rao nlohmann::json& keyUsage = 6075968caeeSMarri Devender Rao asyncResp->res.jsonValue["KeyUsage"]; 6085968caeeSMarri Devender Rao keyUsage = nlohmann::json::array(); 6095968caeeSMarri Devender Rao const std::vector<std::string>* value = 61037cce918SMarri Devender Rao std::get_if<std::vector<std::string>>(&property.second); 6115968caeeSMarri Devender Rao if (value) 6125968caeeSMarri Devender Rao { 6135968caeeSMarri Devender Rao for (const std::string& usage : *value) 6145968caeeSMarri Devender Rao { 6155968caeeSMarri Devender Rao keyUsage.push_back(usage); 6165968caeeSMarri Devender Rao } 6175968caeeSMarri Devender Rao } 6185968caeeSMarri Devender Rao } 6195968caeeSMarri Devender Rao else if (property.first == "Issuer") 6205968caeeSMarri Devender Rao { 6215968caeeSMarri Devender Rao const std::string* value = 6225968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 6235968caeeSMarri Devender Rao if (value) 6245968caeeSMarri Devender Rao { 6255968caeeSMarri Devender Rao updateCertIssuerOrSubject( 6265968caeeSMarri Devender Rao asyncResp->res.jsonValue["Issuer"], *value); 6275968caeeSMarri Devender Rao } 6285968caeeSMarri Devender Rao } 6295968caeeSMarri Devender Rao else if (property.first == "Subject") 6305968caeeSMarri Devender Rao { 6315968caeeSMarri Devender Rao const std::string* value = 6325968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 6335968caeeSMarri Devender Rao if (value) 6345968caeeSMarri Devender Rao { 6355968caeeSMarri Devender Rao updateCertIssuerOrSubject( 63637cce918SMarri Devender Rao asyncResp->res.jsonValue["Subject"], *value); 6375968caeeSMarri Devender Rao } 6385968caeeSMarri Devender Rao } 6395968caeeSMarri Devender Rao else if (property.first == "ValidNotAfter") 6405968caeeSMarri Devender Rao { 6415968caeeSMarri Devender Rao const uint64_t* value = 6425968caeeSMarri Devender Rao std::get_if<uint64_t>(&property.second); 6435968caeeSMarri Devender Rao if (value) 6445968caeeSMarri Devender Rao { 6455968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotAfter"] = 6461d8782e7SNan Zhou crow::utility::getDateTimeUint(*value); 6475968caeeSMarri Devender Rao } 6485968caeeSMarri Devender Rao } 6495968caeeSMarri Devender Rao else if (property.first == "ValidNotBefore") 6505968caeeSMarri Devender Rao { 6515968caeeSMarri Devender Rao const uint64_t* value = 6525968caeeSMarri Devender Rao std::get_if<uint64_t>(&property.second); 6535968caeeSMarri Devender Rao if (value) 6545968caeeSMarri Devender Rao { 6555968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotBefore"] = 6561d8782e7SNan Zhou crow::utility::getDateTimeUint(*value); 6575968caeeSMarri Devender Rao } 6585968caeeSMarri Devender Rao } 6595968caeeSMarri Devender Rao } 6605968caeeSMarri Devender Rao asyncResp->res.addHeader("Location", certURL); 6615968caeeSMarri Devender Rao }, 6625968caeeSMarri Devender Rao service, objectPath, certs::dbusPropIntf, "GetAll", 6635968caeeSMarri Devender Rao certs::certPropIntf); 6645968caeeSMarri Devender Rao } 6655968caeeSMarri Devender Rao 6665968caeeSMarri Devender Rao using GetObjectType = 6675968caeeSMarri Devender Rao std::vector<std::pair<std::string, std::vector<std::string>>>; 6685968caeeSMarri Devender Rao 6695968caeeSMarri Devender Rao /** 6705968caeeSMarri Devender Rao * Action to replace an existing certificate 6715968caeeSMarri Devender Rao */ 6727e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionsReplaceCertificate(App& app) 6735968caeeSMarri Devender Rao { 6740fda0f12SGeorge Liu BMCWEB_ROUTE( 6750fda0f12SGeorge Liu app, 6760fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate/") 677ed398213SEd Tanous .privileges(redfish::privileges::postCertificateService) 6787e860f15SJohn Edward Broadbent .methods( 6797e860f15SJohn Edward Broadbent boost::beast::http::verb:: 6807e860f15SJohn Edward Broadbent post)([](const crow::Request& req, 6817e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 6825968caeeSMarri Devender Rao std::string certificate; 6835968caeeSMarri Devender Rao nlohmann::json certificateUri; 6845968caeeSMarri Devender Rao std::optional<std::string> certificateType = "PEM"; 6858d1b46d7Szhanghch05 6865968caeeSMarri Devender Rao if (!json_util::readJson(req, asyncResp->res, "CertificateString", 6877e860f15SJohn Edward Broadbent certificate, "CertificateUri", 6887e860f15SJohn Edward Broadbent certificateUri, "CertificateType", 6897e860f15SJohn Edward Broadbent certificateType)) 6905968caeeSMarri Devender Rao { 6915968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Required parameters are missing"; 6925968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 6935968caeeSMarri Devender Rao return; 6945968caeeSMarri Devender Rao } 6955968caeeSMarri Devender Rao 6965968caeeSMarri Devender Rao if (!certificateType) 6975968caeeSMarri Devender Rao { 6985968caeeSMarri Devender Rao // should never happen, but it never hurts to be paranoid. 6995968caeeSMarri Devender Rao return; 7005968caeeSMarri Devender Rao } 7015968caeeSMarri Devender Rao if (certificateType != "PEM") 7025968caeeSMarri Devender Rao { 7035968caeeSMarri Devender Rao messages::actionParameterNotSupported( 7045968caeeSMarri Devender Rao asyncResp->res, "CertificateType", "ReplaceCertificate"); 7055968caeeSMarri Devender Rao return; 7065968caeeSMarri Devender Rao } 7075968caeeSMarri Devender Rao 7085968caeeSMarri Devender Rao std::string certURI; 7095968caeeSMarri Devender Rao if (!redfish::json_util::readJson(certificateUri, asyncResp->res, 7105968caeeSMarri Devender Rao "@odata.id", certURI)) 7115968caeeSMarri Devender Rao { 7125968caeeSMarri Devender Rao messages::actionParameterMissing( 7135968caeeSMarri Devender Rao asyncResp->res, "ReplaceCertificate", "CertificateUri"); 7145968caeeSMarri Devender Rao return; 7155968caeeSMarri Devender Rao } 7165968caeeSMarri Devender Rao 7175968caeeSMarri Devender Rao BMCWEB_LOG_INFO << "Certificate URI to replace" << certURI; 7185968caeeSMarri Devender Rao long id = getIDFromURL(certURI); 7195968caeeSMarri Devender Rao if (id < 0) 7205968caeeSMarri Devender Rao { 7217e860f15SJohn Edward Broadbent messages::actionParameterValueFormatError( 7227e860f15SJohn Edward Broadbent asyncResp->res, certURI, "CertificateUri", 7235968caeeSMarri Devender Rao "ReplaceCertificate"); 7245968caeeSMarri Devender Rao return; 7255968caeeSMarri Devender Rao } 7265968caeeSMarri Devender Rao std::string objectPath; 7275968caeeSMarri Devender Rao std::string name; 72837cce918SMarri Devender Rao std::string service; 7290fda0f12SGeorge Liu if (boost::starts_with( 7300fda0f12SGeorge Liu certURI, 7310fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")) 7325968caeeSMarri Devender Rao { 7337e860f15SJohn Edward Broadbent objectPath = std::string(certs::httpsObjectPath) + "/" + 7347e860f15SJohn Edward Broadbent std::to_string(id); 7355968caeeSMarri Devender Rao name = "HTTPS certificate"; 73637cce918SMarri Devender Rao service = certs::httpsServiceName; 73737cce918SMarri Devender Rao } 73837cce918SMarri Devender Rao else if (boost::starts_with( 7397e860f15SJohn Edward Broadbent certURI, 7407e860f15SJohn Edward Broadbent "/redfish/v1/AccountService/LDAP/Certificates/")) 74137cce918SMarri Devender Rao { 7427e860f15SJohn Edward Broadbent objectPath = std::string(certs::ldapObjectPath) + "/" + 7437e860f15SJohn Edward Broadbent std::to_string(id); 74437cce918SMarri Devender Rao name = "LDAP certificate"; 74537cce918SMarri Devender Rao service = certs::ldapServiceName; 7465968caeeSMarri Devender Rao } 747cfcd5f6bSMarri Devender Rao else if (boost::starts_with( 748cfcd5f6bSMarri Devender Rao certURI, 749cfcd5f6bSMarri Devender Rao "/redfish/v1/Managers/bmc/Truststore/Certificates/")) 750cfcd5f6bSMarri Devender Rao { 751cfcd5f6bSMarri Devender Rao objectPath = std::string(certs::authorityObjectPath) + "/" + 752cfcd5f6bSMarri Devender Rao std::to_string(id); 753cfcd5f6bSMarri Devender Rao name = "TrustStore certificate"; 754cfcd5f6bSMarri Devender Rao service = certs::authorityServiceName; 755cfcd5f6bSMarri Devender Rao } 7565968caeeSMarri Devender Rao else 7575968caeeSMarri Devender Rao { 7585968caeeSMarri Devender Rao messages::actionParameterNotSupported( 7595968caeeSMarri Devender Rao asyncResp->res, "CertificateUri", "ReplaceCertificate"); 7605968caeeSMarri Devender Rao return; 7615968caeeSMarri Devender Rao } 7625968caeeSMarri Devender Rao 7635968caeeSMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 7645968caeeSMarri Devender Rao std::make_shared<CertificateFile>(certificate); 7655968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 76637cce918SMarri Devender Rao [asyncResp, certFile, objectPath, service, certURI, id, 7675968caeeSMarri Devender Rao name](const boost::system::error_code ec) { 7685968caeeSMarri Devender Rao if (ec) 7695968caeeSMarri Devender Rao { 7705968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 7718aae75adSMarri Devender Rao messages::resourceNotFound(asyncResp->res, name, 7728aae75adSMarri Devender Rao std::to_string(id)); 7735968caeeSMarri Devender Rao return; 7745968caeeSMarri Devender Rao } 77537cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, service, id, 7765968caeeSMarri Devender Rao certURI, name); 7775968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" 7785968caeeSMarri Devender Rao << certFile->getCertFilePath(); 7795968caeeSMarri Devender Rao }, 7805968caeeSMarri Devender Rao service, objectPath, certs::certReplaceIntf, "Replace", 7815968caeeSMarri Devender Rao certFile->getCertFilePath()); 7827e860f15SJohn Edward Broadbent }); 7837e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionsReplaceCertificate 7845968caeeSMarri Devender Rao 7855968caeeSMarri Devender Rao /** 7865968caeeSMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 7875968caeeSMarri Devender Rao * of a component, account or service. 7885968caeeSMarri Devender Rao */ 7895968caeeSMarri Devender Rao 7907e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificate(App& app) 7915968caeeSMarri Devender Rao { 7927e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 7937e860f15SJohn Edward Broadbent app, 7947e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/<str>/") 795ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 7967e860f15SJohn Edward Broadbent .methods( 7977e860f15SJohn Edward Broadbent boost::beast::http::verb:: 7987e860f15SJohn Edward Broadbent get)([](const crow::Request& req, 7997e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 8007e860f15SJohn Edward Broadbent const std::string& param) -> void { 8017e860f15SJohn Edward Broadbent if (param.empty()) 8025968caeeSMarri Devender Rao { 8035968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 8045968caeeSMarri Devender Rao return; 8055968caeeSMarri Devender Rao } 8065968caeeSMarri Devender Rao long id = getIDFromURL(req.url); 8075968caeeSMarri Devender Rao 8087e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG << "HTTPSCertificate::doGet ID=" 8097e860f15SJohn Edward Broadbent << std::to_string(id); 8105968caeeSMarri Devender Rao std::string certURL = 8115968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" + 8125968caeeSMarri Devender Rao std::to_string(id); 8135968caeeSMarri Devender Rao std::string objectPath = certs::httpsObjectPath; 8145968caeeSMarri Devender Rao objectPath += "/"; 8155968caeeSMarri Devender Rao objectPath += std::to_string(id); 8167e860f15SJohn Edward Broadbent getCertificateProperties(asyncResp, objectPath, 8177e860f15SJohn Edward Broadbent certs::httpsServiceName, id, certURL, 8187e860f15SJohn Edward Broadbent "HTTPS Certificate"); 8197e860f15SJohn Edward Broadbent }); 8205968caeeSMarri Devender Rao } 8215968caeeSMarri Devender Rao 8225968caeeSMarri Devender Rao /** 8235968caeeSMarri Devender Rao * Collection of HTTPS certificates 8245968caeeSMarri Devender Rao */ 8257e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificateCollection(App& app) 8265968caeeSMarri Devender Rao { 8277e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 8285968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/") 829ed398213SEd Tanous .privileges(redfish::privileges::getCertificateCollection) 8307e860f15SJohn Edward Broadbent .methods( 8317e860f15SJohn Edward Broadbent boost::beast::http::verb:: 8327e860f15SJohn Edward Broadbent get)([](const crow::Request&, 8337e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 8348d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 8355968caeeSMarri Devender Rao {"@odata.id", 8365968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"}, 8375968caeeSMarri Devender Rao {"@odata.type", "#CertificateCollection.CertificateCollection"}, 8385968caeeSMarri Devender Rao {"Name", "HTTPS Certificates Collection"}, 8395968caeeSMarri Devender Rao {"Description", "A Collection of HTTPS certificate instances"}}; 8408d1b46d7Szhanghch05 8415968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 8425968caeeSMarri Devender Rao [asyncResp](const boost::system::error_code ec, 8435968caeeSMarri Devender Rao const ManagedObjectType& certs) { 8445968caeeSMarri Devender Rao if (ec) 8455968caeeSMarri Devender Rao { 8465968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 8475968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 8485968caeeSMarri Devender Rao return; 8495968caeeSMarri Devender Rao } 8507e860f15SJohn Edward Broadbent nlohmann::json& members = 8517e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Members"]; 8525968caeeSMarri Devender Rao members = nlohmann::json::array(); 8535968caeeSMarri Devender Rao for (const auto& cert : certs) 8545968caeeSMarri Devender Rao { 8555968caeeSMarri Devender Rao long id = getIDFromURL(cert.first.str); 85637cce918SMarri Devender Rao if (id >= 0) 8575968caeeSMarri Devender Rao { 8585968caeeSMarri Devender Rao members.push_back( 8595968caeeSMarri Devender Rao {{"@odata.id", 8600fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" + 8615968caeeSMarri Devender Rao std::to_string(id)}}); 8625968caeeSMarri Devender Rao } 8635968caeeSMarri Devender Rao } 8645968caeeSMarri Devender Rao asyncResp->res.jsonValue["Members@odata.count"] = 8655968caeeSMarri Devender Rao members.size(); 8665968caeeSMarri Devender Rao }, 86737cce918SMarri Devender Rao certs::httpsServiceName, certs::httpsObjectPath, 86837cce918SMarri Devender Rao certs::dbusObjManagerIntf, "GetManagedObjects"); 8697e860f15SJohn Edward Broadbent }); 8705968caeeSMarri Devender Rao 8717e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 8727e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/") 873ed398213SEd Tanous .privileges(redfish::privileges::postCertificateCollection) 8740fda0f12SGeorge Liu .methods( 8750fda0f12SGeorge Liu boost::beast::http::verb:: 8760fda0f12SGeorge Liu post)([](const crow::Request& req, 8777e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 8785968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost"; 8798d1b46d7Szhanghch05 8800fda0f12SGeorge Liu asyncResp->res.jsonValue = {{"Name", "HTTPS Certificate"}, 8815968caeeSMarri Devender Rao {"Description", "HTTPS Certificate"}}; 8825968caeeSMarri Devender Rao 8837e860f15SJohn Edward Broadbent std::string certFileBody = 8847e860f15SJohn Edward Broadbent getCertificateFromReqBody(asyncResp, req); 88558eb238fSKowalski, Kamil 88658eb238fSKowalski, Kamil if (certFileBody.empty()) 88758eb238fSKowalski, Kamil { 8880fda0f12SGeorge Liu BMCWEB_LOG_ERROR << "Cannot get certificate from request body."; 889a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 89058eb238fSKowalski, Kamil return; 89158eb238fSKowalski, Kamil } 89258eb238fSKowalski, Kamil 8935968caeeSMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 89458eb238fSKowalski, Kamil std::make_shared<CertificateFile>(certFileBody); 8955968caeeSMarri Devender Rao 8965968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 897656ec7e3SZbigniew Kurzynski [asyncResp, certFile](const boost::system::error_code ec, 898656ec7e3SZbigniew Kurzynski const std::string& objectPath) { 8995968caeeSMarri Devender Rao if (ec) 9005968caeeSMarri Devender Rao { 9015968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 9025968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 9035968caeeSMarri Devender Rao return; 9045968caeeSMarri Devender Rao } 905656ec7e3SZbigniew Kurzynski long certId = getIDFromURL(objectPath); 906656ec7e3SZbigniew Kurzynski if (certId < 0) 907656ec7e3SZbigniew Kurzynski { 908656ec7e3SZbigniew Kurzynski BMCWEB_LOG_ERROR << "Invalid objectPath value" 909656ec7e3SZbigniew Kurzynski << objectPath; 910656ec7e3SZbigniew Kurzynski messages::internalError(asyncResp->res); 911656ec7e3SZbigniew Kurzynski return; 912656ec7e3SZbigniew Kurzynski } 9135968caeeSMarri Devender Rao std::string certURL = 9140fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" + 9155968caeeSMarri Devender Rao std::to_string(certId); 9160fda0f12SGeorge Liu getCertificateProperties(asyncResp, objectPath, 9170fda0f12SGeorge Liu certs::httpsServiceName, certId, 9180fda0f12SGeorge Liu certURL, "HTTPS Certificate"); 9195968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" 9205968caeeSMarri Devender Rao << certFile->getCertFilePath(); 9215968caeeSMarri Devender Rao }, 92237cce918SMarri Devender Rao certs::httpsServiceName, certs::httpsObjectPath, 9230fda0f12SGeorge Liu certs::certInstallIntf, "Install", certFile->getCertFilePath()); 9247e860f15SJohn Edward Broadbent }); 9257e860f15SJohn Edward Broadbent } // requestRoutesHTTPSCertificateCollection 9265968caeeSMarri Devender Rao 9275968caeeSMarri Devender Rao /** 92837cce918SMarri Devender Rao * @brief Retrieve the certificates installed list and append to the 92937cce918SMarri Devender Rao * response 93037cce918SMarri Devender Rao * 93137cce918SMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 93237cce918SMarri Devender Rao * @param[in] certURL Path of the certificate object 93337cce918SMarri Devender Rao * @param[in] path Path of the D-Bus service object 93437cce918SMarri Devender Rao * @return None 93537cce918SMarri Devender Rao */ 9364f48d5f6SEd Tanous inline void 9374f48d5f6SEd Tanous getCertificateLocations(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 9388d1b46d7Szhanghch05 const std::string& certURL, const std::string& path, 93937cce918SMarri Devender Rao const std::string& service) 94037cce918SMarri Devender Rao { 94137cce918SMarri Devender Rao BMCWEB_LOG_DEBUG << "getCertificateLocations URI=" << certURL 94237cce918SMarri Devender Rao << " Path=" << path << " service= " << service; 94337cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 94437cce918SMarri Devender Rao [asyncResp, certURL](const boost::system::error_code ec, 94537cce918SMarri Devender Rao const ManagedObjectType& certs) { 94637cce918SMarri Devender Rao if (ec) 94737cce918SMarri Devender Rao { 9489c8e039eSJonathan Doman BMCWEB_LOG_WARNING 9499c8e039eSJonathan Doman << "Certificate collection query failed: " << ec 9509c8e039eSJonathan Doman << ", skipping " << certURL; 95137cce918SMarri Devender Rao return; 95237cce918SMarri Devender Rao } 95337cce918SMarri Devender Rao nlohmann::json& links = 95437cce918SMarri Devender Rao asyncResp->res.jsonValue["Links"]["Certificates"]; 95537cce918SMarri Devender Rao for (auto& cert : certs) 95637cce918SMarri Devender Rao { 95737cce918SMarri Devender Rao long id = getIDFromURL(cert.first.str); 95837cce918SMarri Devender Rao if (id >= 0) 95937cce918SMarri Devender Rao { 96037cce918SMarri Devender Rao links.push_back( 96137cce918SMarri Devender Rao {{"@odata.id", certURL + std::to_string(id)}}); 96237cce918SMarri Devender Rao } 96337cce918SMarri Devender Rao } 96437cce918SMarri Devender Rao asyncResp->res.jsonValue["Links"]["Certificates@odata.count"] = 96537cce918SMarri Devender Rao links.size(); 96637cce918SMarri Devender Rao }, 96737cce918SMarri Devender Rao service, path, certs::dbusObjManagerIntf, "GetManagedObjects"); 9685968caeeSMarri Devender Rao } 9697e860f15SJohn Edward Broadbent 9707e860f15SJohn Edward Broadbent /** 9717e860f15SJohn Edward Broadbent * The certificate location schema defines a resource that an administrator 9727e860f15SJohn Edward Broadbent * can use in order to locate all certificates installed on a given service. 9737e860f15SJohn Edward Broadbent */ 9747e860f15SJohn Edward Broadbent inline void requestRoutesCertificateLocations(App& app) 9757e860f15SJohn Edward Broadbent { 9767e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/") 977ed398213SEd Tanous .privileges(redfish::privileges::getCertificateLocations) 9787e860f15SJohn Edward Broadbent .methods( 9797e860f15SJohn Edward Broadbent boost::beast::http::verb:: 9807e860f15SJohn Edward Broadbent get)([](const crow::Request&, 9817e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 9827e860f15SJohn Edward Broadbent asyncResp->res.jsonValue = { 9837e860f15SJohn Edward Broadbent {"@odata.id", 9847e860f15SJohn Edward Broadbent "/redfish/v1/CertificateService/CertificateLocations"}, 9857e860f15SJohn Edward Broadbent {"@odata.type", 9867e860f15SJohn Edward Broadbent "#CertificateLocations.v1_0_0.CertificateLocations"}, 9877e860f15SJohn Edward Broadbent {"Name", "Certificate Locations"}, 9887e860f15SJohn Edward Broadbent {"Id", "CertificateLocations"}, 9897e860f15SJohn Edward Broadbent {"Description", 9907e860f15SJohn Edward Broadbent "Defines a resource that an administrator can use in order to " 9917e860f15SJohn Edward Broadbent "locate all certificates installed on a given service"}}; 9927e860f15SJohn Edward Broadbent 9937e860f15SJohn Edward Broadbent nlohmann::json& links = 9947e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Links"]["Certificates"]; 9957e860f15SJohn Edward Broadbent links = nlohmann::json::array(); 9967e860f15SJohn Edward Broadbent getCertificateLocations( 9977e860f15SJohn Edward Broadbent asyncResp, 9987e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/", 9997e860f15SJohn Edward Broadbent certs::httpsObjectPath, certs::httpsServiceName); 10007e860f15SJohn Edward Broadbent getCertificateLocations( 10017e860f15SJohn Edward Broadbent asyncResp, "/redfish/v1/AccountService/LDAP/Certificates/", 10027e860f15SJohn Edward Broadbent certs::ldapObjectPath, certs::ldapServiceName); 10037e860f15SJohn Edward Broadbent getCertificateLocations( 10047e860f15SJohn Edward Broadbent asyncResp, "/redfish/v1/Managers/bmc/Truststore/Certificates/", 10057e860f15SJohn Edward Broadbent certs::authorityObjectPath, certs::authorityServiceName); 10067e860f15SJohn Edward Broadbent }); 10077e860f15SJohn Edward Broadbent } 10087e860f15SJohn Edward Broadbent // requestRoutesCertificateLocations 100937cce918SMarri Devender Rao 101037cce918SMarri Devender Rao /** 101137cce918SMarri Devender Rao * Collection of LDAP certificates 101237cce918SMarri Devender Rao */ 10137e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificateCollection(App& app) 101437cce918SMarri Devender Rao { 10157e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/") 1016ed398213SEd Tanous .privileges(redfish::privileges::getCertificateCollection) 10170fda0f12SGeorge Liu .methods( 10180fda0f12SGeorge Liu boost::beast::http::verb:: 10190fda0f12SGeorge Liu get)([](const crow::Request&, 10207e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 10218d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 10220fda0f12SGeorge Liu {"@odata.id", "/redfish/v1/AccountService/LDAP/Certificates"}, 10230fda0f12SGeorge Liu {"@odata.type", "#CertificateCollection.CertificateCollection"}, 102437cce918SMarri Devender Rao {"Name", "LDAP Certificates Collection"}, 10250fda0f12SGeorge Liu {"Description", "A Collection of LDAP certificate instances"}}; 10268d1b46d7Szhanghch05 102737cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 102837cce918SMarri Devender Rao [asyncResp](const boost::system::error_code ec, 102937cce918SMarri Devender Rao const ManagedObjectType& certs) { 10307e860f15SJohn Edward Broadbent nlohmann::json& members = 10317e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Members"]; 10329c8e039eSJonathan Doman nlohmann::json& count = 10339c8e039eSJonathan Doman asyncResp->res.jsonValue["Members@odata.count"]; 10349c8e039eSJonathan Doman members = nlohmann::json::array(); 10359c8e039eSJonathan Doman count = 0; 103637cce918SMarri Devender Rao if (ec) 103737cce918SMarri Devender Rao { 10380fda0f12SGeorge Liu BMCWEB_LOG_WARNING << "LDAP certificate query failed: " 10390fda0f12SGeorge Liu << ec; 104037cce918SMarri Devender Rao return; 104137cce918SMarri Devender Rao } 104237cce918SMarri Devender Rao for (const auto& cert : certs) 104337cce918SMarri Devender Rao { 104437cce918SMarri Devender Rao long id = getIDFromURL(cert.first.str); 104537cce918SMarri Devender Rao if (id >= 0) 104637cce918SMarri Devender Rao { 104737cce918SMarri Devender Rao members.push_back( 10480fda0f12SGeorge Liu {{"@odata.id", 10490fda0f12SGeorge Liu "/redfish/v1/AccountService/LDAP/Certificates/" + 105037cce918SMarri Devender Rao std::to_string(id)}}); 105137cce918SMarri Devender Rao } 105237cce918SMarri Devender Rao } 10539c8e039eSJonathan Doman count = members.size(); 105437cce918SMarri Devender Rao }, 105537cce918SMarri Devender Rao certs::ldapServiceName, certs::ldapObjectPath, 105637cce918SMarri Devender Rao certs::dbusObjManagerIntf, "GetManagedObjects"); 10577e860f15SJohn Edward Broadbent }); 105837cce918SMarri Devender Rao 10597e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/") 1060ed398213SEd Tanous .privileges(redfish::privileges::postCertificateCollection) 10617e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 10627e860f15SJohn Edward Broadbent [](const crow::Request& req, 10637e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 10647e860f15SJohn Edward Broadbent std::string certFileBody = 10657e860f15SJohn Edward Broadbent getCertificateFromReqBody(asyncResp, req); 106658eb238fSKowalski, Kamil 106758eb238fSKowalski, Kamil if (certFileBody.empty()) 106858eb238fSKowalski, Kamil { 10697e860f15SJohn Edward Broadbent BMCWEB_LOG_ERROR 10707e860f15SJohn Edward Broadbent << "Cannot get certificate from request body."; 1071a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 107258eb238fSKowalski, Kamil return; 107358eb238fSKowalski, Kamil } 107458eb238fSKowalski, Kamil 107558eb238fSKowalski, Kamil std::shared_ptr<CertificateFile> certFile = 107658eb238fSKowalski, Kamil std::make_shared<CertificateFile>(certFileBody); 107758eb238fSKowalski, Kamil 107837cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 1079656ec7e3SZbigniew Kurzynski [asyncResp, certFile](const boost::system::error_code ec, 1080656ec7e3SZbigniew Kurzynski const std::string& objectPath) { 108137cce918SMarri Devender Rao if (ec) 108237cce918SMarri Devender Rao { 108337cce918SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 108437cce918SMarri Devender Rao messages::internalError(asyncResp->res); 108537cce918SMarri Devender Rao return; 108637cce918SMarri Devender Rao } 1087656ec7e3SZbigniew Kurzynski long certId = getIDFromURL(objectPath); 1088656ec7e3SZbigniew Kurzynski if (certId < 0) 1089656ec7e3SZbigniew Kurzynski { 1090656ec7e3SZbigniew Kurzynski BMCWEB_LOG_ERROR << "Invalid objectPath value" 1091656ec7e3SZbigniew Kurzynski << objectPath; 1092656ec7e3SZbigniew Kurzynski messages::internalError(asyncResp->res); 1093656ec7e3SZbigniew Kurzynski return; 1094656ec7e3SZbigniew Kurzynski } 109537cce918SMarri Devender Rao std::string certURL = 109637cce918SMarri Devender Rao "/redfish/v1/AccountService/LDAP/Certificates/" + 109737cce918SMarri Devender Rao std::to_string(certId); 109837cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, 109937cce918SMarri Devender Rao certs::ldapServiceName, certId, 110037cce918SMarri Devender Rao certURL, "LDAP Certificate"); 110137cce918SMarri Devender Rao BMCWEB_LOG_DEBUG << "LDAP certificate install file=" 110237cce918SMarri Devender Rao << certFile->getCertFilePath(); 110337cce918SMarri Devender Rao }, 110437cce918SMarri Devender Rao certs::ldapServiceName, certs::ldapObjectPath, 11057e860f15SJohn Edward Broadbent certs::certInstallIntf, "Install", 11067e860f15SJohn Edward Broadbent certFile->getCertFilePath()); 11077e860f15SJohn Edward Broadbent }); 11087e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificateCollection 110937cce918SMarri Devender Rao 111037cce918SMarri Devender Rao /** 111137cce918SMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 111237cce918SMarri Devender Rao * of a component, account or service. 111337cce918SMarri Devender Rao */ 11147e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificate(App& app) 111537cce918SMarri Devender Rao { 11167e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/") 1117ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 11187e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 11197e860f15SJohn Edward Broadbent [](const crow::Request& req, 11207e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 11217e860f15SJohn Edward Broadbent const std::string&) { 112237cce918SMarri Devender Rao long id = getIDFromURL(req.url); 112337cce918SMarri Devender Rao if (id < 0) 112437cce918SMarri Devender Rao { 112537cce918SMarri Devender Rao BMCWEB_LOG_ERROR << "Invalid url value" << req.url; 112637cce918SMarri Devender Rao messages::internalError(asyncResp->res); 112737cce918SMarri Devender Rao return; 112837cce918SMarri Devender Rao } 11297e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" 11307e860f15SJohn Edward Broadbent << std::to_string(id); 11317e860f15SJohn Edward Broadbent std::string certURL = 11327e860f15SJohn Edward Broadbent "/redfish/v1/AccountService/LDAP/Certificates/" + 113337cce918SMarri Devender Rao std::to_string(id); 113437cce918SMarri Devender Rao std::string objectPath = certs::ldapObjectPath; 113537cce918SMarri Devender Rao objectPath += "/"; 113637cce918SMarri Devender Rao objectPath += std::to_string(id); 11377e860f15SJohn Edward Broadbent getCertificateProperties(asyncResp, objectPath, 11387e860f15SJohn Edward Broadbent certs::ldapServiceName, id, certURL, 11397e860f15SJohn Edward Broadbent "LDAP Certificate"); 11407e860f15SJohn Edward Broadbent }); 11417e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificate 1142cfcd5f6bSMarri Devender Rao /** 1143cfcd5f6bSMarri Devender Rao * Collection of TrustStoreCertificate certificates 1144cfcd5f6bSMarri Devender Rao */ 11457e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificateCollection(App& app) 1146cfcd5f6bSMarri Devender Rao { 11477e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/") 1148ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 11490fda0f12SGeorge Liu .methods( 11500fda0f12SGeorge Liu boost::beast::http::verb:: 11510fda0f12SGeorge Liu get)([](const crow::Request&, 11527e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 11538d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 11547e860f15SJohn Edward Broadbent {"@odata.id", 11557e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc/Truststore/Certificates/"}, 11560fda0f12SGeorge Liu {"@odata.type", "#CertificateCollection.CertificateCollection"}, 1157cfcd5f6bSMarri Devender Rao {"Name", "TrustStore Certificates Collection"}, 1158cfcd5f6bSMarri Devender Rao {"Description", 1159cfcd5f6bSMarri Devender Rao "A Collection of TrustStore certificate instances"}}; 11608d1b46d7Szhanghch05 1161cfcd5f6bSMarri Devender Rao crow::connections::systemBus->async_method_call( 1162cfcd5f6bSMarri Devender Rao [asyncResp](const boost::system::error_code ec, 1163cfcd5f6bSMarri Devender Rao const ManagedObjectType& certs) { 1164cfcd5f6bSMarri Devender Rao if (ec) 1165cfcd5f6bSMarri Devender Rao { 1166cfcd5f6bSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 1167cfcd5f6bSMarri Devender Rao messages::internalError(asyncResp->res); 1168cfcd5f6bSMarri Devender Rao return; 1169cfcd5f6bSMarri Devender Rao } 11707e860f15SJohn Edward Broadbent nlohmann::json& members = 11717e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Members"]; 1172cfcd5f6bSMarri Devender Rao members = nlohmann::json::array(); 1173cfcd5f6bSMarri Devender Rao for (const auto& cert : certs) 1174cfcd5f6bSMarri Devender Rao { 1175cfcd5f6bSMarri Devender Rao long id = getIDFromURL(cert.first.str); 1176cfcd5f6bSMarri Devender Rao if (id >= 0) 1177cfcd5f6bSMarri Devender Rao { 1178cfcd5f6bSMarri Devender Rao members.push_back( 11790fda0f12SGeorge Liu {{"@odata.id", 11800fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/Truststore/Certificates/" + 1181cfcd5f6bSMarri Devender Rao std::to_string(id)}}); 1182cfcd5f6bSMarri Devender Rao } 1183cfcd5f6bSMarri Devender Rao } 1184cfcd5f6bSMarri Devender Rao asyncResp->res.jsonValue["Members@odata.count"] = 1185cfcd5f6bSMarri Devender Rao members.size(); 1186cfcd5f6bSMarri Devender Rao }, 1187cfcd5f6bSMarri Devender Rao certs::authorityServiceName, certs::authorityObjectPath, 1188cfcd5f6bSMarri Devender Rao certs::dbusObjManagerIntf, "GetManagedObjects"); 11897e860f15SJohn Edward Broadbent }); 1190cfcd5f6bSMarri Devender Rao 11917e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/") 1192ed398213SEd Tanous .privileges(redfish::privileges::postCertificateCollection) 11930fda0f12SGeorge Liu .methods( 11940fda0f12SGeorge Liu boost::beast::http::verb:: 11950fda0f12SGeorge Liu post)([](const crow::Request& req, 11967e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 11977e860f15SJohn Edward Broadbent std::string certFileBody = 11987e860f15SJohn Edward Broadbent getCertificateFromReqBody(asyncResp, req); 1199a08752f5SZbigniew Kurzynski 1200a08752f5SZbigniew Kurzynski if (certFileBody.empty()) 1201a08752f5SZbigniew Kurzynski { 12020fda0f12SGeorge Liu BMCWEB_LOG_ERROR << "Cannot get certificate from request body."; 1203a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 1204a08752f5SZbigniew Kurzynski return; 1205a08752f5SZbigniew Kurzynski } 1206a08752f5SZbigniew Kurzynski 1207a08752f5SZbigniew Kurzynski std::shared_ptr<CertificateFile> certFile = 1208a08752f5SZbigniew Kurzynski std::make_shared<CertificateFile>(certFileBody); 1209cfcd5f6bSMarri Devender Rao crow::connections::systemBus->async_method_call( 1210656ec7e3SZbigniew Kurzynski [asyncResp, certFile](const boost::system::error_code ec, 1211656ec7e3SZbigniew Kurzynski const std::string& objectPath) { 1212cfcd5f6bSMarri Devender Rao if (ec) 1213cfcd5f6bSMarri Devender Rao { 1214cfcd5f6bSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 1215cfcd5f6bSMarri Devender Rao messages::internalError(asyncResp->res); 1216cfcd5f6bSMarri Devender Rao return; 1217cfcd5f6bSMarri Devender Rao } 1218656ec7e3SZbigniew Kurzynski long certId = getIDFromURL(objectPath); 1219656ec7e3SZbigniew Kurzynski if (certId < 0) 1220656ec7e3SZbigniew Kurzynski { 1221656ec7e3SZbigniew Kurzynski BMCWEB_LOG_ERROR << "Invalid objectPath value" 1222656ec7e3SZbigniew Kurzynski << objectPath; 1223656ec7e3SZbigniew Kurzynski messages::internalError(asyncResp->res); 1224656ec7e3SZbigniew Kurzynski return; 1225656ec7e3SZbigniew Kurzynski } 12260fda0f12SGeorge Liu std::string certURL = 12270fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/Truststore/Certificates/" + 1228cfcd5f6bSMarri Devender Rao std::to_string(certId); 1229656ec7e3SZbigniew Kurzynski 12307e860f15SJohn Edward Broadbent getCertificateProperties( 12317e860f15SJohn Edward Broadbent asyncResp, objectPath, certs::authorityServiceName, 12327e860f15SJohn Edward Broadbent certId, certURL, "TrustStore Certificate"); 12330fda0f12SGeorge Liu BMCWEB_LOG_DEBUG << "TrustStore certificate install file=" 1234cfcd5f6bSMarri Devender Rao << certFile->getCertFilePath(); 1235cfcd5f6bSMarri Devender Rao }, 1236cfcd5f6bSMarri Devender Rao certs::authorityServiceName, certs::authorityObjectPath, 12370fda0f12SGeorge Liu certs::certInstallIntf, "Install", certFile->getCertFilePath()); 12387e860f15SJohn Edward Broadbent }); 12397e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificateCollection 1240cfcd5f6bSMarri Devender Rao 1241cfcd5f6bSMarri Devender Rao /** 1242cfcd5f6bSMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 1243cfcd5f6bSMarri Devender Rao * of a component, account or service. 1244cfcd5f6bSMarri Devender Rao */ 12457e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificate(App& app) 1246cfcd5f6bSMarri Devender Rao { 12477e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/") 1248ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 12497e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 12507e860f15SJohn Edward Broadbent [](const crow::Request& req, 12517e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 12527e860f15SJohn Edward Broadbent const std::string&) { 1253cfcd5f6bSMarri Devender Rao long id = getIDFromURL(req.url); 1254cfcd5f6bSMarri Devender Rao if (id < 0) 1255cfcd5f6bSMarri Devender Rao { 1256cfcd5f6bSMarri Devender Rao BMCWEB_LOG_ERROR << "Invalid url value" << req.url; 1257cfcd5f6bSMarri Devender Rao messages::internalError(asyncResp->res); 1258cfcd5f6bSMarri Devender Rao return; 1259cfcd5f6bSMarri Devender Rao } 1260cfcd5f6bSMarri Devender Rao BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doGet ID=" 1261cfcd5f6bSMarri Devender Rao << std::to_string(id); 1262cfcd5f6bSMarri Devender Rao std::string certURL = 1263cfcd5f6bSMarri Devender Rao "/redfish/v1/Managers/bmc/Truststore/Certificates/" + 1264cfcd5f6bSMarri Devender Rao std::to_string(id); 1265cfcd5f6bSMarri Devender Rao std::string objectPath = certs::authorityObjectPath; 1266cfcd5f6bSMarri Devender Rao objectPath += "/"; 1267cfcd5f6bSMarri Devender Rao objectPath += std::to_string(id); 1268cfcd5f6bSMarri Devender Rao getCertificateProperties(asyncResp, objectPath, 12697e860f15SJohn Edward Broadbent certs::authorityServiceName, id, 12707e860f15SJohn Edward Broadbent certURL, "TrustStore Certificate"); 12717e860f15SJohn Edward Broadbent }); 127207a60299SZbigniew Kurzynski 12737e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/") 1274ed398213SEd Tanous .privileges(redfish::privileges::deleteCertificate) 12757e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::delete_)( 12767e860f15SJohn Edward Broadbent [](const crow::Request& req, 12777e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 12787e860f15SJohn Edward Broadbent const std::string& param) { 12797e860f15SJohn Edward Broadbent if (param.empty()) 128007a60299SZbigniew Kurzynski { 128107a60299SZbigniew Kurzynski messages::internalError(asyncResp->res); 128207a60299SZbigniew Kurzynski return; 128307a60299SZbigniew Kurzynski } 128407a60299SZbigniew Kurzynski 128507a60299SZbigniew Kurzynski long id = getIDFromURL(req.url); 128607a60299SZbigniew Kurzynski if (id < 0) 128707a60299SZbigniew Kurzynski { 128807a60299SZbigniew Kurzynski BMCWEB_LOG_ERROR << "Invalid url value: " << req.url; 12897e860f15SJohn Edward Broadbent messages::resourceNotFound(asyncResp->res, 12907e860f15SJohn Edward Broadbent "TrustStore Certificate", 129107a60299SZbigniew Kurzynski std::string(req.url)); 129207a60299SZbigniew Kurzynski return; 129307a60299SZbigniew Kurzynski } 129407a60299SZbigniew Kurzynski BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doDelete ID=" 129507a60299SZbigniew Kurzynski << std::to_string(id); 129607a60299SZbigniew Kurzynski std::string certPath = certs::authorityObjectPath; 129707a60299SZbigniew Kurzynski certPath += "/"; 129807a60299SZbigniew Kurzynski certPath += std::to_string(id); 129907a60299SZbigniew Kurzynski 130007a60299SZbigniew Kurzynski crow::connections::systemBus->async_method_call( 130107a60299SZbigniew Kurzynski [asyncResp, id](const boost::system::error_code ec) { 130207a60299SZbigniew Kurzynski if (ec) 130307a60299SZbigniew Kurzynski { 130407a60299SZbigniew Kurzynski messages::resourceNotFound(asyncResp->res, 130507a60299SZbigniew Kurzynski "TrustStore Certificate", 130607a60299SZbigniew Kurzynski std::to_string(id)); 130707a60299SZbigniew Kurzynski return; 130807a60299SZbigniew Kurzynski } 130907a60299SZbigniew Kurzynski BMCWEB_LOG_INFO << "Certificate deleted"; 13107e860f15SJohn Edward Broadbent asyncResp->res.result( 13117e860f15SJohn Edward Broadbent boost::beast::http::status::no_content); 131207a60299SZbigniew Kurzynski }, 131307a60299SZbigniew Kurzynski certs::authorityServiceName, certPath, certs::objDeleteIntf, 131407a60299SZbigniew Kurzynski "Delete"); 13157e860f15SJohn Edward Broadbent }); 13167e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificate 13175968caeeSMarri Devender Rao } // namespace redfish 1318