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* certInstallIntf = "xyz.openbmc_project.Certs.Install"; 165968caeeSMarri Devender Rao constexpr char const* certReplaceIntf = "xyz.openbmc_project.Certs.Replace"; 1707a60299SZbigniew Kurzynski constexpr char const* objDeleteIntf = "xyz.openbmc_project.Object.Delete"; 185968caeeSMarri Devender Rao constexpr char const* certPropIntf = "xyz.openbmc_project.Certs.Certificate"; 195968caeeSMarri Devender Rao constexpr char const* dbusPropIntf = "org.freedesktop.DBus.Properties"; 205968caeeSMarri Devender Rao constexpr char const* dbusObjManagerIntf = "org.freedesktop.DBus.ObjectManager"; 2137cce918SMarri Devender Rao constexpr char const* httpsServiceName = 2237cce918SMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Server.Https"; 2337cce918SMarri Devender Rao constexpr char const* ldapServiceName = 2437cce918SMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Client.Ldap"; 25cfcd5f6bSMarri Devender Rao constexpr char const* authorityServiceName = 26cfcd5f6bSMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Authority.Ldap"; 27c6a8dfb1SJiaqing Zhao constexpr char const* baseObjectPath = "/xyz/openbmc_project/certs"; 28c6a8dfb1SJiaqing Zhao constexpr char const* httpsObjectPath = 29c6a8dfb1SJiaqing Zhao "/xyz/openbmc_project/certs/server/https"; 30c6a8dfb1SJiaqing Zhao constexpr char const* ldapObjectPath = "/xyz/openbmc_project/certs/client/ldap"; 31cfcd5f6bSMarri Devender Rao constexpr char const* authorityObjectPath = 32cfcd5f6bSMarri Devender Rao "/xyz/openbmc_project/certs/authority/ldap"; 335968caeeSMarri Devender Rao } // namespace certs 345968caeeSMarri Devender Rao 355968caeeSMarri Devender Rao /** 365968caeeSMarri Devender Rao * The Certificate schema defines a Certificate Service which represents the 375968caeeSMarri Devender Rao * actions available to manage certificates and links to where certificates 385968caeeSMarri Devender Rao * are installed. 395968caeeSMarri Devender Rao */ 407e860f15SJohn Edward Broadbent 415968caeeSMarri Devender Rao // TODO: Issue#61 No entries are available for Certificate 424e0453b1SGunnar Mills // service at https://www.dmtf.org/standards/redfish 435968caeeSMarri Devender Rao // "redfish standard registries". Need to modify after DMTF 445968caeeSMarri Devender Rao // publish Privilege details for certificate service 455968caeeSMarri Devender Rao 467e860f15SJohn Edward Broadbent inline void requestRoutesCertificateService(App& app) 475968caeeSMarri Devender Rao { 487e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/") 49ed398213SEd Tanous .privileges(redfish::privileges::getCertificateService) 50002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 51002d39b4SEd Tanous [&app](const crow::Request& req, 52002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 533ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 5445ca1b86SEd Tanous { 5545ca1b86SEd Tanous return; 5645ca1b86SEd Tanous } 571476687dSEd Tanous 581476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 591476687dSEd Tanous "#CertificateService.v1_0_0.CertificateService"; 601476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 611476687dSEd Tanous "/redfish/v1/CertificateService"; 621476687dSEd Tanous asyncResp->res.jsonValue["Id"] = "CertificateService"; 631476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "Certificate Service"; 641476687dSEd Tanous asyncResp->res.jsonValue["Description"] = 651476687dSEd Tanous "Actions available to manage certificates"; 6672048780SAbhishek Patel // /redfish/v1/CertificateService/CertificateLocations is something 6772048780SAbhishek Patel // only ConfigureManager can access then only display when the user 6872048780SAbhishek Patel // has permissions ConfigureManager 6972048780SAbhishek Patel Privileges effectiveUserPrivileges = 7072048780SAbhishek Patel redfish::getUserPrivileges(req.userRole); 7172048780SAbhishek Patel if (isOperationAllowedWithPrivileges({{"ConfigureManager"}}, 7272048780SAbhishek Patel effectiveUserPrivileges)) 7372048780SAbhishek Patel { 741476687dSEd Tanous asyncResp->res.jsonValue["CertificateLocations"]["@odata.id"] = 751476687dSEd Tanous "/redfish/v1/CertificateService/CertificateLocations"; 7672048780SAbhishek Patel } 770fda0f12SGeorge Liu asyncResp->res 78002d39b4SEd Tanous .jsonValue["Actions"]["#CertificateService.ReplaceCertificate"] = { 790fda0f12SGeorge Liu {"target", 800fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate"}, 815968caeeSMarri Devender Rao {"CertificateType@Redfish.AllowableValues", {"PEM"}}}; 827e860f15SJohn Edward Broadbent asyncResp->res 837e860f15SJohn Edward Broadbent .jsonValue["Actions"]["#CertificateService.GenerateCSR"] = { 840fda0f12SGeorge Liu {"target", 850fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR"}}; 867e860f15SJohn Edward Broadbent }); 877e860f15SJohn Edward Broadbent } // requestRoutesCertificateService 8837cce918SMarri Devender Rao 895968caeeSMarri Devender Rao /** 905968caeeSMarri Devender Rao * @brief Find the ID specified in the URL 915968caeeSMarri Devender Rao * Finds the numbers specified after the last "/" in the URL and returns. 925968caeeSMarri Devender Rao * @param[in] path URL 935968caeeSMarri Devender Rao * @return -1 on failure and number on success 945968caeeSMarri Devender Rao */ 9523a21a1cSEd Tanous inline long getIDFromURL(const std::string_view url) 965968caeeSMarri Devender Rao { 97f23b7296SEd Tanous std::size_t found = url.rfind('/'); 985968caeeSMarri Devender Rao if (found == std::string::npos) 995968caeeSMarri Devender Rao { 1005968caeeSMarri Devender Rao return -1; 1015968caeeSMarri Devender Rao } 102e6604b11SIwona Klimaszewska 1035968caeeSMarri Devender Rao if ((found + 1) < url.length()) 1045968caeeSMarri Devender Rao { 1055968caeeSMarri Devender Rao std::string_view str = url.substr(found + 1); 106e6604b11SIwona Klimaszewska 107e6604b11SIwona Klimaszewska return boost::convert<long>(str, boost::cnv::strtol()).value_or(-1); 1085968caeeSMarri Devender Rao } 109e6604b11SIwona Klimaszewska 1105968caeeSMarri Devender Rao return -1; 1115968caeeSMarri Devender Rao } 1125968caeeSMarri Devender Rao 1138d1b46d7Szhanghch05 inline std::string getCertificateFromReqBody( 1148d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 11558eb238fSKowalski, Kamil const crow::Request& req) 11658eb238fSKowalski, Kamil { 11758eb238fSKowalski, Kamil nlohmann::json reqJson = nlohmann::json::parse(req.body, nullptr, false); 11858eb238fSKowalski, Kamil 11958eb238fSKowalski, Kamil if (reqJson.is_discarded()) 12058eb238fSKowalski, Kamil { 12158eb238fSKowalski, Kamil // We did not receive JSON request, proceed as it is RAW data 12258eb238fSKowalski, Kamil return req.body; 12358eb238fSKowalski, Kamil } 12458eb238fSKowalski, Kamil 12558eb238fSKowalski, Kamil std::string certificate; 12658eb238fSKowalski, Kamil std::optional<std::string> certificateType = "PEM"; 12758eb238fSKowalski, Kamil 12815ed6780SWilly Tu if (!json_util::readJsonPatch(req, asyncResp->res, "CertificateString", 12915ed6780SWilly Tu certificate, "CertificateType", 13015ed6780SWilly Tu certificateType)) 13158eb238fSKowalski, Kamil { 13258eb238fSKowalski, Kamil BMCWEB_LOG_ERROR << "Required parameters are missing"; 13358eb238fSKowalski, Kamil messages::internalError(asyncResp->res); 134abb93cddSEd Tanous return {}; 13558eb238fSKowalski, Kamil } 13658eb238fSKowalski, Kamil 13758eb238fSKowalski, Kamil if (*certificateType != "PEM") 13858eb238fSKowalski, Kamil { 13958eb238fSKowalski, Kamil messages::propertyValueNotInList(asyncResp->res, *certificateType, 14058eb238fSKowalski, Kamil "CertificateType"); 141abb93cddSEd Tanous return {}; 14258eb238fSKowalski, Kamil } 14358eb238fSKowalski, Kamil 14458eb238fSKowalski, Kamil return certificate; 14558eb238fSKowalski, Kamil } 14658eb238fSKowalski, Kamil 1475968caeeSMarri Devender Rao /** 1485968caeeSMarri Devender Rao * Class to create a temporary certificate file for uploading to system 1495968caeeSMarri Devender Rao */ 1505968caeeSMarri Devender Rao class CertificateFile 1515968caeeSMarri Devender Rao { 1525968caeeSMarri Devender Rao public: 1535968caeeSMarri Devender Rao CertificateFile() = delete; 1545968caeeSMarri Devender Rao CertificateFile(const CertificateFile&) = delete; 1555968caeeSMarri Devender Rao CertificateFile& operator=(const CertificateFile&) = delete; 1565968caeeSMarri Devender Rao CertificateFile(CertificateFile&&) = delete; 1575968caeeSMarri Devender Rao CertificateFile& operator=(CertificateFile&&) = delete; 1584e23a444SEd Tanous explicit CertificateFile(const std::string& certString) 1595968caeeSMarri Devender Rao { 16072d52d25SEd Tanous std::array<char, 18> dirTemplate = {'/', 't', 'm', 'p', '/', 'C', 1615207438cSEd Tanous 'e', 'r', 't', 's', '.', 'X', 1625207438cSEd Tanous 'X', 'X', 'X', 'X', 'X', '\0'}; 1635207438cSEd Tanous char* tempDirectory = mkdtemp(dirTemplate.data()); 164e662eae8SEd Tanous if (tempDirectory != nullptr) 1655968caeeSMarri Devender Rao { 1665968caeeSMarri Devender Rao certDirectory = tempDirectory; 1675968caeeSMarri Devender Rao certificateFile = certDirectory / "cert.pem"; 1685968caeeSMarri Devender Rao std::ofstream out(certificateFile, std::ofstream::out | 1695968caeeSMarri Devender Rao std::ofstream::binary | 1705968caeeSMarri Devender Rao std::ofstream::trunc); 1715968caeeSMarri Devender Rao out << certString; 1725968caeeSMarri Devender Rao out.close(); 1738cc8edecSEd Tanous BMCWEB_LOG_DEBUG << "Creating certificate file" 1748cc8edecSEd Tanous << certificateFile.string(); 1755968caeeSMarri Devender Rao } 1765968caeeSMarri Devender Rao } 1775968caeeSMarri Devender Rao ~CertificateFile() 1785968caeeSMarri Devender Rao { 1795968caeeSMarri Devender Rao if (std::filesystem::exists(certDirectory)) 1805968caeeSMarri Devender Rao { 1818cc8edecSEd Tanous BMCWEB_LOG_DEBUG << "Removing certificate file" 1828cc8edecSEd Tanous << certificateFile.string(); 18323a21a1cSEd Tanous std::error_code ec; 18423a21a1cSEd Tanous std::filesystem::remove_all(certDirectory, ec); 18523a21a1cSEd Tanous if (ec) 1865968caeeSMarri Devender Rao { 1875968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Failed to remove temp directory" 1888cc8edecSEd Tanous << certDirectory.string(); 1895968caeeSMarri Devender Rao } 1905968caeeSMarri Devender Rao } 1915968caeeSMarri Devender Rao } 1925968caeeSMarri Devender Rao std::string getCertFilePath() 1935968caeeSMarri Devender Rao { 1945968caeeSMarri Devender Rao return certificateFile; 1955968caeeSMarri Devender Rao } 1965968caeeSMarri Devender Rao 1975968caeeSMarri Devender Rao private: 1985968caeeSMarri Devender Rao std::filesystem::path certificateFile; 1995968caeeSMarri Devender Rao std::filesystem::path certDirectory; 2005968caeeSMarri Devender Rao }; 2015968caeeSMarri Devender Rao 20230215816SMarri Devender Rao static std::unique_ptr<sdbusplus::bus::match::match> csrMatcher; 20330215816SMarri Devender Rao /** 20430215816SMarri Devender Rao * @brief Read data from CSR D-bus object and set to response 20530215816SMarri Devender Rao * 20630215816SMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 20730215816SMarri Devender Rao * @param[in] certURI Link to certifiate collection URI 20830215816SMarri Devender Rao * @param[in] service D-Bus service name 20930215816SMarri Devender Rao * @param[in] certObjPath certificate D-Bus object path 21030215816SMarri Devender Rao * @param[in] csrObjPath CSR D-Bus object path 21130215816SMarri Devender Rao * @return None 21230215816SMarri Devender Rao */ 2138d1b46d7Szhanghch05 static void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 21430215816SMarri Devender Rao const std::string& certURI, const std::string& service, 21530215816SMarri Devender Rao const std::string& certObjPath, 21630215816SMarri Devender Rao const std::string& csrObjPath) 21730215816SMarri Devender Rao { 21830215816SMarri Devender Rao BMCWEB_LOG_DEBUG << "getCSR CertObjectPath" << certObjPath 21930215816SMarri Devender Rao << " CSRObjectPath=" << csrObjPath 22030215816SMarri Devender Rao << " service=" << service; 22130215816SMarri Devender Rao crow::connections::systemBus->async_method_call( 22230215816SMarri Devender Rao [asyncResp, certURI](const boost::system::error_code ec, 22330215816SMarri Devender Rao const std::string& csr) { 22430215816SMarri Devender Rao if (ec) 22530215816SMarri Devender Rao { 22630215816SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 22730215816SMarri Devender Rao messages::internalError(asyncResp->res); 22830215816SMarri Devender Rao return; 22930215816SMarri Devender Rao } 23030215816SMarri Devender Rao if (csr.empty()) 23130215816SMarri Devender Rao { 23230215816SMarri Devender Rao BMCWEB_LOG_ERROR << "CSR read is empty"; 23330215816SMarri Devender Rao messages::internalError(asyncResp->res); 23430215816SMarri Devender Rao return; 23530215816SMarri Devender Rao } 23630215816SMarri Devender Rao asyncResp->res.jsonValue["CSRString"] = csr; 2371476687dSEd Tanous asyncResp->res.jsonValue["CertificateCollection"]["@odata.id"] = 2381476687dSEd Tanous certURI; 23930215816SMarri Devender Rao }, 24030215816SMarri Devender Rao service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR"); 24130215816SMarri Devender Rao } 24230215816SMarri Devender Rao 24330215816SMarri Devender Rao /** 24430215816SMarri Devender Rao * Action to Generate CSR 24530215816SMarri Devender Rao */ 2467e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionGenerateCSR(App& app) 24730215816SMarri Devender Rao { 2480fda0f12SGeorge Liu BMCWEB_ROUTE( 2490fda0f12SGeorge Liu app, 2500fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR/") 2515344ab8eSAbhishek Patel .privileges(redfish::privileges::postCertificateService) 252002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 253002d39b4SEd Tanous [&app](const crow::Request& req, 2547e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 2553ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 25645ca1b86SEd Tanous { 25745ca1b86SEd Tanous return; 25845ca1b86SEd Tanous } 2592c70f800SEd Tanous static const int rsaKeyBitLength = 2048; 2608d1b46d7Szhanghch05 26130215816SMarri Devender Rao // Required parameters 26230215816SMarri Devender Rao std::string city; 26330215816SMarri Devender Rao std::string commonName; 26430215816SMarri Devender Rao std::string country; 26530215816SMarri Devender Rao std::string organization; 26630215816SMarri Devender Rao std::string organizationalUnit; 26730215816SMarri Devender Rao std::string state; 26830215816SMarri Devender Rao nlohmann::json certificateCollection; 26930215816SMarri Devender Rao 27030215816SMarri Devender Rao // Optional parameters 27130215816SMarri Devender Rao std::optional<std::vector<std::string>> optAlternativeNames = 27230215816SMarri Devender Rao std::vector<std::string>(); 27330215816SMarri Devender Rao std::optional<std::string> optContactPerson = ""; 27430215816SMarri Devender Rao std::optional<std::string> optChallengePassword = ""; 27530215816SMarri Devender Rao std::optional<std::string> optEmail = ""; 27630215816SMarri Devender Rao std::optional<std::string> optGivenName = ""; 27730215816SMarri Devender Rao std::optional<std::string> optInitials = ""; 2782c70f800SEd Tanous std::optional<int64_t> optKeyBitLength = rsaKeyBitLength; 279aaf3206fSVernon Mauery std::optional<std::string> optKeyCurveId = "secp384r1"; 28030215816SMarri Devender Rao std::optional<std::string> optKeyPairAlgorithm = "EC"; 28130215816SMarri Devender Rao std::optional<std::vector<std::string>> optKeyUsage = 28230215816SMarri Devender Rao std::vector<std::string>(); 28330215816SMarri Devender Rao std::optional<std::string> optSurname = ""; 28430215816SMarri Devender Rao std::optional<std::string> optUnstructuredName = ""; 28515ed6780SWilly Tu if (!json_util::readJsonAction( 2860fda0f12SGeorge Liu req, asyncResp->res, "City", city, "CommonName", commonName, 2870fda0f12SGeorge Liu "ContactPerson", optContactPerson, "Country", country, 2880fda0f12SGeorge Liu "Organization", organization, "OrganizationalUnit", 2890fda0f12SGeorge Liu organizationalUnit, "State", state, "CertificateCollection", 290002d39b4SEd Tanous certificateCollection, "AlternativeNames", optAlternativeNames, 291002d39b4SEd Tanous "ChallengePassword", optChallengePassword, "Email", optEmail, 292002d39b4SEd Tanous "GivenName", optGivenName, "Initials", optInitials, 293002d39b4SEd Tanous "KeyBitLength", optKeyBitLength, "KeyCurveId", optKeyCurveId, 2940fda0f12SGeorge Liu "KeyPairAlgorithm", optKeyPairAlgorithm, "KeyUsage", 2950fda0f12SGeorge Liu optKeyUsage, "Surname", optSurname, "UnstructuredName", 2960fda0f12SGeorge Liu optUnstructuredName)) 29730215816SMarri Devender Rao { 29830215816SMarri Devender Rao return; 29930215816SMarri Devender Rao } 30030215816SMarri Devender Rao 30130215816SMarri Devender Rao // bmcweb has no way to store or decode a private key challenge 3027e860f15SJohn Edward Broadbent // password, which will likely cause bmcweb to crash on startup 3037e860f15SJohn Edward Broadbent // if this is not set on a post so not allowing the user to set 3047e860f15SJohn Edward Broadbent // value 30526f6976fSEd Tanous if (!optChallengePassword->empty()) 30630215816SMarri Devender Rao { 307002d39b4SEd Tanous messages::actionParameterNotSupported(asyncResp->res, "GenerateCSR", 308002d39b4SEd Tanous "ChallengePassword"); 30930215816SMarri Devender Rao return; 31030215816SMarri Devender Rao } 31130215816SMarri Devender Rao 31230215816SMarri Devender Rao std::string certURI; 313002d39b4SEd Tanous if (!redfish::json_util::readJson(certificateCollection, asyncResp->res, 314002d39b4SEd Tanous "@odata.id", certURI)) 31530215816SMarri Devender Rao { 31630215816SMarri Devender Rao return; 31730215816SMarri Devender Rao } 31830215816SMarri Devender Rao 31930215816SMarri Devender Rao std::string objectPath; 32030215816SMarri Devender Rao std::string service; 321*11ba3979SEd Tanous if (certURI.starts_with( 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 } 327*11ba3979SEd Tanous else if (certURI.starts_with( 328*11ba3979SEd Tanous "/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 360*11ba3979SEd Tanous if (certURI.starts_with( 3610fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) 36230215816SMarri Devender Rao { 36326f6976fSEd Tanous if (optKeyUsage->empty()) 36430215816SMarri Devender Rao { 36530215816SMarri Devender Rao optKeyUsage->push_back("ServerAuthentication"); 36630215816SMarri Devender Rao } 36730215816SMarri Devender Rao else if (optKeyUsage->size() == 1) 36830215816SMarri Devender Rao { 36930215816SMarri Devender Rao if ((*optKeyUsage)[0] != "ServerAuthentication") 37030215816SMarri Devender Rao { 37130215816SMarri Devender Rao messages::propertyValueNotInList( 37230215816SMarri Devender Rao asyncResp->res, (*optKeyUsage)[0], "KeyUsage"); 37330215816SMarri Devender Rao return; 37430215816SMarri Devender Rao } 37530215816SMarri Devender Rao } 37630215816SMarri Devender Rao else 37730215816SMarri Devender Rao { 37830215816SMarri Devender Rao messages::actionParameterNotSupported( 37930215816SMarri Devender Rao asyncResp->res, "KeyUsage", "GenerateCSR"); 38030215816SMarri Devender Rao return; 38130215816SMarri Devender Rao } 38230215816SMarri Devender Rao } 383*11ba3979SEd Tanous else if (certURI.starts_with( 384*11ba3979SEd Tanous "/redfish/v1/AccountService/LDAP/Certificates")) 3853b7f0149SMarri Devender Rao { 38626f6976fSEd Tanous if (optKeyUsage->empty()) 3873b7f0149SMarri Devender Rao { 3883b7f0149SMarri Devender Rao optKeyUsage->push_back("ClientAuthentication"); 3893b7f0149SMarri Devender Rao } 3903b7f0149SMarri Devender Rao else if (optKeyUsage->size() == 1) 3913b7f0149SMarri Devender Rao { 3923b7f0149SMarri Devender Rao if ((*optKeyUsage)[0] != "ClientAuthentication") 3933b7f0149SMarri Devender Rao { 3943b7f0149SMarri Devender Rao messages::propertyValueNotInList( 3953b7f0149SMarri Devender Rao asyncResp->res, (*optKeyUsage)[0], "KeyUsage"); 3963b7f0149SMarri Devender Rao return; 3973b7f0149SMarri Devender Rao } 3983b7f0149SMarri Devender Rao } 3993b7f0149SMarri Devender Rao else 4003b7f0149SMarri Devender Rao { 4013b7f0149SMarri Devender Rao messages::actionParameterNotSupported( 4023b7f0149SMarri Devender Rao asyncResp->res, "KeyUsage", "GenerateCSR"); 4033b7f0149SMarri Devender Rao return; 4043b7f0149SMarri Devender Rao } 4053b7f0149SMarri Devender Rao } 40630215816SMarri Devender Rao 4077e860f15SJohn Edward Broadbent // Only allow one CSR matcher at a time so setting retry 4087e860f15SJohn Edward Broadbent // time-out and timer expiry to 10 seconds for now. 4092c70f800SEd Tanous static const int timeOut = 10; 41030215816SMarri Devender Rao if (csrMatcher) 41130215816SMarri Devender Rao { 412002d39b4SEd Tanous messages::serviceTemporarilyUnavailable(asyncResp->res, 413002d39b4SEd Tanous std::to_string(timeOut)); 41430215816SMarri Devender Rao return; 41530215816SMarri Devender Rao } 41630215816SMarri Devender Rao 41730215816SMarri Devender Rao // Make this static so it survives outside this method 41830215816SMarri Devender Rao static boost::asio::steady_timer timeout(*req.ioService); 4192c70f800SEd Tanous timeout.expires_after(std::chrono::seconds(timeOut)); 420002d39b4SEd Tanous timeout.async_wait([asyncResp](const boost::system::error_code& ec) { 42130215816SMarri Devender Rao csrMatcher = nullptr; 42230215816SMarri Devender Rao if (ec) 42330215816SMarri Devender Rao { 4247e860f15SJohn Edward Broadbent // operation_aborted is expected if timer is canceled 4257e860f15SJohn Edward Broadbent // before completion. 42630215816SMarri Devender Rao if (ec != boost::asio::error::operation_aborted) 42730215816SMarri Devender Rao { 42830215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Async_wait failed " << ec; 42930215816SMarri Devender Rao } 43030215816SMarri Devender Rao return; 43130215816SMarri Devender Rao } 43230215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR"; 43330215816SMarri Devender Rao messages::internalError(asyncResp->res); 43430215816SMarri Devender Rao }); 43530215816SMarri Devender Rao 43630215816SMarri Devender Rao // create a matcher to wait on CSR object 43730215816SMarri Devender Rao BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath; 4380fda0f12SGeorge Liu std::string match("type='signal'," 43930215816SMarri Devender Rao "interface='org.freedesktop.DBus.ObjectManager'," 44030215816SMarri Devender Rao "path='" + 44130215816SMarri Devender Rao objectPath + 44230215816SMarri Devender Rao "'," 44330215816SMarri Devender Rao "member='InterfacesAdded'"); 44430215816SMarri Devender Rao csrMatcher = std::make_unique<sdbusplus::bus::match::match>( 44530215816SMarri Devender Rao *crow::connections::systemBus, match, 44630215816SMarri Devender Rao [asyncResp, service, objectPath, 44730215816SMarri Devender Rao certURI](sdbusplus::message::message& m) { 448271584abSEd Tanous timeout.cancel(); 44930215816SMarri Devender Rao if (m.is_method_error()) 45030215816SMarri Devender Rao { 45130215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Dbus method error!!!"; 45230215816SMarri Devender Rao messages::internalError(asyncResp->res); 45330215816SMarri Devender Rao return; 45430215816SMarri Devender Rao } 455b9d36b47SEd Tanous 456b9d36b47SEd Tanous dbus::utility::DBusInteracesMap interfacesProperties; 457b9d36b47SEd Tanous 45830215816SMarri Devender Rao sdbusplus::message::object_path csrObjectPath; 45930215816SMarri Devender Rao m.read(csrObjectPath, interfacesProperties); 4600fda0f12SGeorge Liu BMCWEB_LOG_DEBUG << "CSR object added" << csrObjectPath.str; 46102cad96eSEd Tanous for (const auto& interface : interfacesProperties) 46230215816SMarri Devender Rao { 4630fda0f12SGeorge Liu if (interface.first == "xyz.openbmc_project.Certs.CSR") 46430215816SMarri Devender Rao { 46530215816SMarri Devender Rao getCSR(asyncResp, certURI, service, objectPath, 46630215816SMarri Devender Rao csrObjectPath.str); 46730215816SMarri Devender Rao break; 46830215816SMarri Devender Rao } 46930215816SMarri Devender Rao } 47030215816SMarri Devender Rao }); 47130215816SMarri Devender Rao crow::connections::systemBus->async_method_call( 472914e2d5dSEd Tanous [asyncResp](const boost::system::error_code ec, 473cb13a392SEd Tanous const std::string&) { 47430215816SMarri Devender Rao if (ec) 47530215816SMarri Devender Rao { 476002d39b4SEd Tanous BMCWEB_LOG_ERROR << "DBUS response error: " << 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", 482002d39b4SEd Tanous "GenerateCSR", *optAlternativeNames, *optChallengePassword, city, 483002d39b4SEd Tanous commonName, *optContactPerson, country, *optEmail, *optGivenName, 484002d39b4SEd Tanous *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 /** 557d3f92ce7SJiaqing Zhao * @brief Retrieve the installed certificate list 558d3f92ce7SJiaqing Zhao * 559d3f92ce7SJiaqing Zhao * @param[in] asyncResp Shared pointer to the response message 560d3f92ce7SJiaqing Zhao * @param[in] basePath DBus object path to search 561d3f92ce7SJiaqing Zhao * @param[in] listPtr Json pointer to the list in asyncResp 562d3f92ce7SJiaqing Zhao * @param[in] countPtr Json pointer to the count in asyncResp 563d3f92ce7SJiaqing Zhao * @return None 564d3f92ce7SJiaqing Zhao */ 565d3f92ce7SJiaqing Zhao static void 566d3f92ce7SJiaqing Zhao getCertificateList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 567d3f92ce7SJiaqing Zhao const std::string& basePath, 568d3f92ce7SJiaqing Zhao const nlohmann::json::json_pointer& listPtr, 569d3f92ce7SJiaqing Zhao const nlohmann::json::json_pointer& countPtr) 570d3f92ce7SJiaqing Zhao { 571d3f92ce7SJiaqing Zhao crow::connections::systemBus->async_method_call( 572d3f92ce7SJiaqing Zhao [asyncResp, listPtr, countPtr]( 573d3f92ce7SJiaqing Zhao const boost::system::error_code ec, 574d3f92ce7SJiaqing Zhao const dbus::utility::MapperGetSubTreePathsResponse& certPaths) { 575d3f92ce7SJiaqing Zhao if (ec) 576d3f92ce7SJiaqing Zhao { 577d3f92ce7SJiaqing Zhao BMCWEB_LOG_ERROR << "Certificate collection query failed: " << ec; 578d3f92ce7SJiaqing Zhao messages::internalError(asyncResp->res); 579d3f92ce7SJiaqing Zhao return; 580d3f92ce7SJiaqing Zhao } 581d3f92ce7SJiaqing Zhao 582d3f92ce7SJiaqing Zhao nlohmann::json& links = asyncResp->res.jsonValue[listPtr]; 583d3f92ce7SJiaqing Zhao links = nlohmann::json::array(); 584d3f92ce7SJiaqing Zhao for (const auto& certPath : certPaths) 585d3f92ce7SJiaqing Zhao { 586d3f92ce7SJiaqing Zhao sdbusplus::message::object_path objPath(certPath); 587d3f92ce7SJiaqing Zhao std::string certId = objPath.filename(); 588d3f92ce7SJiaqing Zhao if (certId.empty()) 589d3f92ce7SJiaqing Zhao { 590d3f92ce7SJiaqing Zhao BMCWEB_LOG_ERROR << "Invalid certificate objPath " << certPath; 591d3f92ce7SJiaqing Zhao continue; 592d3f92ce7SJiaqing Zhao } 593d3f92ce7SJiaqing Zhao 594d3f92ce7SJiaqing Zhao boost::urls::url certURL; 595d3f92ce7SJiaqing Zhao if (objPath.parent_path() == certs::httpsObjectPath) 596d3f92ce7SJiaqing Zhao { 597d3f92ce7SJiaqing Zhao certURL = crow::utility::urlFromPieces( 598d3f92ce7SJiaqing Zhao "redfish", "v1", "Managers", "bmc", "NetworkProtocol", 599d3f92ce7SJiaqing Zhao "HTTPS", "Certificates", certId); 600d3f92ce7SJiaqing Zhao } 601d3f92ce7SJiaqing Zhao else if (objPath.parent_path() == certs::ldapObjectPath) 602d3f92ce7SJiaqing Zhao { 603d3f92ce7SJiaqing Zhao certURL = crow::utility::urlFromPieces("redfish", "v1", 604d3f92ce7SJiaqing Zhao "AccountService", "LDAP", 605d3f92ce7SJiaqing Zhao "Certificates", certId); 606d3f92ce7SJiaqing Zhao } 607d3f92ce7SJiaqing Zhao else if (objPath.parent_path() == certs::authorityObjectPath) 608d3f92ce7SJiaqing Zhao { 609d3f92ce7SJiaqing Zhao certURL = crow::utility::urlFromPieces( 610d3f92ce7SJiaqing Zhao "redfish", "v1", "Managers", "bmc", "Truststore", 611d3f92ce7SJiaqing Zhao "Certificates", certId); 612d3f92ce7SJiaqing Zhao } 613d3f92ce7SJiaqing Zhao else 614d3f92ce7SJiaqing Zhao { 615d3f92ce7SJiaqing Zhao continue; 616d3f92ce7SJiaqing Zhao } 617d3f92ce7SJiaqing Zhao 618d3f92ce7SJiaqing Zhao nlohmann::json::object_t link; 619d3f92ce7SJiaqing Zhao link["@odata.id"] = certURL; 620d3f92ce7SJiaqing Zhao links.emplace_back(std::move(link)); 621d3f92ce7SJiaqing Zhao } 622d3f92ce7SJiaqing Zhao 623d3f92ce7SJiaqing Zhao asyncResp->res.jsonValue[countPtr] = links.size(); 624d3f92ce7SJiaqing Zhao }, 625d3f92ce7SJiaqing Zhao "xyz.openbmc_project.ObjectMapper", 626d3f92ce7SJiaqing Zhao "/xyz/openbmc_project/object_mapper", 627d3f92ce7SJiaqing Zhao "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", basePath, 0, 628d3f92ce7SJiaqing Zhao std::array<const char*, 1>{certs::certPropIntf}); 629d3f92ce7SJiaqing Zhao } 630d3f92ce7SJiaqing Zhao 631d3f92ce7SJiaqing Zhao /** 6325968caeeSMarri Devender Rao * @brief Retrieve the certificates properties and append to the response 6335968caeeSMarri Devender Rao * message 6345968caeeSMarri Devender Rao * 6355968caeeSMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 6365968caeeSMarri Devender Rao * @param[in] objectPath Path of the D-Bus service object 6375968caeeSMarri Devender Rao * @param[in] certId Id of the certificate 6385968caeeSMarri Devender Rao * @param[in] certURL URL of the certificate object 6395968caeeSMarri Devender Rao * @param[in] name name of the certificate 6405968caeeSMarri Devender Rao * @return None 6415968caeeSMarri Devender Rao */ 6425968caeeSMarri Devender Rao static void getCertificateProperties( 6438d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 6448d1b46d7Szhanghch05 const std::string& objectPath, const std::string& service, long certId, 6458d1b46d7Szhanghch05 const std::string& certURL, const std::string& name) 6465968caeeSMarri Devender Rao { 6475968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "getCertificateProperties Path=" << objectPath 6485968caeeSMarri Devender Rao << " certId=" << certId << " certURl=" << certURL; 6495968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 650b9d36b47SEd Tanous [asyncResp, certURL, certId, 651b9d36b47SEd Tanous name](const boost::system::error_code ec, 652b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& properties) { 6535968caeeSMarri Devender Rao if (ec) 6545968caeeSMarri Devender Rao { 6555968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 6568aae75adSMarri Devender Rao messages::resourceNotFound(asyncResp->res, name, 6578aae75adSMarri Devender Rao std::to_string(certId)); 6585968caeeSMarri Devender Rao return; 6595968caeeSMarri Devender Rao } 6601476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = certURL; 6611476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 6621476687dSEd Tanous "#Certificate.v1_0_0.Certificate"; 6631476687dSEd Tanous asyncResp->res.jsonValue["Id"] = std::to_string(certId); 6641476687dSEd Tanous asyncResp->res.jsonValue["Name"] = name; 6651476687dSEd Tanous asyncResp->res.jsonValue["Description"] = name; 6665968caeeSMarri Devender Rao for (const auto& property : properties) 6675968caeeSMarri Devender Rao { 6685968caeeSMarri Devender Rao if (property.first == "CertificateString") 6695968caeeSMarri Devender Rao { 6705968caeeSMarri Devender Rao asyncResp->res.jsonValue["CertificateString"] = ""; 6715968caeeSMarri Devender Rao const std::string* value = 6725968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 673e662eae8SEd Tanous if (value != nullptr) 6745968caeeSMarri Devender Rao { 67537cce918SMarri Devender Rao asyncResp->res.jsonValue["CertificateString"] = *value; 6765968caeeSMarri Devender Rao } 6775968caeeSMarri Devender Rao } 6785968caeeSMarri Devender Rao else if (property.first == "KeyUsage") 6795968caeeSMarri Devender Rao { 680002d39b4SEd Tanous nlohmann::json& keyUsage = asyncResp->res.jsonValue["KeyUsage"]; 6815968caeeSMarri Devender Rao keyUsage = nlohmann::json::array(); 6825968caeeSMarri Devender Rao const std::vector<std::string>* value = 68337cce918SMarri Devender Rao std::get_if<std::vector<std::string>>(&property.second); 684e662eae8SEd Tanous if (value != nullptr) 6855968caeeSMarri Devender Rao { 6865968caeeSMarri Devender Rao for (const std::string& usage : *value) 6875968caeeSMarri Devender Rao { 6885968caeeSMarri Devender Rao keyUsage.push_back(usage); 6895968caeeSMarri Devender Rao } 6905968caeeSMarri Devender Rao } 6915968caeeSMarri Devender Rao } 6925968caeeSMarri Devender Rao else if (property.first == "Issuer") 6935968caeeSMarri Devender Rao { 6945968caeeSMarri Devender Rao const std::string* value = 6955968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 696e662eae8SEd Tanous if (value != nullptr) 6975968caeeSMarri Devender Rao { 6985968caeeSMarri Devender Rao updateCertIssuerOrSubject( 6995968caeeSMarri Devender Rao asyncResp->res.jsonValue["Issuer"], *value); 7005968caeeSMarri Devender Rao } 7015968caeeSMarri Devender Rao } 7025968caeeSMarri Devender Rao else if (property.first == "Subject") 7035968caeeSMarri Devender Rao { 7045968caeeSMarri Devender Rao const std::string* value = 7055968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 706e662eae8SEd Tanous if (value != nullptr) 7075968caeeSMarri Devender Rao { 7085968caeeSMarri Devender Rao updateCertIssuerOrSubject( 70937cce918SMarri Devender Rao asyncResp->res.jsonValue["Subject"], *value); 7105968caeeSMarri Devender Rao } 7115968caeeSMarri Devender Rao } 7125968caeeSMarri Devender Rao else if (property.first == "ValidNotAfter") 7135968caeeSMarri Devender Rao { 714002d39b4SEd Tanous const uint64_t* value = std::get_if<uint64_t>(&property.second); 715e662eae8SEd Tanous if (value != nullptr) 7165968caeeSMarri Devender Rao { 7175968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotAfter"] = 7181d8782e7SNan Zhou crow::utility::getDateTimeUint(*value); 7195968caeeSMarri Devender Rao } 7205968caeeSMarri Devender Rao } 7215968caeeSMarri Devender Rao else if (property.first == "ValidNotBefore") 7225968caeeSMarri Devender Rao { 723002d39b4SEd Tanous const uint64_t* value = std::get_if<uint64_t>(&property.second); 724e662eae8SEd Tanous if (value != nullptr) 7255968caeeSMarri Devender Rao { 7265968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotBefore"] = 7271d8782e7SNan Zhou crow::utility::getDateTimeUint(*value); 7285968caeeSMarri Devender Rao } 7295968caeeSMarri Devender Rao } 7305968caeeSMarri Devender Rao } 7315968caeeSMarri Devender Rao asyncResp->res.addHeader("Location", certURL); 7325968caeeSMarri Devender Rao }, 7335968caeeSMarri Devender Rao service, objectPath, certs::dbusPropIntf, "GetAll", 7345968caeeSMarri Devender Rao certs::certPropIntf); 7355968caeeSMarri Devender Rao } 7365968caeeSMarri Devender Rao 7375968caeeSMarri Devender Rao /** 7385968caeeSMarri Devender Rao * Action to replace an existing certificate 7395968caeeSMarri Devender Rao */ 7407e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionsReplaceCertificate(App& app) 7415968caeeSMarri Devender Rao { 7420fda0f12SGeorge Liu BMCWEB_ROUTE( 7430fda0f12SGeorge Liu app, 7440fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate/") 745ed398213SEd Tanous .privileges(redfish::privileges::postCertificateService) 746002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 747002d39b4SEd Tanous [&app](const crow::Request& req, 7487e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 7493ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 75045ca1b86SEd Tanous { 75145ca1b86SEd Tanous return; 75245ca1b86SEd Tanous } 7535968caeeSMarri Devender Rao std::string certificate; 7545968caeeSMarri Devender Rao nlohmann::json certificateUri; 7555968caeeSMarri Devender Rao std::optional<std::string> certificateType = "PEM"; 7568d1b46d7Szhanghch05 757002d39b4SEd Tanous if (!json_util::readJsonAction(req, asyncResp->res, "CertificateString", 758002d39b4SEd Tanous certificate, "CertificateUri", 759002d39b4SEd Tanous certificateUri, "CertificateType", 760002d39b4SEd Tanous certificateType)) 7615968caeeSMarri Devender Rao { 7625968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Required parameters are missing"; 7635968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 7645968caeeSMarri Devender Rao return; 7655968caeeSMarri Devender Rao } 7665968caeeSMarri Devender Rao 7675968caeeSMarri Devender Rao if (!certificateType) 7685968caeeSMarri Devender Rao { 7695968caeeSMarri Devender Rao // should never happen, but it never hurts to be paranoid. 7705968caeeSMarri Devender Rao return; 7715968caeeSMarri Devender Rao } 7725968caeeSMarri Devender Rao if (certificateType != "PEM") 7735968caeeSMarri Devender Rao { 7745968caeeSMarri Devender Rao messages::actionParameterNotSupported( 7755968caeeSMarri Devender Rao asyncResp->res, "CertificateType", "ReplaceCertificate"); 7765968caeeSMarri Devender Rao return; 7775968caeeSMarri Devender Rao } 7785968caeeSMarri Devender Rao 7795968caeeSMarri Devender Rao std::string certURI; 7805968caeeSMarri Devender Rao if (!redfish::json_util::readJson(certificateUri, asyncResp->res, 7815968caeeSMarri Devender Rao "@odata.id", certURI)) 7825968caeeSMarri Devender Rao { 7835968caeeSMarri Devender Rao messages::actionParameterMissing( 7845968caeeSMarri Devender Rao asyncResp->res, "ReplaceCertificate", "CertificateUri"); 7855968caeeSMarri Devender Rao return; 7865968caeeSMarri Devender Rao } 7875968caeeSMarri Devender Rao 7885968caeeSMarri Devender Rao BMCWEB_LOG_INFO << "Certificate URI to replace" << certURI; 7895968caeeSMarri Devender Rao long id = getIDFromURL(certURI); 7905968caeeSMarri Devender Rao if (id < 0) 7915968caeeSMarri Devender Rao { 792002d39b4SEd Tanous messages::actionParameterValueFormatError(asyncResp->res, certURI, 793002d39b4SEd Tanous "CertificateUri", 7945968caeeSMarri Devender Rao "ReplaceCertificate"); 7955968caeeSMarri Devender Rao return; 7965968caeeSMarri Devender Rao } 7975968caeeSMarri Devender Rao std::string objectPath; 7985968caeeSMarri Devender Rao std::string name; 79937cce918SMarri Devender Rao std::string service; 800*11ba3979SEd Tanous if (certURI.starts_with( 8010fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")) 8025968caeeSMarri Devender Rao { 803002d39b4SEd Tanous objectPath = 804002d39b4SEd Tanous std::string(certs::httpsObjectPath) + "/" + std::to_string(id); 8055968caeeSMarri Devender Rao name = "HTTPS certificate"; 80637cce918SMarri Devender Rao service = certs::httpsServiceName; 80737cce918SMarri Devender Rao } 808*11ba3979SEd Tanous else if (certURI.starts_with( 809*11ba3979SEd Tanous "/redfish/v1/AccountService/LDAP/Certificates/")) 81037cce918SMarri Devender Rao { 811002d39b4SEd Tanous objectPath = 812002d39b4SEd Tanous std::string(certs::ldapObjectPath) + "/" + std::to_string(id); 81337cce918SMarri Devender Rao name = "LDAP certificate"; 81437cce918SMarri Devender Rao service = certs::ldapServiceName; 8155968caeeSMarri Devender Rao } 816*11ba3979SEd Tanous else if (certURI.starts_with( 817cfcd5f6bSMarri Devender Rao "/redfish/v1/Managers/bmc/Truststore/Certificates/")) 818cfcd5f6bSMarri Devender Rao { 819cfcd5f6bSMarri Devender Rao objectPath = std::string(certs::authorityObjectPath) + "/" + 820cfcd5f6bSMarri Devender Rao std::to_string(id); 821cfcd5f6bSMarri Devender Rao name = "TrustStore certificate"; 822cfcd5f6bSMarri Devender Rao service = certs::authorityServiceName; 823cfcd5f6bSMarri Devender Rao } 8245968caeeSMarri Devender Rao else 8255968caeeSMarri Devender Rao { 8265968caeeSMarri Devender Rao messages::actionParameterNotSupported( 8275968caeeSMarri Devender Rao asyncResp->res, "CertificateUri", "ReplaceCertificate"); 8285968caeeSMarri Devender Rao return; 8295968caeeSMarri Devender Rao } 8305968caeeSMarri Devender Rao 8315968caeeSMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 8325968caeeSMarri Devender Rao std::make_shared<CertificateFile>(certificate); 8335968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 83437cce918SMarri Devender Rao [asyncResp, certFile, objectPath, service, certURI, id, 8355968caeeSMarri Devender Rao name](const boost::system::error_code ec) { 8365968caeeSMarri Devender Rao if (ec) 8375968caeeSMarri Devender Rao { 8385968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 83990d2d1e8SJiaqing Zhao if (ec.value() == 84090d2d1e8SJiaqing Zhao boost::system::linux_error::bad_request_descriptor) 84190d2d1e8SJiaqing Zhao { 8428aae75adSMarri Devender Rao messages::resourceNotFound(asyncResp->res, name, 8438aae75adSMarri Devender Rao std::to_string(id)); 8445968caeeSMarri Devender Rao return; 8455968caeeSMarri Devender Rao } 84690d2d1e8SJiaqing Zhao messages::internalError(asyncResp->res); 84790d2d1e8SJiaqing Zhao return; 84890d2d1e8SJiaqing Zhao } 84937cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, service, id, 8505968caeeSMarri Devender Rao certURI, name); 8515968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" 8525968caeeSMarri Devender Rao << certFile->getCertFilePath(); 8535968caeeSMarri Devender Rao }, 8545968caeeSMarri Devender Rao service, objectPath, certs::certReplaceIntf, "Replace", 8555968caeeSMarri Devender Rao certFile->getCertFilePath()); 8567e860f15SJohn Edward Broadbent }); 8577e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionsReplaceCertificate 8585968caeeSMarri Devender Rao 8595968caeeSMarri Devender Rao /** 8605968caeeSMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 8615968caeeSMarri Devender Rao * of a component, account or service. 8625968caeeSMarri Devender Rao */ 8635968caeeSMarri Devender Rao 8647e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificate(App& app) 8655968caeeSMarri Devender Rao { 8667e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 8677e860f15SJohn Edward Broadbent app, 8687e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/<str>/") 869ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 8707e860f15SJohn Edward Broadbent .methods( 8717e860f15SJohn Edward Broadbent boost::beast::http::verb:: 87245ca1b86SEd Tanous get)([&app](const crow::Request& req, 8737e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 8747e860f15SJohn Edward Broadbent const std::string& param) -> void { 8753ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 87645ca1b86SEd Tanous { 87745ca1b86SEd Tanous return; 87845ca1b86SEd Tanous } 8797e860f15SJohn Edward Broadbent if (param.empty()) 8805968caeeSMarri Devender Rao { 8815968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 8825968caeeSMarri Devender Rao return; 8835968caeeSMarri Devender Rao } 8845968caeeSMarri Devender Rao long id = getIDFromURL(req.url); 8855968caeeSMarri Devender Rao 8867e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG << "HTTPSCertificate::doGet ID=" 8877e860f15SJohn Edward Broadbent << std::to_string(id); 8885968caeeSMarri Devender Rao std::string certURL = 8895968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" + 8905968caeeSMarri Devender Rao std::to_string(id); 8915968caeeSMarri Devender Rao std::string objectPath = certs::httpsObjectPath; 8925968caeeSMarri Devender Rao objectPath += "/"; 8935968caeeSMarri Devender Rao objectPath += std::to_string(id); 8947e860f15SJohn Edward Broadbent getCertificateProperties(asyncResp, objectPath, 8957e860f15SJohn Edward Broadbent certs::httpsServiceName, id, certURL, 8967e860f15SJohn Edward Broadbent "HTTPS Certificate"); 8977e860f15SJohn Edward Broadbent }); 8985968caeeSMarri Devender Rao } 8995968caeeSMarri Devender Rao 9005968caeeSMarri Devender Rao /** 9015968caeeSMarri Devender Rao * Collection of HTTPS certificates 9025968caeeSMarri Devender Rao */ 9037e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificateCollection(App& app) 9045968caeeSMarri Devender Rao { 9057e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 9065968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/") 907ed398213SEd Tanous .privileges(redfish::privileges::getCertificateCollection) 908002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 909002d39b4SEd Tanous [&app](const crow::Request& req, 910002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 9113ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 91245ca1b86SEd Tanous { 91345ca1b86SEd Tanous return; 91445ca1b86SEd Tanous } 9151476687dSEd Tanous 9161476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 9171476687dSEd Tanous "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"; 9181476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 9191476687dSEd Tanous "#CertificateCollection.CertificateCollection"; 9201476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "HTTPS Certificates Collection"; 9211476687dSEd Tanous asyncResp->res.jsonValue["Description"] = 9221476687dSEd Tanous "A Collection of HTTPS certificate instances"; 9238d1b46d7Szhanghch05 924d3f92ce7SJiaqing Zhao getCertificateList(asyncResp, certs::httpsObjectPath, 925d3f92ce7SJiaqing Zhao "/Members"_json_pointer, 926d3f92ce7SJiaqing Zhao "/Members@odata.count"_json_pointer); 9277e860f15SJohn Edward Broadbent }); 9285968caeeSMarri Devender Rao 9297e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 9307e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/") 931ed398213SEd Tanous .privileges(redfish::privileges::postCertificateCollection) 932002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 933002d39b4SEd Tanous [&app](const crow::Request& req, 9347e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 9353ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 93645ca1b86SEd Tanous { 93745ca1b86SEd Tanous return; 93845ca1b86SEd Tanous } 9395968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost"; 9408d1b46d7Szhanghch05 9411476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "HTTPS Certificate"; 9421476687dSEd Tanous asyncResp->res.jsonValue["Description"] = "HTTPS Certificate"; 9435968caeeSMarri Devender Rao 944002d39b4SEd Tanous std::string certFileBody = getCertificateFromReqBody(asyncResp, req); 94558eb238fSKowalski, Kamil 94658eb238fSKowalski, Kamil if (certFileBody.empty()) 94758eb238fSKowalski, Kamil { 9480fda0f12SGeorge Liu BMCWEB_LOG_ERROR << "Cannot get certificate from request body."; 949a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 95058eb238fSKowalski, Kamil return; 95158eb238fSKowalski, Kamil } 95258eb238fSKowalski, Kamil 9535968caeeSMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 95458eb238fSKowalski, Kamil std::make_shared<CertificateFile>(certFileBody); 9555968caeeSMarri Devender Rao 9565968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 957656ec7e3SZbigniew Kurzynski [asyncResp, certFile](const boost::system::error_code ec, 958656ec7e3SZbigniew Kurzynski const std::string& objectPath) { 9595968caeeSMarri Devender Rao if (ec) 9605968caeeSMarri Devender Rao { 9615968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 9625968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 9635968caeeSMarri Devender Rao return; 9645968caeeSMarri Devender Rao } 965656ec7e3SZbigniew Kurzynski long certId = getIDFromURL(objectPath); 966656ec7e3SZbigniew Kurzynski if (certId < 0) 967656ec7e3SZbigniew Kurzynski { 968002d39b4SEd Tanous BMCWEB_LOG_ERROR << "Invalid objectPath value" << objectPath; 969656ec7e3SZbigniew Kurzynski messages::internalError(asyncResp->res); 970656ec7e3SZbigniew Kurzynski return; 971656ec7e3SZbigniew Kurzynski } 9725968caeeSMarri Devender Rao std::string certURL = 9730fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" + 9745968caeeSMarri Devender Rao std::to_string(certId); 9750fda0f12SGeorge Liu getCertificateProperties(asyncResp, objectPath, 976002d39b4SEd Tanous certs::httpsServiceName, certId, certURL, 977002d39b4SEd Tanous "HTTPS Certificate"); 9785968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" 9795968caeeSMarri Devender Rao << certFile->getCertFilePath(); 9805968caeeSMarri Devender Rao }, 98137cce918SMarri Devender Rao certs::httpsServiceName, certs::httpsObjectPath, 9820fda0f12SGeorge Liu certs::certInstallIntf, "Install", certFile->getCertFilePath()); 9837e860f15SJohn Edward Broadbent }); 9847e860f15SJohn Edward Broadbent } // requestRoutesHTTPSCertificateCollection 9855968caeeSMarri Devender Rao 9865968caeeSMarri Devender Rao /** 9877e860f15SJohn Edward Broadbent * The certificate location schema defines a resource that an administrator 9887e860f15SJohn Edward Broadbent * can use in order to locate all certificates installed on a given service. 9897e860f15SJohn Edward Broadbent */ 9907e860f15SJohn Edward Broadbent inline void requestRoutesCertificateLocations(App& app) 9917e860f15SJohn Edward Broadbent { 9927e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/") 993ed398213SEd Tanous .privileges(redfish::privileges::getCertificateLocations) 994002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 995002d39b4SEd Tanous [&app](const crow::Request& req, 996002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 9973ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 99845ca1b86SEd Tanous { 99945ca1b86SEd Tanous return; 100045ca1b86SEd Tanous } 10011476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 10021476687dSEd Tanous "/redfish/v1/CertificateService/CertificateLocations"; 10031476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 10041476687dSEd Tanous "#CertificateLocations.v1_0_0.CertificateLocations"; 10051476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "Certificate Locations"; 10061476687dSEd Tanous asyncResp->res.jsonValue["Id"] = "CertificateLocations"; 10071476687dSEd Tanous asyncResp->res.jsonValue["Description"] = 10087e860f15SJohn Edward Broadbent "Defines a resource that an administrator can use in order to " 10091476687dSEd Tanous "locate all certificates installed on a given service"; 10107e860f15SJohn Edward Broadbent 1011d3f92ce7SJiaqing Zhao getCertificateList(asyncResp, certs::baseObjectPath, 1012d3f92ce7SJiaqing Zhao "/Links/Certificates"_json_pointer, 1013d3f92ce7SJiaqing Zhao "/Links/Certificates@odata.count"_json_pointer); 10147e860f15SJohn Edward Broadbent }); 10157e860f15SJohn Edward Broadbent } 10167e860f15SJohn Edward Broadbent // requestRoutesCertificateLocations 101737cce918SMarri Devender Rao 101837cce918SMarri Devender Rao /** 101937cce918SMarri Devender Rao * Collection of LDAP certificates 102037cce918SMarri Devender Rao */ 10217e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificateCollection(App& app) 102237cce918SMarri Devender Rao { 10237e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/") 1024ed398213SEd Tanous .privileges(redfish::privileges::getCertificateCollection) 1025002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1026002d39b4SEd Tanous [&app](const crow::Request& req, 1027002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 10283ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 102945ca1b86SEd Tanous { 103045ca1b86SEd Tanous return; 103145ca1b86SEd Tanous } 10321476687dSEd Tanous 10331476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 10341476687dSEd Tanous "/redfish/v1/AccountService/LDAP/Certificates"; 10351476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 10361476687dSEd Tanous "#CertificateCollection.CertificateCollection"; 10371476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "LDAP Certificates Collection"; 10381476687dSEd Tanous asyncResp->res.jsonValue["Description"] = 10391476687dSEd Tanous "A Collection of LDAP certificate instances"; 10408d1b46d7Szhanghch05 1041d3f92ce7SJiaqing Zhao getCertificateList(asyncResp, certs::ldapObjectPath, 1042d3f92ce7SJiaqing Zhao "/Members"_json_pointer, 1043d3f92ce7SJiaqing Zhao "/Members@odata.count"_json_pointer); 10447e860f15SJohn Edward Broadbent }); 104537cce918SMarri Devender Rao 10467e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/") 1047ed398213SEd Tanous .privileges(redfish::privileges::postCertificateCollection) 10487e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 104945ca1b86SEd Tanous [&app](const crow::Request& req, 10507e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 10513ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 105245ca1b86SEd Tanous { 105345ca1b86SEd Tanous return; 105445ca1b86SEd Tanous } 1055002d39b4SEd Tanous std::string certFileBody = getCertificateFromReqBody(asyncResp, req); 105658eb238fSKowalski, Kamil 105758eb238fSKowalski, Kamil if (certFileBody.empty()) 105858eb238fSKowalski, Kamil { 1059002d39b4SEd Tanous BMCWEB_LOG_ERROR << "Cannot get certificate from request body."; 1060a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 106158eb238fSKowalski, Kamil return; 106258eb238fSKowalski, Kamil } 106358eb238fSKowalski, Kamil 106458eb238fSKowalski, Kamil std::shared_ptr<CertificateFile> certFile = 106558eb238fSKowalski, Kamil std::make_shared<CertificateFile>(certFileBody); 106658eb238fSKowalski, Kamil 106737cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 1068656ec7e3SZbigniew Kurzynski [asyncResp, certFile](const boost::system::error_code ec, 1069656ec7e3SZbigniew Kurzynski const std::string& objectPath) { 107037cce918SMarri Devender Rao if (ec) 107137cce918SMarri Devender Rao { 107237cce918SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 107337cce918SMarri Devender Rao messages::internalError(asyncResp->res); 107437cce918SMarri Devender Rao return; 107537cce918SMarri Devender Rao } 1076656ec7e3SZbigniew Kurzynski long certId = getIDFromURL(objectPath); 1077656ec7e3SZbigniew Kurzynski if (certId < 0) 1078656ec7e3SZbigniew Kurzynski { 1079002d39b4SEd Tanous BMCWEB_LOG_ERROR << "Invalid objectPath value" << objectPath; 1080656ec7e3SZbigniew Kurzynski messages::internalError(asyncResp->res); 1081656ec7e3SZbigniew Kurzynski return; 1082656ec7e3SZbigniew Kurzynski } 108337cce918SMarri Devender Rao std::string certURL = 108437cce918SMarri Devender Rao "/redfish/v1/AccountService/LDAP/Certificates/" + 108537cce918SMarri Devender Rao std::to_string(certId); 108637cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, 1087002d39b4SEd Tanous certs::ldapServiceName, certId, certURL, 1088002d39b4SEd Tanous "LDAP Certificate"); 108937cce918SMarri Devender Rao BMCWEB_LOG_DEBUG << "LDAP certificate install file=" 109037cce918SMarri Devender Rao << certFile->getCertFilePath(); 109137cce918SMarri Devender Rao }, 109237cce918SMarri Devender Rao certs::ldapServiceName, certs::ldapObjectPath, 1093002d39b4SEd Tanous certs::certInstallIntf, "Install", certFile->getCertFilePath()); 10947e860f15SJohn Edward Broadbent }); 10957e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificateCollection 109637cce918SMarri Devender Rao 109737cce918SMarri Devender Rao /** 109837cce918SMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 109937cce918SMarri Devender Rao * of a component, account or service. 110037cce918SMarri Devender Rao */ 11017e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificate(App& app) 110237cce918SMarri Devender Rao { 11037e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/") 1104ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 11057e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 110645ca1b86SEd Tanous [&app](const crow::Request& req, 11077e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 11087e860f15SJohn Edward Broadbent const std::string&) { 11093ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 111045ca1b86SEd Tanous { 111145ca1b86SEd Tanous return; 111245ca1b86SEd Tanous } 111337cce918SMarri Devender Rao long id = getIDFromURL(req.url); 111437cce918SMarri Devender Rao if (id < 0) 111537cce918SMarri Devender Rao { 111637cce918SMarri Devender Rao BMCWEB_LOG_ERROR << "Invalid url value" << req.url; 111737cce918SMarri Devender Rao messages::internalError(asyncResp->res); 111837cce918SMarri Devender Rao return; 111937cce918SMarri Devender Rao } 1120002d39b4SEd Tanous BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" << std::to_string(id); 1121002d39b4SEd Tanous std::string certURL = "/redfish/v1/AccountService/LDAP/Certificates/" + 112237cce918SMarri Devender Rao std::to_string(id); 112337cce918SMarri Devender Rao std::string objectPath = certs::ldapObjectPath; 112437cce918SMarri Devender Rao objectPath += "/"; 112537cce918SMarri Devender Rao objectPath += std::to_string(id); 1126002d39b4SEd Tanous getCertificateProperties(asyncResp, objectPath, certs::ldapServiceName, 1127002d39b4SEd Tanous id, certURL, "LDAP Certificate"); 11287e860f15SJohn Edward Broadbent }); 11297e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificate 1130cfcd5f6bSMarri Devender Rao /** 1131cfcd5f6bSMarri Devender Rao * Collection of TrustStoreCertificate certificates 1132cfcd5f6bSMarri Devender Rao */ 11337e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificateCollection(App& app) 1134cfcd5f6bSMarri Devender Rao { 11357e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/") 1136ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 1137002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1138002d39b4SEd Tanous [&app](const crow::Request& req, 1139002d39b4SEd Tanous const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 11403ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 114145ca1b86SEd Tanous { 114245ca1b86SEd Tanous return; 114345ca1b86SEd Tanous } 11441476687dSEd Tanous 11451476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 11461476687dSEd Tanous "/redfish/v1/Managers/bmc/Truststore/Certificates/"; 11471476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 11481476687dSEd Tanous "#CertificateCollection.CertificateCollection"; 1149002d39b4SEd Tanous asyncResp->res.jsonValue["Name"] = "TrustStore Certificates Collection"; 11501476687dSEd Tanous asyncResp->res.jsonValue["Description"] = 11511476687dSEd Tanous "A Collection of TrustStore certificate instances"; 11528d1b46d7Szhanghch05 1153d3f92ce7SJiaqing Zhao getCertificateList(asyncResp, certs::authorityObjectPath, 1154d3f92ce7SJiaqing Zhao "/Members"_json_pointer, 1155d3f92ce7SJiaqing Zhao "/Members@odata.count"_json_pointer); 11567e860f15SJohn Edward Broadbent }); 1157cfcd5f6bSMarri Devender Rao 11587e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/") 1159ed398213SEd Tanous .privileges(redfish::privileges::postCertificateCollection) 1160002d39b4SEd Tanous .methods(boost::beast::http::verb::post)( 1161002d39b4SEd Tanous [&app](const crow::Request& req, 11627e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 11633ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 116445ca1b86SEd Tanous { 116545ca1b86SEd Tanous return; 116645ca1b86SEd Tanous } 1167002d39b4SEd Tanous std::string certFileBody = getCertificateFromReqBody(asyncResp, req); 1168a08752f5SZbigniew Kurzynski 1169a08752f5SZbigniew Kurzynski if (certFileBody.empty()) 1170a08752f5SZbigniew Kurzynski { 11710fda0f12SGeorge Liu BMCWEB_LOG_ERROR << "Cannot get certificate from request body."; 1172a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 1173a08752f5SZbigniew Kurzynski return; 1174a08752f5SZbigniew Kurzynski } 1175a08752f5SZbigniew Kurzynski 1176a08752f5SZbigniew Kurzynski std::shared_ptr<CertificateFile> certFile = 1177a08752f5SZbigniew Kurzynski std::make_shared<CertificateFile>(certFileBody); 1178cfcd5f6bSMarri Devender Rao crow::connections::systemBus->async_method_call( 1179656ec7e3SZbigniew Kurzynski [asyncResp, certFile](const boost::system::error_code ec, 1180656ec7e3SZbigniew Kurzynski const std::string& objectPath) { 1181cfcd5f6bSMarri Devender Rao if (ec) 1182cfcd5f6bSMarri Devender Rao { 1183cfcd5f6bSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 1184cfcd5f6bSMarri Devender Rao messages::internalError(asyncResp->res); 1185cfcd5f6bSMarri Devender Rao return; 1186cfcd5f6bSMarri Devender Rao } 1187656ec7e3SZbigniew Kurzynski long certId = getIDFromURL(objectPath); 1188656ec7e3SZbigniew Kurzynski if (certId < 0) 1189656ec7e3SZbigniew Kurzynski { 1190002d39b4SEd Tanous BMCWEB_LOG_ERROR << "Invalid objectPath value" << objectPath; 1191656ec7e3SZbigniew Kurzynski messages::internalError(asyncResp->res); 1192656ec7e3SZbigniew Kurzynski return; 1193656ec7e3SZbigniew Kurzynski } 11940fda0f12SGeorge Liu std::string certURL = 11950fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/Truststore/Certificates/" + 1196cfcd5f6bSMarri Devender Rao std::to_string(certId); 1197656ec7e3SZbigniew Kurzynski 1198002d39b4SEd Tanous getCertificateProperties(asyncResp, objectPath, 1199002d39b4SEd Tanous certs::authorityServiceName, certId, 1200002d39b4SEd Tanous certURL, "TrustStore Certificate"); 12010fda0f12SGeorge Liu BMCWEB_LOG_DEBUG << "TrustStore certificate install file=" 1202cfcd5f6bSMarri Devender Rao << certFile->getCertFilePath(); 1203cfcd5f6bSMarri Devender Rao }, 1204cfcd5f6bSMarri Devender Rao certs::authorityServiceName, certs::authorityObjectPath, 12050fda0f12SGeorge Liu certs::certInstallIntf, "Install", certFile->getCertFilePath()); 12067e860f15SJohn Edward Broadbent }); 12077e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificateCollection 1208cfcd5f6bSMarri Devender Rao 1209cfcd5f6bSMarri Devender Rao /** 1210cfcd5f6bSMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 1211cfcd5f6bSMarri Devender Rao * of a component, account or service. 1212cfcd5f6bSMarri Devender Rao */ 12137e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificate(App& app) 1214cfcd5f6bSMarri Devender Rao { 12157e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/") 1216ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 12177e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 121845ca1b86SEd Tanous [&app](const crow::Request& req, 12197e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 12207e860f15SJohn Edward Broadbent const std::string&) { 12213ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 122245ca1b86SEd Tanous { 122345ca1b86SEd Tanous return; 122445ca1b86SEd Tanous } 1225cfcd5f6bSMarri Devender Rao long id = getIDFromURL(req.url); 1226cfcd5f6bSMarri Devender Rao if (id < 0) 1227cfcd5f6bSMarri Devender Rao { 1228cfcd5f6bSMarri Devender Rao BMCWEB_LOG_ERROR << "Invalid url value" << req.url; 1229cfcd5f6bSMarri Devender Rao messages::internalError(asyncResp->res); 1230cfcd5f6bSMarri Devender Rao return; 1231cfcd5f6bSMarri Devender Rao } 1232cfcd5f6bSMarri Devender Rao BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doGet ID=" 1233cfcd5f6bSMarri Devender Rao << std::to_string(id); 1234cfcd5f6bSMarri Devender Rao std::string certURL = 1235cfcd5f6bSMarri Devender Rao "/redfish/v1/Managers/bmc/Truststore/Certificates/" + 1236cfcd5f6bSMarri Devender Rao std::to_string(id); 1237cfcd5f6bSMarri Devender Rao std::string objectPath = certs::authorityObjectPath; 1238cfcd5f6bSMarri Devender Rao objectPath += "/"; 1239cfcd5f6bSMarri Devender Rao objectPath += std::to_string(id); 1240cfcd5f6bSMarri Devender Rao getCertificateProperties(asyncResp, objectPath, 1241002d39b4SEd Tanous certs::authorityServiceName, id, certURL, 1242002d39b4SEd Tanous "TrustStore Certificate"); 12437e860f15SJohn Edward Broadbent }); 124407a60299SZbigniew Kurzynski 12457e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/") 1246ed398213SEd Tanous .privileges(redfish::privileges::deleteCertificate) 12477e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::delete_)( 124845ca1b86SEd Tanous [&app](const crow::Request& req, 12497e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 12507e860f15SJohn Edward Broadbent const std::string& param) { 12513ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 125245ca1b86SEd Tanous { 125345ca1b86SEd Tanous return; 125445ca1b86SEd Tanous } 12557e860f15SJohn Edward Broadbent if (param.empty()) 125607a60299SZbigniew Kurzynski { 125707a60299SZbigniew Kurzynski messages::internalError(asyncResp->res); 125807a60299SZbigniew Kurzynski return; 125907a60299SZbigniew Kurzynski } 126007a60299SZbigniew Kurzynski 126107a60299SZbigniew Kurzynski long id = getIDFromURL(req.url); 126207a60299SZbigniew Kurzynski if (id < 0) 126307a60299SZbigniew Kurzynski { 126407a60299SZbigniew Kurzynski BMCWEB_LOG_ERROR << "Invalid url value: " << req.url; 1265002d39b4SEd Tanous messages::resourceNotFound(asyncResp->res, "TrustStore Certificate", 126607a60299SZbigniew Kurzynski std::string(req.url)); 126707a60299SZbigniew Kurzynski return; 126807a60299SZbigniew Kurzynski } 126907a60299SZbigniew Kurzynski BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doDelete ID=" 127007a60299SZbigniew Kurzynski << std::to_string(id); 127107a60299SZbigniew Kurzynski std::string certPath = certs::authorityObjectPath; 127207a60299SZbigniew Kurzynski certPath += "/"; 127307a60299SZbigniew Kurzynski certPath += std::to_string(id); 127407a60299SZbigniew Kurzynski 127507a60299SZbigniew Kurzynski crow::connections::systemBus->async_method_call( 127607a60299SZbigniew Kurzynski [asyncResp, id](const boost::system::error_code ec) { 127707a60299SZbigniew Kurzynski if (ec) 127807a60299SZbigniew Kurzynski { 127907a60299SZbigniew Kurzynski messages::resourceNotFound(asyncResp->res, 128007a60299SZbigniew Kurzynski "TrustStore Certificate", 128107a60299SZbigniew Kurzynski std::to_string(id)); 128207a60299SZbigniew Kurzynski return; 128307a60299SZbigniew Kurzynski } 128407a60299SZbigniew Kurzynski BMCWEB_LOG_INFO << "Certificate deleted"; 1285002d39b4SEd Tanous asyncResp->res.result(boost::beast::http::status::no_content); 128607a60299SZbigniew Kurzynski }, 128707a60299SZbigniew Kurzynski certs::authorityServiceName, certPath, certs::objDeleteIntf, 128807a60299SZbigniew Kurzynski "Delete"); 12897e860f15SJohn Edward Broadbent }); 12907e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificate 12915968caeeSMarri Devender Rao } // namespace redfish 1292