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> 6ed398213SEd Tanous #include <registries/privilege_registry.hpp> 71214b7e7SGunnar Mills 85968caeeSMarri Devender Rao #include <variant> 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 } 70*0fda0f12SGeorge Liu asyncResp->res 71*0fda0f12SGeorge Liu .jsonValue["Actions"] 72*0fda0f12SGeorge Liu ["#CertificateService.ReplaceCertificate"] = { 73*0fda0f12SGeorge Liu {"target", 74*0fda0f12SGeorge 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"] = { 78*0fda0f12SGeorge Liu {"target", 79*0fda0f12SGeorge 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 { 239*0fda0f12SGeorge Liu BMCWEB_ROUTE( 240*0fda0f12SGeorge Liu app, 241*0fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR/") 242ed398213SEd Tanous // Incorrect Privilege; Should be ConfigureManager 243ed398213SEd Tanous //.privileges(redfish::privileges::postCertificateService) 244432a890cSEd Tanous .privileges({{"ConfigureComponents"}}) 245*0fda0f12SGeorge Liu .methods( 246*0fda0f12SGeorge Liu boost::beast::http::verb:: 247*0fda0f12SGeorge 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( 276*0fda0f12SGeorge Liu req, asyncResp->res, "City", city, "CommonName", commonName, 277*0fda0f12SGeorge Liu "ContactPerson", optContactPerson, "Country", country, 278*0fda0f12SGeorge Liu "Organization", organization, "OrganizationalUnit", 279*0fda0f12SGeorge Liu organizationalUnit, "State", state, "CertificateCollection", 280*0fda0f12SGeorge Liu certificateCollection, "AlternativeNames", 281*0fda0f12SGeorge Liu optAlternativeNames, "ChallengePassword", 282*0fda0f12SGeorge Liu optChallengePassword, "Email", optEmail, "GivenName", 283*0fda0f12SGeorge Liu optGivenName, "Initials", optInitials, "KeyBitLength", 284*0fda0f12SGeorge Liu optKeyBitLength, "KeyCurveId", optKeyCurveId, 285*0fda0f12SGeorge Liu "KeyPairAlgorithm", optKeyPairAlgorithm, "KeyUsage", 286*0fda0f12SGeorge Liu optKeyUsage, "Surname", optSurname, "UnstructuredName", 287*0fda0f12SGeorge 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; 313*0fda0f12SGeorge Liu if (boost::starts_with( 314*0fda0f12SGeorge Liu certURI, 315*0fda0f12SGeorge 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 335*0fda0f12SGeorge 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 354*0fda0f12SGeorge Liu if (boost::starts_with( 355*0fda0f12SGeorge Liu certURI, 356*0fda0f12SGeorge 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)); 416*0fda0f12SGeorge Liu timeout.async_wait( 417*0fda0f12SGeorge 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; 435*0fda0f12SGeorge 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 } 452*0fda0f12SGeorge Liu std::vector< 453*0fda0f12SGeorge Liu std::pair<std::string, 45430215816SMarri Devender Rao std::vector<std::pair< 455*0fda0f12SGeorge Liu std::string, std::variant<std::string>>>>> 45630215816SMarri Devender Rao interfacesProperties; 45730215816SMarri Devender Rao sdbusplus::message::object_path csrObjectPath; 45830215816SMarri Devender Rao m.read(csrObjectPath, interfacesProperties); 459*0fda0f12SGeorge Liu BMCWEB_LOG_DEBUG << "CSR object added" << csrObjectPath.str; 46030215816SMarri Devender Rao for (auto& interface : interfacesProperties) 46130215816SMarri Devender Rao { 462*0fda0f12SGeorge 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, 484*0fda0f12SGeorge Liu *optGivenName, *optInitials, *optKeyBitLength, *optKeyCurveId, 485*0fda0f12SGeorge Liu *optKeyPairAlgorithm, *optKeyUsage, organization, 486*0fda0f12SGeorge 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 { 5725968caeeSMarri Devender Rao using PropertyType = 5735968caeeSMarri Devender Rao std::variant<std::string, uint64_t, std::vector<std::string>>; 5745968caeeSMarri Devender Rao using PropertiesMap = boost::container::flat_map<std::string, PropertyType>; 5755968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "getCertificateProperties Path=" << objectPath 5765968caeeSMarri Devender Rao << " certId=" << certId << " certURl=" << certURL; 5775968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 57837cce918SMarri Devender Rao [asyncResp, certURL, certId, name](const boost::system::error_code ec, 5795968caeeSMarri Devender Rao const PropertiesMap& properties) { 5805968caeeSMarri Devender Rao if (ec) 5815968caeeSMarri Devender Rao { 5825968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 5838aae75adSMarri Devender Rao messages::resourceNotFound(asyncResp->res, name, 5848aae75adSMarri Devender Rao std::to_string(certId)); 5855968caeeSMarri Devender Rao return; 5865968caeeSMarri Devender Rao } 5875968caeeSMarri Devender Rao asyncResp->res.jsonValue = { 5885968caeeSMarri Devender Rao {"@odata.id", certURL}, 5895968caeeSMarri Devender Rao {"@odata.type", "#Certificate.v1_0_0.Certificate"}, 5905968caeeSMarri Devender Rao {"Id", std::to_string(certId)}, 5915968caeeSMarri Devender Rao {"Name", name}, 5925968caeeSMarri Devender Rao {"Description", name}}; 5935968caeeSMarri Devender Rao for (const auto& property : properties) 5945968caeeSMarri Devender Rao { 5955968caeeSMarri Devender Rao if (property.first == "CertificateString") 5965968caeeSMarri Devender Rao { 5975968caeeSMarri Devender Rao asyncResp->res.jsonValue["CertificateString"] = ""; 5985968caeeSMarri Devender Rao const std::string* value = 5995968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 6005968caeeSMarri Devender Rao if (value) 6015968caeeSMarri Devender Rao { 60237cce918SMarri Devender Rao asyncResp->res.jsonValue["CertificateString"] = *value; 6035968caeeSMarri Devender Rao } 6045968caeeSMarri Devender Rao } 6055968caeeSMarri Devender Rao else if (property.first == "KeyUsage") 6065968caeeSMarri Devender Rao { 6075968caeeSMarri Devender Rao nlohmann::json& keyUsage = 6085968caeeSMarri Devender Rao asyncResp->res.jsonValue["KeyUsage"]; 6095968caeeSMarri Devender Rao keyUsage = nlohmann::json::array(); 6105968caeeSMarri Devender Rao const std::vector<std::string>* value = 61137cce918SMarri Devender Rao std::get_if<std::vector<std::string>>(&property.second); 6125968caeeSMarri Devender Rao if (value) 6135968caeeSMarri Devender Rao { 6145968caeeSMarri Devender Rao for (const std::string& usage : *value) 6155968caeeSMarri Devender Rao { 6165968caeeSMarri Devender Rao keyUsage.push_back(usage); 6175968caeeSMarri Devender Rao } 6185968caeeSMarri Devender Rao } 6195968caeeSMarri Devender Rao } 6205968caeeSMarri Devender Rao else if (property.first == "Issuer") 6215968caeeSMarri Devender Rao { 6225968caeeSMarri Devender Rao const std::string* value = 6235968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 6245968caeeSMarri Devender Rao if (value) 6255968caeeSMarri Devender Rao { 6265968caeeSMarri Devender Rao updateCertIssuerOrSubject( 6275968caeeSMarri Devender Rao asyncResp->res.jsonValue["Issuer"], *value); 6285968caeeSMarri Devender Rao } 6295968caeeSMarri Devender Rao } 6305968caeeSMarri Devender Rao else if (property.first == "Subject") 6315968caeeSMarri Devender Rao { 6325968caeeSMarri Devender Rao const std::string* value = 6335968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 6345968caeeSMarri Devender Rao if (value) 6355968caeeSMarri Devender Rao { 6365968caeeSMarri Devender Rao updateCertIssuerOrSubject( 63737cce918SMarri Devender Rao asyncResp->res.jsonValue["Subject"], *value); 6385968caeeSMarri Devender Rao } 6395968caeeSMarri Devender Rao } 6405968caeeSMarri Devender Rao else if (property.first == "ValidNotAfter") 6415968caeeSMarri Devender Rao { 6425968caeeSMarri Devender Rao const uint64_t* value = 6435968caeeSMarri Devender Rao std::get_if<uint64_t>(&property.second); 6445968caeeSMarri Devender Rao if (value) 6455968caeeSMarri Devender Rao { 64637cce918SMarri Devender Rao std::time_t time = static_cast<std::time_t>(*value); 6475968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotAfter"] = 6485968caeeSMarri Devender Rao crow::utility::getDateTime(time); 6495968caeeSMarri Devender Rao } 6505968caeeSMarri Devender Rao } 6515968caeeSMarri Devender Rao else if (property.first == "ValidNotBefore") 6525968caeeSMarri Devender Rao { 6535968caeeSMarri Devender Rao const uint64_t* value = 6545968caeeSMarri Devender Rao std::get_if<uint64_t>(&property.second); 6555968caeeSMarri Devender Rao if (value) 6565968caeeSMarri Devender Rao { 65737cce918SMarri Devender Rao std::time_t time = static_cast<std::time_t>(*value); 6585968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotBefore"] = 6595968caeeSMarri Devender Rao crow::utility::getDateTime(time); 6605968caeeSMarri Devender Rao } 6615968caeeSMarri Devender Rao } 6625968caeeSMarri Devender Rao } 6635968caeeSMarri Devender Rao asyncResp->res.addHeader("Location", certURL); 6645968caeeSMarri Devender Rao }, 6655968caeeSMarri Devender Rao service, objectPath, certs::dbusPropIntf, "GetAll", 6665968caeeSMarri Devender Rao certs::certPropIntf); 6675968caeeSMarri Devender Rao } 6685968caeeSMarri Devender Rao 6695968caeeSMarri Devender Rao using GetObjectType = 6705968caeeSMarri Devender Rao std::vector<std::pair<std::string, std::vector<std::string>>>; 6715968caeeSMarri Devender Rao 6725968caeeSMarri Devender Rao /** 6735968caeeSMarri Devender Rao * Action to replace an existing certificate 6745968caeeSMarri Devender Rao */ 6757e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionsReplaceCertificate(App& app) 6765968caeeSMarri Devender Rao { 677*0fda0f12SGeorge Liu BMCWEB_ROUTE( 678*0fda0f12SGeorge Liu app, 679*0fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate/") 680ed398213SEd Tanous .privileges(redfish::privileges::postCertificateService) 6817e860f15SJohn Edward Broadbent .methods( 6827e860f15SJohn Edward Broadbent boost::beast::http::verb:: 6837e860f15SJohn Edward Broadbent post)([](const crow::Request& req, 6847e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 6855968caeeSMarri Devender Rao std::string certificate; 6865968caeeSMarri Devender Rao nlohmann::json certificateUri; 6875968caeeSMarri Devender Rao std::optional<std::string> certificateType = "PEM"; 6888d1b46d7Szhanghch05 6895968caeeSMarri Devender Rao if (!json_util::readJson(req, asyncResp->res, "CertificateString", 6907e860f15SJohn Edward Broadbent certificate, "CertificateUri", 6917e860f15SJohn Edward Broadbent certificateUri, "CertificateType", 6927e860f15SJohn Edward Broadbent certificateType)) 6935968caeeSMarri Devender Rao { 6945968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Required parameters are missing"; 6955968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 6965968caeeSMarri Devender Rao return; 6975968caeeSMarri Devender Rao } 6985968caeeSMarri Devender Rao 6995968caeeSMarri Devender Rao if (!certificateType) 7005968caeeSMarri Devender Rao { 7015968caeeSMarri Devender Rao // should never happen, but it never hurts to be paranoid. 7025968caeeSMarri Devender Rao return; 7035968caeeSMarri Devender Rao } 7045968caeeSMarri Devender Rao if (certificateType != "PEM") 7055968caeeSMarri Devender Rao { 7065968caeeSMarri Devender Rao messages::actionParameterNotSupported( 7075968caeeSMarri Devender Rao asyncResp->res, "CertificateType", "ReplaceCertificate"); 7085968caeeSMarri Devender Rao return; 7095968caeeSMarri Devender Rao } 7105968caeeSMarri Devender Rao 7115968caeeSMarri Devender Rao std::string certURI; 7125968caeeSMarri Devender Rao if (!redfish::json_util::readJson(certificateUri, asyncResp->res, 7135968caeeSMarri Devender Rao "@odata.id", certURI)) 7145968caeeSMarri Devender Rao { 7155968caeeSMarri Devender Rao messages::actionParameterMissing( 7165968caeeSMarri Devender Rao asyncResp->res, "ReplaceCertificate", "CertificateUri"); 7175968caeeSMarri Devender Rao return; 7185968caeeSMarri Devender Rao } 7195968caeeSMarri Devender Rao 7205968caeeSMarri Devender Rao BMCWEB_LOG_INFO << "Certificate URI to replace" << certURI; 7215968caeeSMarri Devender Rao long id = getIDFromURL(certURI); 7225968caeeSMarri Devender Rao if (id < 0) 7235968caeeSMarri Devender Rao { 7247e860f15SJohn Edward Broadbent messages::actionParameterValueFormatError( 7257e860f15SJohn Edward Broadbent asyncResp->res, certURI, "CertificateUri", 7265968caeeSMarri Devender Rao "ReplaceCertificate"); 7275968caeeSMarri Devender Rao return; 7285968caeeSMarri Devender Rao } 7295968caeeSMarri Devender Rao std::string objectPath; 7305968caeeSMarri Devender Rao std::string name; 73137cce918SMarri Devender Rao std::string service; 732*0fda0f12SGeorge Liu if (boost::starts_with( 733*0fda0f12SGeorge Liu certURI, 734*0fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")) 7355968caeeSMarri Devender Rao { 7367e860f15SJohn Edward Broadbent objectPath = std::string(certs::httpsObjectPath) + "/" + 7377e860f15SJohn Edward Broadbent std::to_string(id); 7385968caeeSMarri Devender Rao name = "HTTPS certificate"; 73937cce918SMarri Devender Rao service = certs::httpsServiceName; 74037cce918SMarri Devender Rao } 74137cce918SMarri Devender Rao else if (boost::starts_with( 7427e860f15SJohn Edward Broadbent certURI, 7437e860f15SJohn Edward Broadbent "/redfish/v1/AccountService/LDAP/Certificates/")) 74437cce918SMarri Devender Rao { 7457e860f15SJohn Edward Broadbent objectPath = std::string(certs::ldapObjectPath) + "/" + 7467e860f15SJohn Edward Broadbent std::to_string(id); 74737cce918SMarri Devender Rao name = "LDAP certificate"; 74837cce918SMarri Devender Rao service = certs::ldapServiceName; 7495968caeeSMarri Devender Rao } 750cfcd5f6bSMarri Devender Rao else if (boost::starts_with( 751cfcd5f6bSMarri Devender Rao certURI, 752cfcd5f6bSMarri Devender Rao "/redfish/v1/Managers/bmc/Truststore/Certificates/")) 753cfcd5f6bSMarri Devender Rao { 754cfcd5f6bSMarri Devender Rao objectPath = std::string(certs::authorityObjectPath) + "/" + 755cfcd5f6bSMarri Devender Rao std::to_string(id); 756cfcd5f6bSMarri Devender Rao name = "TrustStore certificate"; 757cfcd5f6bSMarri Devender Rao service = certs::authorityServiceName; 758cfcd5f6bSMarri Devender Rao } 7595968caeeSMarri Devender Rao else 7605968caeeSMarri Devender Rao { 7615968caeeSMarri Devender Rao messages::actionParameterNotSupported( 7625968caeeSMarri Devender Rao asyncResp->res, "CertificateUri", "ReplaceCertificate"); 7635968caeeSMarri Devender Rao return; 7645968caeeSMarri Devender Rao } 7655968caeeSMarri Devender Rao 7665968caeeSMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 7675968caeeSMarri Devender Rao std::make_shared<CertificateFile>(certificate); 7685968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 76937cce918SMarri Devender Rao [asyncResp, certFile, objectPath, service, certURI, id, 7705968caeeSMarri Devender Rao name](const boost::system::error_code ec) { 7715968caeeSMarri Devender Rao if (ec) 7725968caeeSMarri Devender Rao { 7735968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 7748aae75adSMarri Devender Rao messages::resourceNotFound(asyncResp->res, name, 7758aae75adSMarri Devender Rao std::to_string(id)); 7765968caeeSMarri Devender Rao return; 7775968caeeSMarri Devender Rao } 77837cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, service, id, 7795968caeeSMarri Devender Rao certURI, name); 7805968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" 7815968caeeSMarri Devender Rao << certFile->getCertFilePath(); 7825968caeeSMarri Devender Rao }, 7835968caeeSMarri Devender Rao service, objectPath, certs::certReplaceIntf, "Replace", 7845968caeeSMarri Devender Rao certFile->getCertFilePath()); 7857e860f15SJohn Edward Broadbent }); 7867e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionsReplaceCertificate 7875968caeeSMarri Devender Rao 7885968caeeSMarri Devender Rao /** 7895968caeeSMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 7905968caeeSMarri Devender Rao * of a component, account or service. 7915968caeeSMarri Devender Rao */ 7925968caeeSMarri Devender Rao 7937e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificate(App& app) 7945968caeeSMarri Devender Rao { 7957e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 7967e860f15SJohn Edward Broadbent app, 7977e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/<str>/") 798ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 7997e860f15SJohn Edward Broadbent .methods( 8007e860f15SJohn Edward Broadbent boost::beast::http::verb:: 8017e860f15SJohn Edward Broadbent get)([](const crow::Request& req, 8027e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 8037e860f15SJohn Edward Broadbent const std::string& param) -> void { 8047e860f15SJohn Edward Broadbent if (param.empty()) 8055968caeeSMarri Devender Rao { 8065968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 8075968caeeSMarri Devender Rao return; 8085968caeeSMarri Devender Rao } 8095968caeeSMarri Devender Rao long id = getIDFromURL(req.url); 8105968caeeSMarri Devender Rao 8117e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG << "HTTPSCertificate::doGet ID=" 8127e860f15SJohn Edward Broadbent << std::to_string(id); 8135968caeeSMarri Devender Rao std::string certURL = 8145968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" + 8155968caeeSMarri Devender Rao std::to_string(id); 8165968caeeSMarri Devender Rao std::string objectPath = certs::httpsObjectPath; 8175968caeeSMarri Devender Rao objectPath += "/"; 8185968caeeSMarri Devender Rao objectPath += std::to_string(id); 8197e860f15SJohn Edward Broadbent getCertificateProperties(asyncResp, objectPath, 8207e860f15SJohn Edward Broadbent certs::httpsServiceName, id, certURL, 8217e860f15SJohn Edward Broadbent "HTTPS Certificate"); 8227e860f15SJohn Edward Broadbent }); 8235968caeeSMarri Devender Rao } 8245968caeeSMarri Devender Rao 8255968caeeSMarri Devender Rao /** 8265968caeeSMarri Devender Rao * Collection of HTTPS certificates 8275968caeeSMarri Devender Rao */ 8287e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificateCollection(App& app) 8295968caeeSMarri Devender Rao { 8307e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 8315968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/") 832ed398213SEd Tanous .privileges(redfish::privileges::getCertificateCollection) 8337e860f15SJohn Edward Broadbent .methods( 8347e860f15SJohn Edward Broadbent boost::beast::http::verb:: 8357e860f15SJohn Edward Broadbent get)([](const crow::Request&, 8367e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 8378d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 8385968caeeSMarri Devender Rao {"@odata.id", 8395968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"}, 8405968caeeSMarri Devender Rao {"@odata.type", "#CertificateCollection.CertificateCollection"}, 8415968caeeSMarri Devender Rao {"Name", "HTTPS Certificates Collection"}, 8425968caeeSMarri Devender Rao {"Description", "A Collection of HTTPS certificate instances"}}; 8438d1b46d7Szhanghch05 8445968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 8455968caeeSMarri Devender Rao [asyncResp](const boost::system::error_code ec, 8465968caeeSMarri Devender Rao const ManagedObjectType& certs) { 8475968caeeSMarri Devender Rao if (ec) 8485968caeeSMarri Devender Rao { 8495968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 8505968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 8515968caeeSMarri Devender Rao return; 8525968caeeSMarri Devender Rao } 8537e860f15SJohn Edward Broadbent nlohmann::json& members = 8547e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Members"]; 8555968caeeSMarri Devender Rao members = nlohmann::json::array(); 8565968caeeSMarri Devender Rao for (const auto& cert : certs) 8575968caeeSMarri Devender Rao { 8585968caeeSMarri Devender Rao long id = getIDFromURL(cert.first.str); 85937cce918SMarri Devender Rao if (id >= 0) 8605968caeeSMarri Devender Rao { 8615968caeeSMarri Devender Rao members.push_back( 8625968caeeSMarri Devender Rao {{"@odata.id", 863*0fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" + 8645968caeeSMarri Devender Rao std::to_string(id)}}); 8655968caeeSMarri Devender Rao } 8665968caeeSMarri Devender Rao } 8675968caeeSMarri Devender Rao asyncResp->res.jsonValue["Members@odata.count"] = 8685968caeeSMarri Devender Rao members.size(); 8695968caeeSMarri Devender Rao }, 87037cce918SMarri Devender Rao certs::httpsServiceName, certs::httpsObjectPath, 87137cce918SMarri Devender Rao certs::dbusObjManagerIntf, "GetManagedObjects"); 8727e860f15SJohn Edward Broadbent }); 8735968caeeSMarri Devender Rao 8747e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 8757e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/") 876ed398213SEd Tanous .privileges(redfish::privileges::postCertificateCollection) 877*0fda0f12SGeorge Liu .methods( 878*0fda0f12SGeorge Liu boost::beast::http::verb:: 879*0fda0f12SGeorge Liu post)([](const crow::Request& req, 8807e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 8815968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost"; 8828d1b46d7Szhanghch05 883*0fda0f12SGeorge Liu asyncResp->res.jsonValue = {{"Name", "HTTPS Certificate"}, 8845968caeeSMarri Devender Rao {"Description", "HTTPS Certificate"}}; 8855968caeeSMarri Devender Rao 8867e860f15SJohn Edward Broadbent std::string certFileBody = 8877e860f15SJohn Edward Broadbent getCertificateFromReqBody(asyncResp, req); 88858eb238fSKowalski, Kamil 88958eb238fSKowalski, Kamil if (certFileBody.empty()) 89058eb238fSKowalski, Kamil { 891*0fda0f12SGeorge Liu BMCWEB_LOG_ERROR << "Cannot get certificate from request body."; 892a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 89358eb238fSKowalski, Kamil return; 89458eb238fSKowalski, Kamil } 89558eb238fSKowalski, Kamil 8965968caeeSMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 89758eb238fSKowalski, Kamil std::make_shared<CertificateFile>(certFileBody); 8985968caeeSMarri Devender Rao 8995968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 900656ec7e3SZbigniew Kurzynski [asyncResp, certFile](const boost::system::error_code ec, 901656ec7e3SZbigniew Kurzynski const std::string& objectPath) { 9025968caeeSMarri Devender Rao if (ec) 9035968caeeSMarri Devender Rao { 9045968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 9055968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 9065968caeeSMarri Devender Rao return; 9075968caeeSMarri Devender Rao } 908656ec7e3SZbigniew Kurzynski long certId = getIDFromURL(objectPath); 909656ec7e3SZbigniew Kurzynski if (certId < 0) 910656ec7e3SZbigniew Kurzynski { 911656ec7e3SZbigniew Kurzynski BMCWEB_LOG_ERROR << "Invalid objectPath value" 912656ec7e3SZbigniew Kurzynski << objectPath; 913656ec7e3SZbigniew Kurzynski messages::internalError(asyncResp->res); 914656ec7e3SZbigniew Kurzynski return; 915656ec7e3SZbigniew Kurzynski } 9165968caeeSMarri Devender Rao std::string certURL = 917*0fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" + 9185968caeeSMarri Devender Rao std::to_string(certId); 919*0fda0f12SGeorge Liu getCertificateProperties(asyncResp, objectPath, 920*0fda0f12SGeorge Liu certs::httpsServiceName, certId, 921*0fda0f12SGeorge Liu certURL, "HTTPS Certificate"); 9225968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" 9235968caeeSMarri Devender Rao << certFile->getCertFilePath(); 9245968caeeSMarri Devender Rao }, 92537cce918SMarri Devender Rao certs::httpsServiceName, certs::httpsObjectPath, 926*0fda0f12SGeorge Liu certs::certInstallIntf, "Install", certFile->getCertFilePath()); 9277e860f15SJohn Edward Broadbent }); 9287e860f15SJohn Edward Broadbent } // requestRoutesHTTPSCertificateCollection 9295968caeeSMarri Devender Rao 9305968caeeSMarri Devender Rao /** 93137cce918SMarri Devender Rao * @brief Retrieve the certificates installed list and append to the 93237cce918SMarri Devender Rao * response 93337cce918SMarri Devender Rao * 93437cce918SMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 93537cce918SMarri Devender Rao * @param[in] certURL Path of the certificate object 93637cce918SMarri Devender Rao * @param[in] path Path of the D-Bus service object 93737cce918SMarri Devender Rao * @return None 93837cce918SMarri Devender Rao */ 9394f48d5f6SEd Tanous inline void 9404f48d5f6SEd Tanous getCertificateLocations(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 9418d1b46d7Szhanghch05 const std::string& certURL, const std::string& path, 94237cce918SMarri Devender Rao const std::string& service) 94337cce918SMarri Devender Rao { 94437cce918SMarri Devender Rao BMCWEB_LOG_DEBUG << "getCertificateLocations URI=" << certURL 94537cce918SMarri Devender Rao << " Path=" << path << " service= " << service; 94637cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 94737cce918SMarri Devender Rao [asyncResp, certURL](const boost::system::error_code ec, 94837cce918SMarri Devender Rao const ManagedObjectType& certs) { 94937cce918SMarri Devender Rao if (ec) 95037cce918SMarri Devender Rao { 9519c8e039eSJonathan Doman BMCWEB_LOG_WARNING 9529c8e039eSJonathan Doman << "Certificate collection query failed: " << ec 9539c8e039eSJonathan Doman << ", skipping " << certURL; 95437cce918SMarri Devender Rao return; 95537cce918SMarri Devender Rao } 95637cce918SMarri Devender Rao nlohmann::json& links = 95737cce918SMarri Devender Rao asyncResp->res.jsonValue["Links"]["Certificates"]; 95837cce918SMarri Devender Rao for (auto& cert : certs) 95937cce918SMarri Devender Rao { 96037cce918SMarri Devender Rao long id = getIDFromURL(cert.first.str); 96137cce918SMarri Devender Rao if (id >= 0) 96237cce918SMarri Devender Rao { 96337cce918SMarri Devender Rao links.push_back( 96437cce918SMarri Devender Rao {{"@odata.id", certURL + std::to_string(id)}}); 96537cce918SMarri Devender Rao } 96637cce918SMarri Devender Rao } 96737cce918SMarri Devender Rao asyncResp->res.jsonValue["Links"]["Certificates@odata.count"] = 96837cce918SMarri Devender Rao links.size(); 96937cce918SMarri Devender Rao }, 97037cce918SMarri Devender Rao service, path, certs::dbusObjManagerIntf, "GetManagedObjects"); 9715968caeeSMarri Devender Rao } 9727e860f15SJohn Edward Broadbent 9737e860f15SJohn Edward Broadbent /** 9747e860f15SJohn Edward Broadbent * The certificate location schema defines a resource that an administrator 9757e860f15SJohn Edward Broadbent * can use in order to locate all certificates installed on a given service. 9767e860f15SJohn Edward Broadbent */ 9777e860f15SJohn Edward Broadbent inline void requestRoutesCertificateLocations(App& app) 9787e860f15SJohn Edward Broadbent { 9797e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/") 980ed398213SEd Tanous .privileges(redfish::privileges::getCertificateLocations) 9817e860f15SJohn Edward Broadbent .methods( 9827e860f15SJohn Edward Broadbent boost::beast::http::verb:: 9837e860f15SJohn Edward Broadbent get)([](const crow::Request&, 9847e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 9857e860f15SJohn Edward Broadbent asyncResp->res.jsonValue = { 9867e860f15SJohn Edward Broadbent {"@odata.id", 9877e860f15SJohn Edward Broadbent "/redfish/v1/CertificateService/CertificateLocations"}, 9887e860f15SJohn Edward Broadbent {"@odata.type", 9897e860f15SJohn Edward Broadbent "#CertificateLocations.v1_0_0.CertificateLocations"}, 9907e860f15SJohn Edward Broadbent {"Name", "Certificate Locations"}, 9917e860f15SJohn Edward Broadbent {"Id", "CertificateLocations"}, 9927e860f15SJohn Edward Broadbent {"Description", 9937e860f15SJohn Edward Broadbent "Defines a resource that an administrator can use in order to " 9947e860f15SJohn Edward Broadbent "locate all certificates installed on a given service"}}; 9957e860f15SJohn Edward Broadbent 9967e860f15SJohn Edward Broadbent nlohmann::json& links = 9977e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Links"]["Certificates"]; 9987e860f15SJohn Edward Broadbent links = nlohmann::json::array(); 9997e860f15SJohn Edward Broadbent getCertificateLocations( 10007e860f15SJohn Edward Broadbent asyncResp, 10017e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/", 10027e860f15SJohn Edward Broadbent certs::httpsObjectPath, certs::httpsServiceName); 10037e860f15SJohn Edward Broadbent getCertificateLocations( 10047e860f15SJohn Edward Broadbent asyncResp, "/redfish/v1/AccountService/LDAP/Certificates/", 10057e860f15SJohn Edward Broadbent certs::ldapObjectPath, certs::ldapServiceName); 10067e860f15SJohn Edward Broadbent getCertificateLocations( 10077e860f15SJohn Edward Broadbent asyncResp, "/redfish/v1/Managers/bmc/Truststore/Certificates/", 10087e860f15SJohn Edward Broadbent certs::authorityObjectPath, certs::authorityServiceName); 10097e860f15SJohn Edward Broadbent }); 10107e860f15SJohn Edward Broadbent } 10117e860f15SJohn Edward Broadbent // requestRoutesCertificateLocations 101237cce918SMarri Devender Rao 101337cce918SMarri Devender Rao /** 101437cce918SMarri Devender Rao * Collection of LDAP certificates 101537cce918SMarri Devender Rao */ 10167e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificateCollection(App& app) 101737cce918SMarri Devender Rao { 10187e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/") 1019ed398213SEd Tanous .privileges(redfish::privileges::getCertificateCollection) 1020*0fda0f12SGeorge Liu .methods( 1021*0fda0f12SGeorge Liu boost::beast::http::verb:: 1022*0fda0f12SGeorge Liu get)([](const crow::Request&, 10237e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 10248d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 1025*0fda0f12SGeorge Liu {"@odata.id", "/redfish/v1/AccountService/LDAP/Certificates"}, 1026*0fda0f12SGeorge Liu {"@odata.type", "#CertificateCollection.CertificateCollection"}, 102737cce918SMarri Devender Rao {"Name", "LDAP Certificates Collection"}, 1028*0fda0f12SGeorge Liu {"Description", "A Collection of LDAP certificate instances"}}; 10298d1b46d7Szhanghch05 103037cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 103137cce918SMarri Devender Rao [asyncResp](const boost::system::error_code ec, 103237cce918SMarri Devender Rao const ManagedObjectType& certs) { 10337e860f15SJohn Edward Broadbent nlohmann::json& members = 10347e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Members"]; 10359c8e039eSJonathan Doman nlohmann::json& count = 10369c8e039eSJonathan Doman asyncResp->res.jsonValue["Members@odata.count"]; 10379c8e039eSJonathan Doman members = nlohmann::json::array(); 10389c8e039eSJonathan Doman count = 0; 103937cce918SMarri Devender Rao if (ec) 104037cce918SMarri Devender Rao { 1041*0fda0f12SGeorge Liu BMCWEB_LOG_WARNING << "LDAP certificate query failed: " 1042*0fda0f12SGeorge Liu << ec; 104337cce918SMarri Devender Rao return; 104437cce918SMarri Devender Rao } 104537cce918SMarri Devender Rao for (const auto& cert : certs) 104637cce918SMarri Devender Rao { 104737cce918SMarri Devender Rao long id = getIDFromURL(cert.first.str); 104837cce918SMarri Devender Rao if (id >= 0) 104937cce918SMarri Devender Rao { 105037cce918SMarri Devender Rao members.push_back( 1051*0fda0f12SGeorge Liu {{"@odata.id", 1052*0fda0f12SGeorge Liu "/redfish/v1/AccountService/LDAP/Certificates/" + 105337cce918SMarri Devender Rao std::to_string(id)}}); 105437cce918SMarri Devender Rao } 105537cce918SMarri Devender Rao } 10569c8e039eSJonathan Doman count = members.size(); 105737cce918SMarri Devender Rao }, 105837cce918SMarri Devender Rao certs::ldapServiceName, certs::ldapObjectPath, 105937cce918SMarri Devender Rao certs::dbusObjManagerIntf, "GetManagedObjects"); 10607e860f15SJohn Edward Broadbent }); 106137cce918SMarri Devender Rao 10627e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/") 1063ed398213SEd Tanous .privileges(redfish::privileges::postCertificateCollection) 10647e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 10657e860f15SJohn Edward Broadbent [](const crow::Request& req, 10667e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 10677e860f15SJohn Edward Broadbent std::string certFileBody = 10687e860f15SJohn Edward Broadbent getCertificateFromReqBody(asyncResp, req); 106958eb238fSKowalski, Kamil 107058eb238fSKowalski, Kamil if (certFileBody.empty()) 107158eb238fSKowalski, Kamil { 10727e860f15SJohn Edward Broadbent BMCWEB_LOG_ERROR 10737e860f15SJohn Edward Broadbent << "Cannot get certificate from request body."; 1074a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 107558eb238fSKowalski, Kamil return; 107658eb238fSKowalski, Kamil } 107758eb238fSKowalski, Kamil 107858eb238fSKowalski, Kamil std::shared_ptr<CertificateFile> certFile = 107958eb238fSKowalski, Kamil std::make_shared<CertificateFile>(certFileBody); 108058eb238fSKowalski, Kamil 108137cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 1082656ec7e3SZbigniew Kurzynski [asyncResp, certFile](const boost::system::error_code ec, 1083656ec7e3SZbigniew Kurzynski const std::string& objectPath) { 108437cce918SMarri Devender Rao if (ec) 108537cce918SMarri Devender Rao { 108637cce918SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 108737cce918SMarri Devender Rao messages::internalError(asyncResp->res); 108837cce918SMarri Devender Rao return; 108937cce918SMarri Devender Rao } 1090656ec7e3SZbigniew Kurzynski long certId = getIDFromURL(objectPath); 1091656ec7e3SZbigniew Kurzynski if (certId < 0) 1092656ec7e3SZbigniew Kurzynski { 1093656ec7e3SZbigniew Kurzynski BMCWEB_LOG_ERROR << "Invalid objectPath value" 1094656ec7e3SZbigniew Kurzynski << objectPath; 1095656ec7e3SZbigniew Kurzynski messages::internalError(asyncResp->res); 1096656ec7e3SZbigniew Kurzynski return; 1097656ec7e3SZbigniew Kurzynski } 109837cce918SMarri Devender Rao std::string certURL = 109937cce918SMarri Devender Rao "/redfish/v1/AccountService/LDAP/Certificates/" + 110037cce918SMarri Devender Rao std::to_string(certId); 110137cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, 110237cce918SMarri Devender Rao certs::ldapServiceName, certId, 110337cce918SMarri Devender Rao certURL, "LDAP Certificate"); 110437cce918SMarri Devender Rao BMCWEB_LOG_DEBUG << "LDAP certificate install file=" 110537cce918SMarri Devender Rao << certFile->getCertFilePath(); 110637cce918SMarri Devender Rao }, 110737cce918SMarri Devender Rao certs::ldapServiceName, certs::ldapObjectPath, 11087e860f15SJohn Edward Broadbent certs::certInstallIntf, "Install", 11097e860f15SJohn Edward Broadbent certFile->getCertFilePath()); 11107e860f15SJohn Edward Broadbent }); 11117e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificateCollection 111237cce918SMarri Devender Rao 111337cce918SMarri Devender Rao /** 111437cce918SMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 111537cce918SMarri Devender Rao * of a component, account or service. 111637cce918SMarri Devender Rao */ 11177e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificate(App& app) 111837cce918SMarri Devender Rao { 11197e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/") 1120ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 11217e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 11227e860f15SJohn Edward Broadbent [](const crow::Request& req, 11237e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 11247e860f15SJohn Edward Broadbent const std::string&) { 112537cce918SMarri Devender Rao long id = getIDFromURL(req.url); 112637cce918SMarri Devender Rao if (id < 0) 112737cce918SMarri Devender Rao { 112837cce918SMarri Devender Rao BMCWEB_LOG_ERROR << "Invalid url value" << req.url; 112937cce918SMarri Devender Rao messages::internalError(asyncResp->res); 113037cce918SMarri Devender Rao return; 113137cce918SMarri Devender Rao } 11327e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" 11337e860f15SJohn Edward Broadbent << std::to_string(id); 11347e860f15SJohn Edward Broadbent std::string certURL = 11357e860f15SJohn Edward Broadbent "/redfish/v1/AccountService/LDAP/Certificates/" + 113637cce918SMarri Devender Rao std::to_string(id); 113737cce918SMarri Devender Rao std::string objectPath = certs::ldapObjectPath; 113837cce918SMarri Devender Rao objectPath += "/"; 113937cce918SMarri Devender Rao objectPath += std::to_string(id); 11407e860f15SJohn Edward Broadbent getCertificateProperties(asyncResp, objectPath, 11417e860f15SJohn Edward Broadbent certs::ldapServiceName, id, certURL, 11427e860f15SJohn Edward Broadbent "LDAP Certificate"); 11437e860f15SJohn Edward Broadbent }); 11447e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificate 1145cfcd5f6bSMarri Devender Rao /** 1146cfcd5f6bSMarri Devender Rao * Collection of TrustStoreCertificate certificates 1147cfcd5f6bSMarri Devender Rao */ 11487e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificateCollection(App& app) 1149cfcd5f6bSMarri Devender Rao { 11507e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/") 1151ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 1152*0fda0f12SGeorge Liu .methods( 1153*0fda0f12SGeorge Liu boost::beast::http::verb:: 1154*0fda0f12SGeorge Liu get)([](const crow::Request&, 11557e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 11568d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 11577e860f15SJohn Edward Broadbent {"@odata.id", 11587e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc/Truststore/Certificates/"}, 1159*0fda0f12SGeorge Liu {"@odata.type", "#CertificateCollection.CertificateCollection"}, 1160cfcd5f6bSMarri Devender Rao {"Name", "TrustStore Certificates Collection"}, 1161cfcd5f6bSMarri Devender Rao {"Description", 1162cfcd5f6bSMarri Devender Rao "A Collection of TrustStore certificate instances"}}; 11638d1b46d7Szhanghch05 1164cfcd5f6bSMarri Devender Rao crow::connections::systemBus->async_method_call( 1165cfcd5f6bSMarri Devender Rao [asyncResp](const boost::system::error_code ec, 1166cfcd5f6bSMarri Devender Rao const ManagedObjectType& certs) { 1167cfcd5f6bSMarri Devender Rao if (ec) 1168cfcd5f6bSMarri Devender Rao { 1169cfcd5f6bSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 1170cfcd5f6bSMarri Devender Rao messages::internalError(asyncResp->res); 1171cfcd5f6bSMarri Devender Rao return; 1172cfcd5f6bSMarri Devender Rao } 11737e860f15SJohn Edward Broadbent nlohmann::json& members = 11747e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Members"]; 1175cfcd5f6bSMarri Devender Rao members = nlohmann::json::array(); 1176cfcd5f6bSMarri Devender Rao for (const auto& cert : certs) 1177cfcd5f6bSMarri Devender Rao { 1178cfcd5f6bSMarri Devender Rao long id = getIDFromURL(cert.first.str); 1179cfcd5f6bSMarri Devender Rao if (id >= 0) 1180cfcd5f6bSMarri Devender Rao { 1181cfcd5f6bSMarri Devender Rao members.push_back( 1182*0fda0f12SGeorge Liu {{"@odata.id", 1183*0fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/Truststore/Certificates/" + 1184cfcd5f6bSMarri Devender Rao std::to_string(id)}}); 1185cfcd5f6bSMarri Devender Rao } 1186cfcd5f6bSMarri Devender Rao } 1187cfcd5f6bSMarri Devender Rao asyncResp->res.jsonValue["Members@odata.count"] = 1188cfcd5f6bSMarri Devender Rao members.size(); 1189cfcd5f6bSMarri Devender Rao }, 1190cfcd5f6bSMarri Devender Rao certs::authorityServiceName, certs::authorityObjectPath, 1191cfcd5f6bSMarri Devender Rao certs::dbusObjManagerIntf, "GetManagedObjects"); 11927e860f15SJohn Edward Broadbent }); 1193cfcd5f6bSMarri Devender Rao 11947e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/") 1195ed398213SEd Tanous .privileges(redfish::privileges::postCertificateCollection) 1196*0fda0f12SGeorge Liu .methods( 1197*0fda0f12SGeorge Liu boost::beast::http::verb:: 1198*0fda0f12SGeorge Liu post)([](const crow::Request& req, 11997e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 12007e860f15SJohn Edward Broadbent std::string certFileBody = 12017e860f15SJohn Edward Broadbent getCertificateFromReqBody(asyncResp, req); 1202a08752f5SZbigniew Kurzynski 1203a08752f5SZbigniew Kurzynski if (certFileBody.empty()) 1204a08752f5SZbigniew Kurzynski { 1205*0fda0f12SGeorge Liu BMCWEB_LOG_ERROR << "Cannot get certificate from request body."; 1206a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 1207a08752f5SZbigniew Kurzynski return; 1208a08752f5SZbigniew Kurzynski } 1209a08752f5SZbigniew Kurzynski 1210a08752f5SZbigniew Kurzynski std::shared_ptr<CertificateFile> certFile = 1211a08752f5SZbigniew Kurzynski std::make_shared<CertificateFile>(certFileBody); 1212cfcd5f6bSMarri Devender Rao crow::connections::systemBus->async_method_call( 1213656ec7e3SZbigniew Kurzynski [asyncResp, certFile](const boost::system::error_code ec, 1214656ec7e3SZbigniew Kurzynski const std::string& objectPath) { 1215cfcd5f6bSMarri Devender Rao if (ec) 1216cfcd5f6bSMarri Devender Rao { 1217cfcd5f6bSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 1218cfcd5f6bSMarri Devender Rao messages::internalError(asyncResp->res); 1219cfcd5f6bSMarri Devender Rao return; 1220cfcd5f6bSMarri Devender Rao } 1221656ec7e3SZbigniew Kurzynski long certId = getIDFromURL(objectPath); 1222656ec7e3SZbigniew Kurzynski if (certId < 0) 1223656ec7e3SZbigniew Kurzynski { 1224656ec7e3SZbigniew Kurzynski BMCWEB_LOG_ERROR << "Invalid objectPath value" 1225656ec7e3SZbigniew Kurzynski << objectPath; 1226656ec7e3SZbigniew Kurzynski messages::internalError(asyncResp->res); 1227656ec7e3SZbigniew Kurzynski return; 1228656ec7e3SZbigniew Kurzynski } 1229*0fda0f12SGeorge Liu std::string certURL = 1230*0fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/Truststore/Certificates/" + 1231cfcd5f6bSMarri Devender Rao std::to_string(certId); 1232656ec7e3SZbigniew Kurzynski 12337e860f15SJohn Edward Broadbent getCertificateProperties( 12347e860f15SJohn Edward Broadbent asyncResp, objectPath, certs::authorityServiceName, 12357e860f15SJohn Edward Broadbent certId, certURL, "TrustStore Certificate"); 1236*0fda0f12SGeorge Liu BMCWEB_LOG_DEBUG << "TrustStore certificate install file=" 1237cfcd5f6bSMarri Devender Rao << certFile->getCertFilePath(); 1238cfcd5f6bSMarri Devender Rao }, 1239cfcd5f6bSMarri Devender Rao certs::authorityServiceName, certs::authorityObjectPath, 1240*0fda0f12SGeorge Liu certs::certInstallIntf, "Install", certFile->getCertFilePath()); 12417e860f15SJohn Edward Broadbent }); 12427e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificateCollection 1243cfcd5f6bSMarri Devender Rao 1244cfcd5f6bSMarri Devender Rao /** 1245cfcd5f6bSMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 1246cfcd5f6bSMarri Devender Rao * of a component, account or service. 1247cfcd5f6bSMarri Devender Rao */ 12487e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificate(App& app) 1249cfcd5f6bSMarri Devender Rao { 12507e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/") 1251ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 12527e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 12537e860f15SJohn Edward Broadbent [](const crow::Request& req, 12547e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 12557e860f15SJohn Edward Broadbent const std::string&) { 1256cfcd5f6bSMarri Devender Rao long id = getIDFromURL(req.url); 1257cfcd5f6bSMarri Devender Rao if (id < 0) 1258cfcd5f6bSMarri Devender Rao { 1259cfcd5f6bSMarri Devender Rao BMCWEB_LOG_ERROR << "Invalid url value" << req.url; 1260cfcd5f6bSMarri Devender Rao messages::internalError(asyncResp->res); 1261cfcd5f6bSMarri Devender Rao return; 1262cfcd5f6bSMarri Devender Rao } 1263cfcd5f6bSMarri Devender Rao BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doGet ID=" 1264cfcd5f6bSMarri Devender Rao << std::to_string(id); 1265cfcd5f6bSMarri Devender Rao std::string certURL = 1266cfcd5f6bSMarri Devender Rao "/redfish/v1/Managers/bmc/Truststore/Certificates/" + 1267cfcd5f6bSMarri Devender Rao std::to_string(id); 1268cfcd5f6bSMarri Devender Rao std::string objectPath = certs::authorityObjectPath; 1269cfcd5f6bSMarri Devender Rao objectPath += "/"; 1270cfcd5f6bSMarri Devender Rao objectPath += std::to_string(id); 1271cfcd5f6bSMarri Devender Rao getCertificateProperties(asyncResp, objectPath, 12727e860f15SJohn Edward Broadbent certs::authorityServiceName, id, 12737e860f15SJohn Edward Broadbent certURL, "TrustStore Certificate"); 12747e860f15SJohn Edward Broadbent }); 127507a60299SZbigniew Kurzynski 12767e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/") 1277ed398213SEd Tanous .privileges(redfish::privileges::deleteCertificate) 12787e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::delete_)( 12797e860f15SJohn Edward Broadbent [](const crow::Request& req, 12807e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 12817e860f15SJohn Edward Broadbent const std::string& param) { 12827e860f15SJohn Edward Broadbent if (param.empty()) 128307a60299SZbigniew Kurzynski { 128407a60299SZbigniew Kurzynski messages::internalError(asyncResp->res); 128507a60299SZbigniew Kurzynski return; 128607a60299SZbigniew Kurzynski } 128707a60299SZbigniew Kurzynski 128807a60299SZbigniew Kurzynski long id = getIDFromURL(req.url); 128907a60299SZbigniew Kurzynski if (id < 0) 129007a60299SZbigniew Kurzynski { 129107a60299SZbigniew Kurzynski BMCWEB_LOG_ERROR << "Invalid url value: " << req.url; 12927e860f15SJohn Edward Broadbent messages::resourceNotFound(asyncResp->res, 12937e860f15SJohn Edward Broadbent "TrustStore Certificate", 129407a60299SZbigniew Kurzynski std::string(req.url)); 129507a60299SZbigniew Kurzynski return; 129607a60299SZbigniew Kurzynski } 129707a60299SZbigniew Kurzynski BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doDelete ID=" 129807a60299SZbigniew Kurzynski << std::to_string(id); 129907a60299SZbigniew Kurzynski std::string certPath = certs::authorityObjectPath; 130007a60299SZbigniew Kurzynski certPath += "/"; 130107a60299SZbigniew Kurzynski certPath += std::to_string(id); 130207a60299SZbigniew Kurzynski 130307a60299SZbigniew Kurzynski crow::connections::systemBus->async_method_call( 130407a60299SZbigniew Kurzynski [asyncResp, id](const boost::system::error_code ec) { 130507a60299SZbigniew Kurzynski if (ec) 130607a60299SZbigniew Kurzynski { 130707a60299SZbigniew Kurzynski messages::resourceNotFound(asyncResp->res, 130807a60299SZbigniew Kurzynski "TrustStore Certificate", 130907a60299SZbigniew Kurzynski std::to_string(id)); 131007a60299SZbigniew Kurzynski return; 131107a60299SZbigniew Kurzynski } 131207a60299SZbigniew Kurzynski BMCWEB_LOG_INFO << "Certificate deleted"; 13137e860f15SJohn Edward Broadbent asyncResp->res.result( 13147e860f15SJohn Edward Broadbent boost::beast::http::status::no_content); 131507a60299SZbigniew Kurzynski }, 131607a60299SZbigniew Kurzynski certs::authorityServiceName, certPath, certs::objDeleteIntf, 131707a60299SZbigniew Kurzynski "Delete"); 13187e860f15SJohn Edward Broadbent }); 13197e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificate 13205968caeeSMarri Devender Rao } // namespace redfish 1321