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> 6168e20c1SEd Tanous #include <dbus_utility.hpp> 7ed398213SEd Tanous #include <registries/privilege_registry.hpp> 81214b7e7SGunnar Mills 95968caeeSMarri Devender Rao namespace redfish 105968caeeSMarri Devender Rao { 115968caeeSMarri Devender Rao namespace certs 125968caeeSMarri Devender Rao { 135968caeeSMarri Devender Rao constexpr char const* httpsObjectPath = 145968caeeSMarri Devender Rao "/xyz/openbmc_project/certs/server/https"; 155968caeeSMarri Devender Rao constexpr char const* certInstallIntf = "xyz.openbmc_project.Certs.Install"; 165968caeeSMarri Devender Rao constexpr char const* certReplaceIntf = "xyz.openbmc_project.Certs.Replace"; 1707a60299SZbigniew Kurzynski constexpr char const* objDeleteIntf = "xyz.openbmc_project.Object.Delete"; 185968caeeSMarri Devender Rao constexpr char const* certPropIntf = "xyz.openbmc_project.Certs.Certificate"; 195968caeeSMarri Devender Rao constexpr char const* dbusPropIntf = "org.freedesktop.DBus.Properties"; 205968caeeSMarri Devender Rao constexpr char const* dbusObjManagerIntf = "org.freedesktop.DBus.ObjectManager"; 2137cce918SMarri Devender Rao constexpr char const* ldapObjectPath = "/xyz/openbmc_project/certs/client/ldap"; 2237cce918SMarri Devender Rao constexpr char const* httpsServiceName = 2337cce918SMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Server.Https"; 2437cce918SMarri Devender Rao constexpr char const* ldapServiceName = 2537cce918SMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Client.Ldap"; 26cfcd5f6bSMarri Devender Rao constexpr char const* authorityServiceName = 27cfcd5f6bSMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Authority.Ldap"; 28cfcd5f6bSMarri Devender Rao constexpr char const* authorityObjectPath = 29cfcd5f6bSMarri Devender Rao "/xyz/openbmc_project/certs/authority/ldap"; 305968caeeSMarri Devender Rao } // namespace certs 315968caeeSMarri Devender Rao 325968caeeSMarri Devender Rao /** 335968caeeSMarri Devender Rao * The Certificate schema defines a Certificate Service which represents the 345968caeeSMarri Devender Rao * actions available to manage certificates and links to where certificates 355968caeeSMarri Devender Rao * are installed. 365968caeeSMarri Devender Rao */ 377e860f15SJohn Edward Broadbent 385968caeeSMarri Devender Rao // TODO: Issue#61 No entries are available for Certificate 394e0453b1SGunnar Mills // service at https://www.dmtf.org/standards/redfish 405968caeeSMarri Devender Rao // "redfish standard registries". Need to modify after DMTF 415968caeeSMarri Devender Rao // publish Privilege details for certificate service 425968caeeSMarri Devender Rao 437e860f15SJohn Edward Broadbent inline void requestRoutesCertificateService(App& app) 445968caeeSMarri Devender Rao { 457e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/") 46ed398213SEd Tanous .privileges(redfish::privileges::getCertificateService) 4772048780SAbhishek Patel .methods( 4872048780SAbhishek Patel boost::beast::http::verb:: 4972048780SAbhishek Patel get)([](const crow::Request& req, 507e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 518d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 527e860f15SJohn Edward Broadbent {"@odata.type", 537e860f15SJohn Edward Broadbent "#CertificateService.v1_0_0.CertificateService"}, 545968caeeSMarri Devender Rao {"@odata.id", "/redfish/v1/CertificateService"}, 555968caeeSMarri Devender Rao {"Id", "CertificateService"}, 565968caeeSMarri Devender Rao {"Name", "Certificate Service"}, 5772048780SAbhishek Patel {"Description", "Actions available to manage certificates"}}; 5872048780SAbhishek Patel // /redfish/v1/CertificateService/CertificateLocations is something 5972048780SAbhishek Patel // only ConfigureManager can access then only display when the user 6072048780SAbhishek Patel // has permissions ConfigureManager 6172048780SAbhishek Patel Privileges effectiveUserPrivileges = 6272048780SAbhishek Patel redfish::getUserPrivileges(req.userRole); 6372048780SAbhishek Patel if (isOperationAllowedWithPrivileges({{"ConfigureManager"}}, 6472048780SAbhishek Patel effectiveUserPrivileges)) 6572048780SAbhishek Patel { 668d1b46d7Szhanghch05 asyncResp->res.jsonValue["CertificateLocations"] = { 675968caeeSMarri Devender Rao {"@odata.id", 685968caeeSMarri Devender Rao "/redfish/v1/CertificateService/CertificateLocations"}}; 6972048780SAbhishek Patel } 700fda0f12SGeorge Liu asyncResp->res 710fda0f12SGeorge Liu .jsonValue["Actions"] 720fda0f12SGeorge Liu ["#CertificateService.ReplaceCertificate"] = { 730fda0f12SGeorge Liu {"target", 740fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate"}, 755968caeeSMarri Devender Rao {"CertificateType@Redfish.AllowableValues", {"PEM"}}}; 767e860f15SJohn Edward Broadbent asyncResp->res 777e860f15SJohn Edward Broadbent .jsonValue["Actions"]["#CertificateService.GenerateCSR"] = { 780fda0f12SGeorge Liu {"target", 790fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR"}}; 807e860f15SJohn Edward Broadbent }); 817e860f15SJohn Edward Broadbent } // requestRoutesCertificateService 8237cce918SMarri Devender Rao 835968caeeSMarri Devender Rao /** 845968caeeSMarri Devender Rao * @brief Find the ID specified in the URL 855968caeeSMarri Devender Rao * Finds the numbers specified after the last "/" in the URL and returns. 865968caeeSMarri Devender Rao * @param[in] path URL 875968caeeSMarri Devender Rao * @return -1 on failure and number on success 885968caeeSMarri Devender Rao */ 8923a21a1cSEd Tanous inline long getIDFromURL(const std::string_view url) 905968caeeSMarri Devender Rao { 91f23b7296SEd Tanous std::size_t found = url.rfind('/'); 925968caeeSMarri Devender Rao if (found == std::string::npos) 935968caeeSMarri Devender Rao { 945968caeeSMarri Devender Rao return -1; 955968caeeSMarri Devender Rao } 96e6604b11SIwona Klimaszewska 975968caeeSMarri Devender Rao if ((found + 1) < url.length()) 985968caeeSMarri Devender Rao { 995968caeeSMarri Devender Rao std::string_view str = url.substr(found + 1); 100e6604b11SIwona Klimaszewska 101e6604b11SIwona Klimaszewska return boost::convert<long>(str, boost::cnv::strtol()).value_or(-1); 1025968caeeSMarri Devender Rao } 103e6604b11SIwona Klimaszewska 1045968caeeSMarri Devender Rao return -1; 1055968caeeSMarri Devender Rao } 1065968caeeSMarri Devender Rao 1078d1b46d7Szhanghch05 inline std::string getCertificateFromReqBody( 1088d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 10958eb238fSKowalski, Kamil const crow::Request& req) 11058eb238fSKowalski, Kamil { 11158eb238fSKowalski, Kamil nlohmann::json reqJson = nlohmann::json::parse(req.body, nullptr, false); 11258eb238fSKowalski, Kamil 11358eb238fSKowalski, Kamil if (reqJson.is_discarded()) 11458eb238fSKowalski, Kamil { 11558eb238fSKowalski, Kamil // We did not receive JSON request, proceed as it is RAW data 11658eb238fSKowalski, Kamil return req.body; 11758eb238fSKowalski, Kamil } 11858eb238fSKowalski, Kamil 11958eb238fSKowalski, Kamil std::string certificate; 12058eb238fSKowalski, Kamil std::optional<std::string> certificateType = "PEM"; 12158eb238fSKowalski, Kamil 12215ed6780SWilly Tu if (!json_util::readJsonPatch(req, asyncResp->res, "CertificateString", 12315ed6780SWilly Tu certificate, "CertificateType", 12415ed6780SWilly Tu certificateType)) 12558eb238fSKowalski, Kamil { 12658eb238fSKowalski, Kamil BMCWEB_LOG_ERROR << "Required parameters are missing"; 12758eb238fSKowalski, Kamil messages::internalError(asyncResp->res); 128abb93cddSEd Tanous return {}; 12958eb238fSKowalski, Kamil } 13058eb238fSKowalski, Kamil 13158eb238fSKowalski, Kamil if (*certificateType != "PEM") 13258eb238fSKowalski, Kamil { 13358eb238fSKowalski, Kamil messages::propertyValueNotInList(asyncResp->res, *certificateType, 13458eb238fSKowalski, Kamil "CertificateType"); 135abb93cddSEd Tanous return {}; 13658eb238fSKowalski, Kamil } 13758eb238fSKowalski, Kamil 13858eb238fSKowalski, Kamil return certificate; 13958eb238fSKowalski, Kamil } 14058eb238fSKowalski, Kamil 1415968caeeSMarri Devender Rao /** 1425968caeeSMarri Devender Rao * Class to create a temporary certificate file for uploading to system 1435968caeeSMarri Devender Rao */ 1445968caeeSMarri Devender Rao class CertificateFile 1455968caeeSMarri Devender Rao { 1465968caeeSMarri Devender Rao public: 1475968caeeSMarri Devender Rao CertificateFile() = delete; 1485968caeeSMarri Devender Rao CertificateFile(const CertificateFile&) = delete; 1495968caeeSMarri Devender Rao CertificateFile& operator=(const CertificateFile&) = delete; 1505968caeeSMarri Devender Rao CertificateFile(CertificateFile&&) = delete; 1515968caeeSMarri Devender Rao CertificateFile& operator=(CertificateFile&&) = delete; 1525968caeeSMarri Devender Rao CertificateFile(const std::string& certString) 1535968caeeSMarri Devender Rao { 15472d52d25SEd Tanous std::array<char, 18> dirTemplate = {'/', 't', 'm', 'p', '/', 'C', 1555207438cSEd Tanous 'e', 'r', 't', 's', '.', 'X', 1565207438cSEd Tanous 'X', 'X', 'X', 'X', 'X', '\0'}; 1575207438cSEd Tanous char* tempDirectory = mkdtemp(dirTemplate.data()); 158e662eae8SEd Tanous if (tempDirectory != nullptr) 1595968caeeSMarri Devender Rao { 1605968caeeSMarri Devender Rao certDirectory = tempDirectory; 1615968caeeSMarri Devender Rao certificateFile = certDirectory / "cert.pem"; 1625968caeeSMarri Devender Rao std::ofstream out(certificateFile, std::ofstream::out | 1635968caeeSMarri Devender Rao std::ofstream::binary | 1645968caeeSMarri Devender Rao std::ofstream::trunc); 1655968caeeSMarri Devender Rao out << certString; 1665968caeeSMarri Devender Rao out.close(); 167*8cc8edecSEd Tanous BMCWEB_LOG_DEBUG << "Creating certificate file" 168*8cc8edecSEd Tanous << certificateFile.string(); 1695968caeeSMarri Devender Rao } 1705968caeeSMarri Devender Rao } 1715968caeeSMarri Devender Rao ~CertificateFile() 1725968caeeSMarri Devender Rao { 1735968caeeSMarri Devender Rao if (std::filesystem::exists(certDirectory)) 1745968caeeSMarri Devender Rao { 175*8cc8edecSEd Tanous BMCWEB_LOG_DEBUG << "Removing certificate file" 176*8cc8edecSEd Tanous << certificateFile.string(); 17723a21a1cSEd Tanous std::error_code ec; 17823a21a1cSEd Tanous std::filesystem::remove_all(certDirectory, ec); 17923a21a1cSEd Tanous if (ec) 1805968caeeSMarri Devender Rao { 1815968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Failed to remove temp directory" 182*8cc8edecSEd Tanous << certDirectory.string(); 1835968caeeSMarri Devender Rao } 1845968caeeSMarri Devender Rao } 1855968caeeSMarri Devender Rao } 1865968caeeSMarri Devender Rao std::string getCertFilePath() 1875968caeeSMarri Devender Rao { 1885968caeeSMarri Devender Rao return certificateFile; 1895968caeeSMarri Devender Rao } 1905968caeeSMarri Devender Rao 1915968caeeSMarri Devender Rao private: 1925968caeeSMarri Devender Rao std::filesystem::path certificateFile; 1935968caeeSMarri Devender Rao std::filesystem::path certDirectory; 1945968caeeSMarri Devender Rao }; 1955968caeeSMarri Devender Rao 19630215816SMarri Devender Rao static std::unique_ptr<sdbusplus::bus::match::match> csrMatcher; 19730215816SMarri Devender Rao /** 19830215816SMarri Devender Rao * @brief Read data from CSR D-bus object and set to response 19930215816SMarri Devender Rao * 20030215816SMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 20130215816SMarri Devender Rao * @param[in] certURI Link to certifiate collection URI 20230215816SMarri Devender Rao * @param[in] service D-Bus service name 20330215816SMarri Devender Rao * @param[in] certObjPath certificate D-Bus object path 20430215816SMarri Devender Rao * @param[in] csrObjPath CSR D-Bus object path 20530215816SMarri Devender Rao * @return None 20630215816SMarri Devender Rao */ 2078d1b46d7Szhanghch05 static void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 20830215816SMarri Devender Rao const std::string& certURI, const std::string& service, 20930215816SMarri Devender Rao const std::string& certObjPath, 21030215816SMarri Devender Rao const std::string& csrObjPath) 21130215816SMarri Devender Rao { 21230215816SMarri Devender Rao BMCWEB_LOG_DEBUG << "getCSR CertObjectPath" << certObjPath 21330215816SMarri Devender Rao << " CSRObjectPath=" << csrObjPath 21430215816SMarri Devender Rao << " service=" << service; 21530215816SMarri Devender Rao crow::connections::systemBus->async_method_call( 21630215816SMarri Devender Rao [asyncResp, certURI](const boost::system::error_code ec, 21730215816SMarri Devender Rao const std::string& csr) { 21830215816SMarri Devender Rao if (ec) 21930215816SMarri Devender Rao { 22030215816SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 22130215816SMarri Devender Rao messages::internalError(asyncResp->res); 22230215816SMarri Devender Rao return; 22330215816SMarri Devender Rao } 22430215816SMarri Devender Rao if (csr.empty()) 22530215816SMarri Devender Rao { 22630215816SMarri Devender Rao BMCWEB_LOG_ERROR << "CSR read is empty"; 22730215816SMarri Devender Rao messages::internalError(asyncResp->res); 22830215816SMarri Devender Rao return; 22930215816SMarri Devender Rao } 23030215816SMarri Devender Rao asyncResp->res.jsonValue["CSRString"] = csr; 23130215816SMarri Devender Rao asyncResp->res.jsonValue["CertificateCollection"] = { 23230215816SMarri Devender Rao {"@odata.id", certURI}}; 23330215816SMarri Devender Rao }, 23430215816SMarri Devender Rao service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR"); 23530215816SMarri Devender Rao } 23630215816SMarri Devender Rao 23730215816SMarri Devender Rao /** 23830215816SMarri Devender Rao * Action to Generate CSR 23930215816SMarri Devender Rao */ 2407e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionGenerateCSR(App& app) 24130215816SMarri Devender Rao { 2420fda0f12SGeorge Liu BMCWEB_ROUTE( 2430fda0f12SGeorge Liu app, 2440fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR/") 245ed398213SEd Tanous // Incorrect Privilege; Should be ConfigureManager 246ed398213SEd Tanous //.privileges(redfish::privileges::postCertificateService) 247432a890cSEd Tanous .privileges({{"ConfigureComponents"}}) 2480fda0f12SGeorge Liu .methods( 2490fda0f12SGeorge Liu boost::beast::http::verb:: 2500fda0f12SGeorge Liu post)([](const crow::Request& req, 2517e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 2522c70f800SEd Tanous static const int rsaKeyBitLength = 2048; 2538d1b46d7Szhanghch05 25430215816SMarri Devender Rao // Required parameters 25530215816SMarri Devender Rao std::string city; 25630215816SMarri Devender Rao std::string commonName; 25730215816SMarri Devender Rao std::string country; 25830215816SMarri Devender Rao std::string organization; 25930215816SMarri Devender Rao std::string organizationalUnit; 26030215816SMarri Devender Rao std::string state; 26130215816SMarri Devender Rao nlohmann::json certificateCollection; 26230215816SMarri Devender Rao 26330215816SMarri Devender Rao // Optional parameters 26430215816SMarri Devender Rao std::optional<std::vector<std::string>> optAlternativeNames = 26530215816SMarri Devender Rao std::vector<std::string>(); 26630215816SMarri Devender Rao std::optional<std::string> optContactPerson = ""; 26730215816SMarri Devender Rao std::optional<std::string> optChallengePassword = ""; 26830215816SMarri Devender Rao std::optional<std::string> optEmail = ""; 26930215816SMarri Devender Rao std::optional<std::string> optGivenName = ""; 27030215816SMarri Devender Rao std::optional<std::string> optInitials = ""; 2712c70f800SEd Tanous std::optional<int64_t> optKeyBitLength = rsaKeyBitLength; 272aaf3206fSVernon Mauery std::optional<std::string> optKeyCurveId = "secp384r1"; 27330215816SMarri Devender Rao std::optional<std::string> optKeyPairAlgorithm = "EC"; 27430215816SMarri Devender Rao std::optional<std::vector<std::string>> optKeyUsage = 27530215816SMarri Devender Rao std::vector<std::string>(); 27630215816SMarri Devender Rao std::optional<std::string> optSurname = ""; 27730215816SMarri Devender Rao std::optional<std::string> optUnstructuredName = ""; 27815ed6780SWilly Tu if (!json_util::readJsonAction( 2790fda0f12SGeorge Liu req, asyncResp->res, "City", city, "CommonName", commonName, 2800fda0f12SGeorge Liu "ContactPerson", optContactPerson, "Country", country, 2810fda0f12SGeorge Liu "Organization", organization, "OrganizationalUnit", 2820fda0f12SGeorge Liu organizationalUnit, "State", state, "CertificateCollection", 2830fda0f12SGeorge Liu certificateCollection, "AlternativeNames", 2840fda0f12SGeorge Liu optAlternativeNames, "ChallengePassword", 2850fda0f12SGeorge Liu optChallengePassword, "Email", optEmail, "GivenName", 2860fda0f12SGeorge Liu optGivenName, "Initials", optInitials, "KeyBitLength", 2870fda0f12SGeorge Liu optKeyBitLength, "KeyCurveId", optKeyCurveId, 2880fda0f12SGeorge Liu "KeyPairAlgorithm", optKeyPairAlgorithm, "KeyUsage", 2890fda0f12SGeorge Liu optKeyUsage, "Surname", optSurname, "UnstructuredName", 2900fda0f12SGeorge Liu optUnstructuredName)) 29130215816SMarri Devender Rao { 29230215816SMarri Devender Rao return; 29330215816SMarri Devender Rao } 29430215816SMarri Devender Rao 29530215816SMarri Devender Rao // bmcweb has no way to store or decode a private key challenge 2967e860f15SJohn Edward Broadbent // password, which will likely cause bmcweb to crash on startup 2977e860f15SJohn Edward Broadbent // if this is not set on a post so not allowing the user to set 2987e860f15SJohn Edward Broadbent // value 29926f6976fSEd Tanous if (!optChallengePassword->empty()) 30030215816SMarri Devender Rao { 3017e860f15SJohn Edward Broadbent messages::actionParameterNotSupported( 3027e860f15SJohn Edward Broadbent asyncResp->res, "GenerateCSR", "ChallengePassword"); 30330215816SMarri Devender Rao return; 30430215816SMarri Devender Rao } 30530215816SMarri Devender Rao 30630215816SMarri Devender Rao std::string certURI; 3077e860f15SJohn Edward Broadbent if (!redfish::json_util::readJson(certificateCollection, 3087e860f15SJohn Edward Broadbent asyncResp->res, "@odata.id", 3097e860f15SJohn Edward Broadbent certURI)) 31030215816SMarri Devender Rao { 31130215816SMarri Devender Rao return; 31230215816SMarri Devender Rao } 31330215816SMarri Devender Rao 31430215816SMarri Devender Rao std::string objectPath; 31530215816SMarri Devender Rao std::string service; 3160fda0f12SGeorge Liu if (boost::starts_with( 3170fda0f12SGeorge Liu certURI, 3180fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) 31930215816SMarri Devender Rao { 32030215816SMarri Devender Rao objectPath = certs::httpsObjectPath; 32130215816SMarri Devender Rao service = certs::httpsServiceName; 32230215816SMarri Devender Rao } 3233b7f0149SMarri Devender Rao else if (boost::starts_with( 3247e860f15SJohn Edward Broadbent certURI, 3257e860f15SJohn Edward Broadbent "/redfish/v1/AccountService/LDAP/Certificates")) 3263b7f0149SMarri Devender Rao { 3273b7f0149SMarri Devender Rao objectPath = certs::ldapObjectPath; 3283b7f0149SMarri Devender Rao service = certs::ldapServiceName; 3293b7f0149SMarri Devender Rao } 33030215816SMarri Devender Rao else 33130215816SMarri Devender Rao { 33230215816SMarri Devender Rao messages::actionParameterNotSupported( 33330215816SMarri Devender Rao asyncResp->res, "CertificateCollection", "GenerateCSR"); 33430215816SMarri Devender Rao return; 33530215816SMarri Devender Rao } 33630215816SMarri Devender Rao 33730215816SMarri Devender Rao // supporting only EC and RSA algorithm 3380fda0f12SGeorge Liu if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA") 33930215816SMarri Devender Rao { 34030215816SMarri Devender Rao messages::actionParameterNotSupported( 34130215816SMarri Devender Rao asyncResp->res, "KeyPairAlgorithm", "GenerateCSR"); 34230215816SMarri Devender Rao return; 34330215816SMarri Devender Rao } 34430215816SMarri Devender Rao 3457e860f15SJohn Edward Broadbent // supporting only 2048 key bit length for RSA algorithm due to 3467e860f15SJohn Edward Broadbent // time consumed in generating private key 34730215816SMarri Devender Rao if (*optKeyPairAlgorithm == "RSA" && 3482c70f800SEd Tanous *optKeyBitLength != rsaKeyBitLength) 34930215816SMarri Devender Rao { 3507e860f15SJohn Edward Broadbent messages::propertyValueNotInList( 3517e860f15SJohn Edward Broadbent asyncResp->res, std::to_string(*optKeyBitLength), 35230215816SMarri Devender Rao "KeyBitLength"); 35330215816SMarri Devender Rao return; 35430215816SMarri Devender Rao } 35530215816SMarri Devender Rao 35630215816SMarri Devender Rao // validate KeyUsage supporting only 1 type based on URL 3570fda0f12SGeorge Liu if (boost::starts_with( 3580fda0f12SGeorge Liu certURI, 3590fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) 36030215816SMarri Devender Rao { 36126f6976fSEd Tanous if (optKeyUsage->empty()) 36230215816SMarri Devender Rao { 36330215816SMarri Devender Rao optKeyUsage->push_back("ServerAuthentication"); 36430215816SMarri Devender Rao } 36530215816SMarri Devender Rao else if (optKeyUsage->size() == 1) 36630215816SMarri Devender Rao { 36730215816SMarri Devender Rao if ((*optKeyUsage)[0] != "ServerAuthentication") 36830215816SMarri Devender Rao { 36930215816SMarri Devender Rao messages::propertyValueNotInList( 37030215816SMarri Devender Rao asyncResp->res, (*optKeyUsage)[0], "KeyUsage"); 37130215816SMarri Devender Rao return; 37230215816SMarri Devender Rao } 37330215816SMarri Devender Rao } 37430215816SMarri Devender Rao else 37530215816SMarri Devender Rao { 37630215816SMarri Devender Rao messages::actionParameterNotSupported( 37730215816SMarri Devender Rao asyncResp->res, "KeyUsage", "GenerateCSR"); 37830215816SMarri Devender Rao return; 37930215816SMarri Devender Rao } 38030215816SMarri Devender Rao } 3813b7f0149SMarri Devender Rao else if (boost::starts_with( 3827e860f15SJohn Edward Broadbent certURI, 3837e860f15SJohn Edward Broadbent "/redfish/v1/AccountService/LDAP/Certificates")) 3843b7f0149SMarri Devender Rao { 38526f6976fSEd Tanous if (optKeyUsage->empty()) 3863b7f0149SMarri Devender Rao { 3873b7f0149SMarri Devender Rao optKeyUsage->push_back("ClientAuthentication"); 3883b7f0149SMarri Devender Rao } 3893b7f0149SMarri Devender Rao else if (optKeyUsage->size() == 1) 3903b7f0149SMarri Devender Rao { 3913b7f0149SMarri Devender Rao if ((*optKeyUsage)[0] != "ClientAuthentication") 3923b7f0149SMarri Devender Rao { 3933b7f0149SMarri Devender Rao messages::propertyValueNotInList( 3943b7f0149SMarri Devender Rao asyncResp->res, (*optKeyUsage)[0], "KeyUsage"); 3953b7f0149SMarri Devender Rao return; 3963b7f0149SMarri Devender Rao } 3973b7f0149SMarri Devender Rao } 3983b7f0149SMarri Devender Rao else 3993b7f0149SMarri Devender Rao { 4003b7f0149SMarri Devender Rao messages::actionParameterNotSupported( 4013b7f0149SMarri Devender Rao asyncResp->res, "KeyUsage", "GenerateCSR"); 4023b7f0149SMarri Devender Rao return; 4033b7f0149SMarri Devender Rao } 4043b7f0149SMarri Devender Rao } 40530215816SMarri Devender Rao 4067e860f15SJohn Edward Broadbent // Only allow one CSR matcher at a time so setting retry 4077e860f15SJohn Edward Broadbent // time-out and timer expiry to 10 seconds for now. 4082c70f800SEd Tanous static const int timeOut = 10; 40930215816SMarri Devender Rao if (csrMatcher) 41030215816SMarri Devender Rao { 4117e860f15SJohn Edward Broadbent messages::serviceTemporarilyUnavailable( 4127e860f15SJohn Edward Broadbent asyncResp->res, std::to_string(timeOut)); 41330215816SMarri Devender Rao return; 41430215816SMarri Devender Rao } 41530215816SMarri Devender Rao 41630215816SMarri Devender Rao // Make this static so it survives outside this method 41730215816SMarri Devender Rao static boost::asio::steady_timer timeout(*req.ioService); 4182c70f800SEd Tanous timeout.expires_after(std::chrono::seconds(timeOut)); 4190fda0f12SGeorge Liu timeout.async_wait( 4200fda0f12SGeorge Liu [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 } 45530215816SMarri Devender Rao std::vector<std::pair< 456168e20c1SEd Tanous std::string, 457168e20c1SEd Tanous std::vector<std::pair<std::string, 458168e20c1SEd Tanous dbus::utility::DbusVariantType>>>> 45930215816SMarri Devender Rao interfacesProperties; 46030215816SMarri Devender Rao sdbusplus::message::object_path csrObjectPath; 46130215816SMarri Devender Rao m.read(csrObjectPath, interfacesProperties); 4620fda0f12SGeorge Liu BMCWEB_LOG_DEBUG << "CSR object added" << csrObjectPath.str; 46330215816SMarri Devender Rao for (auto& interface : interfacesProperties) 46430215816SMarri Devender Rao { 4650fda0f12SGeorge Liu if (interface.first == "xyz.openbmc_project.Certs.CSR") 46630215816SMarri Devender Rao { 46730215816SMarri Devender Rao getCSR(asyncResp, certURI, service, objectPath, 46830215816SMarri Devender Rao csrObjectPath.str); 46930215816SMarri Devender Rao break; 47030215816SMarri Devender Rao } 47130215816SMarri Devender Rao } 47230215816SMarri Devender Rao }); 47330215816SMarri Devender Rao crow::connections::systemBus->async_method_call( 474914e2d5dSEd Tanous [asyncResp](const boost::system::error_code ec, 475cb13a392SEd Tanous const std::string&) { 47630215816SMarri Devender Rao if (ec) 47730215816SMarri Devender Rao { 4787e860f15SJohn Edward Broadbent BMCWEB_LOG_ERROR << "DBUS response error: " 4797e860f15SJohn Edward Broadbent << ec.message(); 48030215816SMarri Devender Rao messages::internalError(asyncResp->res); 48130215816SMarri Devender Rao return; 48230215816SMarri Devender Rao } 48330215816SMarri Devender Rao }, 48430215816SMarri Devender Rao service, objectPath, "xyz.openbmc_project.Certs.CSR.Create", 4857e860f15SJohn Edward Broadbent "GenerateCSR", *optAlternativeNames, *optChallengePassword, 4867e860f15SJohn Edward Broadbent city, commonName, *optContactPerson, country, *optEmail, 4870fda0f12SGeorge Liu *optGivenName, *optInitials, *optKeyBitLength, *optKeyCurveId, 4880fda0f12SGeorge Liu *optKeyPairAlgorithm, *optKeyUsage, organization, 4890fda0f12SGeorge Liu organizationalUnit, state, *optSurname, *optUnstructuredName); 4907e860f15SJohn Edward Broadbent }); 4917e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionGenerateCSR 49230215816SMarri Devender Rao 4935968caeeSMarri Devender Rao /** 4944e0453b1SGunnar Mills * @brief Parse and update Certificate Issue/Subject property 4955968caeeSMarri Devender Rao * 4965968caeeSMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 4975968caeeSMarri Devender Rao * @param[in] str Issuer/Subject value in key=value pairs 4985968caeeSMarri Devender Rao * @param[in] type Issuer/Subject 4995968caeeSMarri Devender Rao * @return None 5005968caeeSMarri Devender Rao */ 5015968caeeSMarri Devender Rao static void updateCertIssuerOrSubject(nlohmann::json& out, 5025968caeeSMarri Devender Rao const std::string_view value) 5035968caeeSMarri Devender Rao { 5045968caeeSMarri Devender Rao // example: O=openbmc-project.xyz,CN=localhost 5055968caeeSMarri Devender Rao std::string_view::iterator i = value.begin(); 5065968caeeSMarri Devender Rao while (i != value.end()) 5075968caeeSMarri Devender Rao { 5085968caeeSMarri Devender Rao std::string_view::iterator tokenBegin = i; 5095968caeeSMarri Devender Rao while (i != value.end() && *i != '=') 5105968caeeSMarri Devender Rao { 51117a897dfSManojkiran Eda ++i; 5125968caeeSMarri Devender Rao } 5135968caeeSMarri Devender Rao if (i == value.end()) 5145968caeeSMarri Devender Rao { 5155968caeeSMarri Devender Rao break; 5165968caeeSMarri Devender Rao } 517271584abSEd Tanous const std::string_view key(tokenBegin, 518271584abSEd Tanous static_cast<size_t>(i - tokenBegin)); 51917a897dfSManojkiran Eda ++i; 5205968caeeSMarri Devender Rao tokenBegin = i; 5215968caeeSMarri Devender Rao while (i != value.end() && *i != ',') 5225968caeeSMarri Devender Rao { 52317a897dfSManojkiran Eda ++i; 5245968caeeSMarri Devender Rao } 525271584abSEd Tanous const std::string_view val(tokenBegin, 526271584abSEd Tanous static_cast<size_t>(i - tokenBegin)); 5275968caeeSMarri Devender Rao if (key == "L") 5285968caeeSMarri Devender Rao { 5295968caeeSMarri Devender Rao out["City"] = val; 5305968caeeSMarri Devender Rao } 5315968caeeSMarri Devender Rao else if (key == "CN") 5325968caeeSMarri Devender Rao { 5335968caeeSMarri Devender Rao out["CommonName"] = val; 5345968caeeSMarri Devender Rao } 5355968caeeSMarri Devender Rao else if (key == "C") 5365968caeeSMarri Devender Rao { 5375968caeeSMarri Devender Rao out["Country"] = val; 5385968caeeSMarri Devender Rao } 5395968caeeSMarri Devender Rao else if (key == "O") 5405968caeeSMarri Devender Rao { 5415968caeeSMarri Devender Rao out["Organization"] = val; 5425968caeeSMarri Devender Rao } 5435968caeeSMarri Devender Rao else if (key == "OU") 5445968caeeSMarri Devender Rao { 5455968caeeSMarri Devender Rao out["OrganizationalUnit"] = val; 5465968caeeSMarri Devender Rao } 5475968caeeSMarri Devender Rao else if (key == "ST") 5485968caeeSMarri Devender Rao { 5495968caeeSMarri Devender Rao out["State"] = val; 5505968caeeSMarri Devender Rao } 5515968caeeSMarri Devender Rao // skip comma character 5525968caeeSMarri Devender Rao if (i != value.end()) 5535968caeeSMarri Devender Rao { 55417a897dfSManojkiran Eda ++i; 5555968caeeSMarri Devender Rao } 5565968caeeSMarri Devender Rao } 5575968caeeSMarri Devender Rao } 5585968caeeSMarri Devender Rao 5595968caeeSMarri Devender Rao /** 5605968caeeSMarri Devender Rao * @brief Retrieve the certificates properties and append to the response 5615968caeeSMarri Devender Rao * message 5625968caeeSMarri Devender Rao * 5635968caeeSMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 5645968caeeSMarri Devender Rao * @param[in] objectPath Path of the D-Bus service object 5655968caeeSMarri Devender Rao * @param[in] certId Id of the certificate 5665968caeeSMarri Devender Rao * @param[in] certURL URL of the certificate object 5675968caeeSMarri Devender Rao * @param[in] name name of the certificate 5685968caeeSMarri Devender Rao * @return None 5695968caeeSMarri Devender Rao */ 5705968caeeSMarri Devender Rao static void getCertificateProperties( 5718d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 5728d1b46d7Szhanghch05 const std::string& objectPath, const std::string& service, long certId, 5738d1b46d7Szhanghch05 const std::string& certURL, const std::string& name) 5745968caeeSMarri Devender Rao { 575168e20c1SEd Tanous using PropertiesMap = 576168e20c1SEd Tanous boost::container::flat_map<std::string, dbus::utility::DbusVariantType>; 5775968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "getCertificateProperties Path=" << objectPath 5785968caeeSMarri Devender Rao << " certId=" << certId << " certURl=" << certURL; 5795968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 58037cce918SMarri Devender Rao [asyncResp, certURL, certId, name](const boost::system::error_code ec, 5815968caeeSMarri Devender Rao const PropertiesMap& properties) { 5825968caeeSMarri Devender Rao if (ec) 5835968caeeSMarri Devender Rao { 5845968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 5858aae75adSMarri Devender Rao messages::resourceNotFound(asyncResp->res, name, 5868aae75adSMarri Devender Rao std::to_string(certId)); 5875968caeeSMarri Devender Rao return; 5885968caeeSMarri Devender Rao } 5895968caeeSMarri Devender Rao asyncResp->res.jsonValue = { 5905968caeeSMarri Devender Rao {"@odata.id", certURL}, 5915968caeeSMarri Devender Rao {"@odata.type", "#Certificate.v1_0_0.Certificate"}, 5925968caeeSMarri Devender Rao {"Id", std::to_string(certId)}, 5935968caeeSMarri Devender Rao {"Name", name}, 5945968caeeSMarri Devender Rao {"Description", name}}; 5955968caeeSMarri Devender Rao for (const auto& property : properties) 5965968caeeSMarri Devender Rao { 5975968caeeSMarri Devender Rao if (property.first == "CertificateString") 5985968caeeSMarri Devender Rao { 5995968caeeSMarri Devender Rao asyncResp->res.jsonValue["CertificateString"] = ""; 6005968caeeSMarri Devender Rao const std::string* value = 6015968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 602e662eae8SEd Tanous if (value != nullptr) 6035968caeeSMarri Devender Rao { 60437cce918SMarri Devender Rao asyncResp->res.jsonValue["CertificateString"] = *value; 6055968caeeSMarri Devender Rao } 6065968caeeSMarri Devender Rao } 6075968caeeSMarri Devender Rao else if (property.first == "KeyUsage") 6085968caeeSMarri Devender Rao { 6095968caeeSMarri Devender Rao nlohmann::json& keyUsage = 6105968caeeSMarri Devender Rao asyncResp->res.jsonValue["KeyUsage"]; 6115968caeeSMarri Devender Rao keyUsage = nlohmann::json::array(); 6125968caeeSMarri Devender Rao const std::vector<std::string>* value = 61337cce918SMarri Devender Rao std::get_if<std::vector<std::string>>(&property.second); 614e662eae8SEd Tanous if (value != nullptr) 6155968caeeSMarri Devender Rao { 6165968caeeSMarri Devender Rao for (const std::string& usage : *value) 6175968caeeSMarri Devender Rao { 6185968caeeSMarri Devender Rao keyUsage.push_back(usage); 6195968caeeSMarri Devender Rao } 6205968caeeSMarri Devender Rao } 6215968caeeSMarri Devender Rao } 6225968caeeSMarri Devender Rao else if (property.first == "Issuer") 6235968caeeSMarri Devender Rao { 6245968caeeSMarri Devender Rao const std::string* value = 6255968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 626e662eae8SEd Tanous if (value != nullptr) 6275968caeeSMarri Devender Rao { 6285968caeeSMarri Devender Rao updateCertIssuerOrSubject( 6295968caeeSMarri Devender Rao asyncResp->res.jsonValue["Issuer"], *value); 6305968caeeSMarri Devender Rao } 6315968caeeSMarri Devender Rao } 6325968caeeSMarri Devender Rao else if (property.first == "Subject") 6335968caeeSMarri Devender Rao { 6345968caeeSMarri Devender Rao const std::string* value = 6355968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 636e662eae8SEd Tanous if (value != nullptr) 6375968caeeSMarri Devender Rao { 6385968caeeSMarri Devender Rao updateCertIssuerOrSubject( 63937cce918SMarri Devender Rao asyncResp->res.jsonValue["Subject"], *value); 6405968caeeSMarri Devender Rao } 6415968caeeSMarri Devender Rao } 6425968caeeSMarri Devender Rao else if (property.first == "ValidNotAfter") 6435968caeeSMarri Devender Rao { 6445968caeeSMarri Devender Rao const uint64_t* value = 6455968caeeSMarri Devender Rao std::get_if<uint64_t>(&property.second); 646e662eae8SEd Tanous if (value != nullptr) 6475968caeeSMarri Devender Rao { 6485968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotAfter"] = 6491d8782e7SNan Zhou crow::utility::getDateTimeUint(*value); 6505968caeeSMarri Devender Rao } 6515968caeeSMarri Devender Rao } 6525968caeeSMarri Devender Rao else if (property.first == "ValidNotBefore") 6535968caeeSMarri Devender Rao { 6545968caeeSMarri Devender Rao const uint64_t* value = 6555968caeeSMarri Devender Rao std::get_if<uint64_t>(&property.second); 656e662eae8SEd Tanous if (value != nullptr) 6575968caeeSMarri Devender Rao { 6585968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotBefore"] = 6591d8782e7SNan Zhou crow::utility::getDateTimeUint(*value); 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 { 6770fda0f12SGeorge Liu BMCWEB_ROUTE( 6780fda0f12SGeorge Liu app, 6790fda0f12SGeorge 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 68915ed6780SWilly Tu if (!json_util::readJsonAction(req, asyncResp->res, 69015ed6780SWilly Tu "CertificateString", certificate, 69115ed6780SWilly Tu "CertificateUri", certificateUri, 69215ed6780SWilly Tu "CertificateType", 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; 7320fda0f12SGeorge Liu if (boost::starts_with( 7330fda0f12SGeorge Liu certURI, 7340fda0f12SGeorge 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, 846711ac7a9SEd Tanous const dbus::utility::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", 8630fda0f12SGeorge 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) 8770fda0f12SGeorge Liu .methods( 8780fda0f12SGeorge Liu boost::beast::http::verb:: 8790fda0f12SGeorge 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 8830fda0f12SGeorge 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 { 8910fda0f12SGeorge 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 = 9170fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" + 9185968caeeSMarri Devender Rao std::to_string(certId); 9190fda0f12SGeorge Liu getCertificateProperties(asyncResp, objectPath, 9200fda0f12SGeorge Liu certs::httpsServiceName, certId, 9210fda0f12SGeorge 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, 9260fda0f12SGeorge 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, 948711ac7a9SEd Tanous const dbus::utility::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"]; 9589eb808c1SEd Tanous for (const 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) 10200fda0f12SGeorge Liu .methods( 10210fda0f12SGeorge Liu boost::beast::http::verb:: 10220fda0f12SGeorge Liu get)([](const crow::Request&, 10237e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 10248d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 10250fda0f12SGeorge Liu {"@odata.id", "/redfish/v1/AccountService/LDAP/Certificates"}, 10260fda0f12SGeorge Liu {"@odata.type", "#CertificateCollection.CertificateCollection"}, 102737cce918SMarri Devender Rao {"Name", "LDAP Certificates Collection"}, 10280fda0f12SGeorge 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, 1032711ac7a9SEd Tanous const dbus::utility::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 { 10410fda0f12SGeorge Liu BMCWEB_LOG_WARNING << "LDAP certificate query failed: " 10420fda0f12SGeorge 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( 10510fda0f12SGeorge Liu {{"@odata.id", 10520fda0f12SGeorge 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) 11520fda0f12SGeorge Liu .methods( 11530fda0f12SGeorge Liu boost::beast::http::verb:: 11540fda0f12SGeorge 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/"}, 11590fda0f12SGeorge 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, 1166711ac7a9SEd Tanous const dbus::utility::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( 11820fda0f12SGeorge Liu {{"@odata.id", 11830fda0f12SGeorge 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) 11960fda0f12SGeorge Liu .methods( 11970fda0f12SGeorge Liu boost::beast::http::verb:: 11980fda0f12SGeorge 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 { 12050fda0f12SGeorge 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 } 12290fda0f12SGeorge Liu std::string certURL = 12300fda0f12SGeorge 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"); 12360fda0f12SGeorge Liu BMCWEB_LOG_DEBUG << "TrustStore certificate install file=" 1237cfcd5f6bSMarri Devender Rao << certFile->getCertFilePath(); 1238cfcd5f6bSMarri Devender Rao }, 1239cfcd5f6bSMarri Devender Rao certs::authorityServiceName, certs::authorityObjectPath, 12400fda0f12SGeorge 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