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> 7*45ca1b86SEd Tanous #include <query.hpp> 8ed398213SEd Tanous #include <registries/privilege_registry.hpp> 91214b7e7SGunnar Mills 105968caeeSMarri Devender Rao namespace redfish 115968caeeSMarri Devender Rao { 125968caeeSMarri Devender Rao namespace certs 135968caeeSMarri Devender Rao { 145968caeeSMarri Devender Rao constexpr char const* httpsObjectPath = 155968caeeSMarri Devender Rao "/xyz/openbmc_project/certs/server/https"; 165968caeeSMarri Devender Rao constexpr char const* certInstallIntf = "xyz.openbmc_project.Certs.Install"; 175968caeeSMarri Devender Rao constexpr char const* certReplaceIntf = "xyz.openbmc_project.Certs.Replace"; 1807a60299SZbigniew Kurzynski constexpr char const* objDeleteIntf = "xyz.openbmc_project.Object.Delete"; 195968caeeSMarri Devender Rao constexpr char const* certPropIntf = "xyz.openbmc_project.Certs.Certificate"; 205968caeeSMarri Devender Rao constexpr char const* dbusPropIntf = "org.freedesktop.DBus.Properties"; 215968caeeSMarri Devender Rao constexpr char const* dbusObjManagerIntf = "org.freedesktop.DBus.ObjectManager"; 2237cce918SMarri Devender Rao constexpr char const* ldapObjectPath = "/xyz/openbmc_project/certs/client/ldap"; 2337cce918SMarri Devender Rao constexpr char const* httpsServiceName = 2437cce918SMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Server.Https"; 2537cce918SMarri Devender Rao constexpr char const* ldapServiceName = 2637cce918SMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Client.Ldap"; 27cfcd5f6bSMarri Devender Rao constexpr char const* authorityServiceName = 28cfcd5f6bSMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Authority.Ldap"; 29cfcd5f6bSMarri Devender Rao constexpr char const* authorityObjectPath = 30cfcd5f6bSMarri Devender Rao "/xyz/openbmc_project/certs/authority/ldap"; 315968caeeSMarri Devender Rao } // namespace certs 325968caeeSMarri Devender Rao 335968caeeSMarri Devender Rao /** 345968caeeSMarri Devender Rao * The Certificate schema defines a Certificate Service which represents the 355968caeeSMarri Devender Rao * actions available to manage certificates and links to where certificates 365968caeeSMarri Devender Rao * are installed. 375968caeeSMarri Devender Rao */ 387e860f15SJohn Edward Broadbent 395968caeeSMarri Devender Rao // TODO: Issue#61 No entries are available for Certificate 404e0453b1SGunnar Mills // service at https://www.dmtf.org/standards/redfish 415968caeeSMarri Devender Rao // "redfish standard registries". Need to modify after DMTF 425968caeeSMarri Devender Rao // publish Privilege details for certificate service 435968caeeSMarri Devender Rao 447e860f15SJohn Edward Broadbent inline void requestRoutesCertificateService(App& app) 455968caeeSMarri Devender Rao { 467e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/") 47ed398213SEd Tanous .privileges(redfish::privileges::getCertificateService) 48*45ca1b86SEd Tanous .methods(boost::beast::http::verb::get)([&app](const crow::Request& req, 49*45ca1b86SEd Tanous const std::shared_ptr< 50*45ca1b86SEd Tanous bmcweb::AsyncResp>& 51*45ca1b86SEd Tanous asyncResp) { 52*45ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 53*45ca1b86SEd Tanous { 54*45ca1b86SEd Tanous return; 55*45ca1b86SEd Tanous } 568d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 577e860f15SJohn Edward Broadbent {"@odata.type", 587e860f15SJohn Edward Broadbent "#CertificateService.v1_0_0.CertificateService"}, 595968caeeSMarri Devender Rao {"@odata.id", "/redfish/v1/CertificateService"}, 605968caeeSMarri Devender Rao {"Id", "CertificateService"}, 615968caeeSMarri Devender Rao {"Name", "Certificate Service"}, 6272048780SAbhishek Patel {"Description", "Actions available to manage certificates"}}; 6372048780SAbhishek Patel // /redfish/v1/CertificateService/CertificateLocations is something 6472048780SAbhishek Patel // only ConfigureManager can access then only display when the user 6572048780SAbhishek Patel // has permissions ConfigureManager 6672048780SAbhishek Patel Privileges effectiveUserPrivileges = 6772048780SAbhishek Patel redfish::getUserPrivileges(req.userRole); 6872048780SAbhishek Patel if (isOperationAllowedWithPrivileges({{"ConfigureManager"}}, 6972048780SAbhishek Patel effectiveUserPrivileges)) 7072048780SAbhishek Patel { 718d1b46d7Szhanghch05 asyncResp->res.jsonValue["CertificateLocations"] = { 725968caeeSMarri Devender Rao {"@odata.id", 735968caeeSMarri Devender Rao "/redfish/v1/CertificateService/CertificateLocations"}}; 7472048780SAbhishek Patel } 750fda0f12SGeorge Liu asyncResp->res 760fda0f12SGeorge Liu .jsonValue["Actions"] 770fda0f12SGeorge Liu ["#CertificateService.ReplaceCertificate"] = { 780fda0f12SGeorge Liu {"target", 790fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate"}, 805968caeeSMarri Devender Rao {"CertificateType@Redfish.AllowableValues", {"PEM"}}}; 817e860f15SJohn Edward Broadbent asyncResp->res 827e860f15SJohn Edward Broadbent .jsonValue["Actions"]["#CertificateService.GenerateCSR"] = { 830fda0f12SGeorge Liu {"target", 840fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR"}}; 857e860f15SJohn Edward Broadbent }); 867e860f15SJohn Edward Broadbent } // requestRoutesCertificateService 8737cce918SMarri Devender Rao 885968caeeSMarri Devender Rao /** 895968caeeSMarri Devender Rao * @brief Find the ID specified in the URL 905968caeeSMarri Devender Rao * Finds the numbers specified after the last "/" in the URL and returns. 915968caeeSMarri Devender Rao * @param[in] path URL 925968caeeSMarri Devender Rao * @return -1 on failure and number on success 935968caeeSMarri Devender Rao */ 9423a21a1cSEd Tanous inline long getIDFromURL(const std::string_view url) 955968caeeSMarri Devender Rao { 96f23b7296SEd Tanous std::size_t found = url.rfind('/'); 975968caeeSMarri Devender Rao if (found == std::string::npos) 985968caeeSMarri Devender Rao { 995968caeeSMarri Devender Rao return -1; 1005968caeeSMarri Devender Rao } 101e6604b11SIwona Klimaszewska 1025968caeeSMarri Devender Rao if ((found + 1) < url.length()) 1035968caeeSMarri Devender Rao { 1045968caeeSMarri Devender Rao std::string_view str = url.substr(found + 1); 105e6604b11SIwona Klimaszewska 106e6604b11SIwona Klimaszewska return boost::convert<long>(str, boost::cnv::strtol()).value_or(-1); 1075968caeeSMarri Devender Rao } 108e6604b11SIwona Klimaszewska 1095968caeeSMarri Devender Rao return -1; 1105968caeeSMarri Devender Rao } 1115968caeeSMarri Devender Rao 1128d1b46d7Szhanghch05 inline std::string getCertificateFromReqBody( 1138d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 11458eb238fSKowalski, Kamil const crow::Request& req) 11558eb238fSKowalski, Kamil { 11658eb238fSKowalski, Kamil nlohmann::json reqJson = nlohmann::json::parse(req.body, nullptr, false); 11758eb238fSKowalski, Kamil 11858eb238fSKowalski, Kamil if (reqJson.is_discarded()) 11958eb238fSKowalski, Kamil { 12058eb238fSKowalski, Kamil // We did not receive JSON request, proceed as it is RAW data 12158eb238fSKowalski, Kamil return req.body; 12258eb238fSKowalski, Kamil } 12358eb238fSKowalski, Kamil 12458eb238fSKowalski, Kamil std::string certificate; 12558eb238fSKowalski, Kamil std::optional<std::string> certificateType = "PEM"; 12658eb238fSKowalski, Kamil 12715ed6780SWilly Tu if (!json_util::readJsonPatch(req, asyncResp->res, "CertificateString", 12815ed6780SWilly Tu certificate, "CertificateType", 12915ed6780SWilly Tu certificateType)) 13058eb238fSKowalski, Kamil { 13158eb238fSKowalski, Kamil BMCWEB_LOG_ERROR << "Required parameters are missing"; 13258eb238fSKowalski, Kamil messages::internalError(asyncResp->res); 133abb93cddSEd Tanous return {}; 13458eb238fSKowalski, Kamil } 13558eb238fSKowalski, Kamil 13658eb238fSKowalski, Kamil if (*certificateType != "PEM") 13758eb238fSKowalski, Kamil { 13858eb238fSKowalski, Kamil messages::propertyValueNotInList(asyncResp->res, *certificateType, 13958eb238fSKowalski, Kamil "CertificateType"); 140abb93cddSEd Tanous return {}; 14158eb238fSKowalski, Kamil } 14258eb238fSKowalski, Kamil 14358eb238fSKowalski, Kamil return certificate; 14458eb238fSKowalski, Kamil } 14558eb238fSKowalski, Kamil 1465968caeeSMarri Devender Rao /** 1475968caeeSMarri Devender Rao * Class to create a temporary certificate file for uploading to system 1485968caeeSMarri Devender Rao */ 1495968caeeSMarri Devender Rao class CertificateFile 1505968caeeSMarri Devender Rao { 1515968caeeSMarri Devender Rao public: 1525968caeeSMarri Devender Rao CertificateFile() = delete; 1535968caeeSMarri Devender Rao CertificateFile(const CertificateFile&) = delete; 1545968caeeSMarri Devender Rao CertificateFile& operator=(const CertificateFile&) = delete; 1555968caeeSMarri Devender Rao CertificateFile(CertificateFile&&) = delete; 1565968caeeSMarri Devender Rao CertificateFile& operator=(CertificateFile&&) = delete; 1575968caeeSMarri Devender Rao CertificateFile(const std::string& certString) 1585968caeeSMarri Devender Rao { 15972d52d25SEd Tanous std::array<char, 18> dirTemplate = {'/', 't', 'm', 'p', '/', 'C', 1605207438cSEd Tanous 'e', 'r', 't', 's', '.', 'X', 1615207438cSEd Tanous 'X', 'X', 'X', 'X', 'X', '\0'}; 1625207438cSEd Tanous char* tempDirectory = mkdtemp(dirTemplate.data()); 163e662eae8SEd Tanous if (tempDirectory != nullptr) 1645968caeeSMarri Devender Rao { 1655968caeeSMarri Devender Rao certDirectory = tempDirectory; 1665968caeeSMarri Devender Rao certificateFile = certDirectory / "cert.pem"; 1675968caeeSMarri Devender Rao std::ofstream out(certificateFile, std::ofstream::out | 1685968caeeSMarri Devender Rao std::ofstream::binary | 1695968caeeSMarri Devender Rao std::ofstream::trunc); 1705968caeeSMarri Devender Rao out << certString; 1715968caeeSMarri Devender Rao out.close(); 1728cc8edecSEd Tanous BMCWEB_LOG_DEBUG << "Creating certificate file" 1738cc8edecSEd Tanous << certificateFile.string(); 1745968caeeSMarri Devender Rao } 1755968caeeSMarri Devender Rao } 1765968caeeSMarri Devender Rao ~CertificateFile() 1775968caeeSMarri Devender Rao { 1785968caeeSMarri Devender Rao if (std::filesystem::exists(certDirectory)) 1795968caeeSMarri Devender Rao { 1808cc8edecSEd Tanous BMCWEB_LOG_DEBUG << "Removing certificate file" 1818cc8edecSEd Tanous << certificateFile.string(); 18223a21a1cSEd Tanous std::error_code ec; 18323a21a1cSEd Tanous std::filesystem::remove_all(certDirectory, ec); 18423a21a1cSEd Tanous if (ec) 1855968caeeSMarri Devender Rao { 1865968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Failed to remove temp directory" 1878cc8edecSEd Tanous << certDirectory.string(); 1885968caeeSMarri Devender Rao } 1895968caeeSMarri Devender Rao } 1905968caeeSMarri Devender Rao } 1915968caeeSMarri Devender Rao std::string getCertFilePath() 1925968caeeSMarri Devender Rao { 1935968caeeSMarri Devender Rao return certificateFile; 1945968caeeSMarri Devender Rao } 1955968caeeSMarri Devender Rao 1965968caeeSMarri Devender Rao private: 1975968caeeSMarri Devender Rao std::filesystem::path certificateFile; 1985968caeeSMarri Devender Rao std::filesystem::path certDirectory; 1995968caeeSMarri Devender Rao }; 2005968caeeSMarri Devender Rao 20130215816SMarri Devender Rao static std::unique_ptr<sdbusplus::bus::match::match> csrMatcher; 20230215816SMarri Devender Rao /** 20330215816SMarri Devender Rao * @brief Read data from CSR D-bus object and set to response 20430215816SMarri Devender Rao * 20530215816SMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 20630215816SMarri Devender Rao * @param[in] certURI Link to certifiate collection URI 20730215816SMarri Devender Rao * @param[in] service D-Bus service name 20830215816SMarri Devender Rao * @param[in] certObjPath certificate D-Bus object path 20930215816SMarri Devender Rao * @param[in] csrObjPath CSR D-Bus object path 21030215816SMarri Devender Rao * @return None 21130215816SMarri Devender Rao */ 2128d1b46d7Szhanghch05 static void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 21330215816SMarri Devender Rao const std::string& certURI, const std::string& service, 21430215816SMarri Devender Rao const std::string& certObjPath, 21530215816SMarri Devender Rao const std::string& csrObjPath) 21630215816SMarri Devender Rao { 21730215816SMarri Devender Rao BMCWEB_LOG_DEBUG << "getCSR CertObjectPath" << certObjPath 21830215816SMarri Devender Rao << " CSRObjectPath=" << csrObjPath 21930215816SMarri Devender Rao << " service=" << service; 22030215816SMarri Devender Rao crow::connections::systemBus->async_method_call( 22130215816SMarri Devender Rao [asyncResp, certURI](const boost::system::error_code ec, 22230215816SMarri Devender Rao const std::string& csr) { 22330215816SMarri Devender Rao if (ec) 22430215816SMarri Devender Rao { 22530215816SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 22630215816SMarri Devender Rao messages::internalError(asyncResp->res); 22730215816SMarri Devender Rao return; 22830215816SMarri Devender Rao } 22930215816SMarri Devender Rao if (csr.empty()) 23030215816SMarri Devender Rao { 23130215816SMarri Devender Rao BMCWEB_LOG_ERROR << "CSR read is empty"; 23230215816SMarri Devender Rao messages::internalError(asyncResp->res); 23330215816SMarri Devender Rao return; 23430215816SMarri Devender Rao } 23530215816SMarri Devender Rao asyncResp->res.jsonValue["CSRString"] = csr; 23630215816SMarri Devender Rao asyncResp->res.jsonValue["CertificateCollection"] = { 23730215816SMarri Devender Rao {"@odata.id", certURI}}; 23830215816SMarri Devender Rao }, 23930215816SMarri Devender Rao service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR"); 24030215816SMarri Devender Rao } 24130215816SMarri Devender Rao 24230215816SMarri Devender Rao /** 24330215816SMarri Devender Rao * Action to Generate CSR 24430215816SMarri Devender Rao */ 2457e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionGenerateCSR(App& app) 24630215816SMarri Devender Rao { 2470fda0f12SGeorge Liu BMCWEB_ROUTE( 2480fda0f12SGeorge Liu app, 2490fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR/") 250ed398213SEd Tanous // Incorrect Privilege; Should be ConfigureManager 251ed398213SEd Tanous //.privileges(redfish::privileges::postCertificateService) 252432a890cSEd Tanous .privileges({{"ConfigureComponents"}}) 2530fda0f12SGeorge Liu .methods( 2540fda0f12SGeorge Liu boost::beast::http::verb:: 255*45ca1b86SEd Tanous post)([&app]( 256*45ca1b86SEd Tanous const crow::Request& req, 2577e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 258*45ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 259*45ca1b86SEd Tanous { 260*45ca1b86SEd Tanous return; 261*45ca1b86SEd Tanous } 2622c70f800SEd Tanous static const int rsaKeyBitLength = 2048; 2638d1b46d7Szhanghch05 26430215816SMarri Devender Rao // Required parameters 26530215816SMarri Devender Rao std::string city; 26630215816SMarri Devender Rao std::string commonName; 26730215816SMarri Devender Rao std::string country; 26830215816SMarri Devender Rao std::string organization; 26930215816SMarri Devender Rao std::string organizationalUnit; 27030215816SMarri Devender Rao std::string state; 27130215816SMarri Devender Rao nlohmann::json certificateCollection; 27230215816SMarri Devender Rao 27330215816SMarri Devender Rao // Optional parameters 27430215816SMarri Devender Rao std::optional<std::vector<std::string>> optAlternativeNames = 27530215816SMarri Devender Rao std::vector<std::string>(); 27630215816SMarri Devender Rao std::optional<std::string> optContactPerson = ""; 27730215816SMarri Devender Rao std::optional<std::string> optChallengePassword = ""; 27830215816SMarri Devender Rao std::optional<std::string> optEmail = ""; 27930215816SMarri Devender Rao std::optional<std::string> optGivenName = ""; 28030215816SMarri Devender Rao std::optional<std::string> optInitials = ""; 2812c70f800SEd Tanous std::optional<int64_t> optKeyBitLength = rsaKeyBitLength; 282aaf3206fSVernon Mauery std::optional<std::string> optKeyCurveId = "secp384r1"; 28330215816SMarri Devender Rao std::optional<std::string> optKeyPairAlgorithm = "EC"; 28430215816SMarri Devender Rao std::optional<std::vector<std::string>> optKeyUsage = 28530215816SMarri Devender Rao std::vector<std::string>(); 28630215816SMarri Devender Rao std::optional<std::string> optSurname = ""; 28730215816SMarri Devender Rao std::optional<std::string> optUnstructuredName = ""; 28815ed6780SWilly Tu if (!json_util::readJsonAction( 2890fda0f12SGeorge Liu req, asyncResp->res, "City", city, "CommonName", commonName, 2900fda0f12SGeorge Liu "ContactPerson", optContactPerson, "Country", country, 2910fda0f12SGeorge Liu "Organization", organization, "OrganizationalUnit", 2920fda0f12SGeorge Liu organizationalUnit, "State", state, "CertificateCollection", 2930fda0f12SGeorge Liu certificateCollection, "AlternativeNames", 2940fda0f12SGeorge Liu optAlternativeNames, "ChallengePassword", 2950fda0f12SGeorge Liu optChallengePassword, "Email", optEmail, "GivenName", 2960fda0f12SGeorge Liu optGivenName, "Initials", optInitials, "KeyBitLength", 2970fda0f12SGeorge Liu optKeyBitLength, "KeyCurveId", optKeyCurveId, 2980fda0f12SGeorge Liu "KeyPairAlgorithm", optKeyPairAlgorithm, "KeyUsage", 2990fda0f12SGeorge Liu optKeyUsage, "Surname", optSurname, "UnstructuredName", 3000fda0f12SGeorge Liu optUnstructuredName)) 30130215816SMarri Devender Rao { 30230215816SMarri Devender Rao return; 30330215816SMarri Devender Rao } 30430215816SMarri Devender Rao 30530215816SMarri Devender Rao // bmcweb has no way to store or decode a private key challenge 3067e860f15SJohn Edward Broadbent // password, which will likely cause bmcweb to crash on startup 3077e860f15SJohn Edward Broadbent // if this is not set on a post so not allowing the user to set 3087e860f15SJohn Edward Broadbent // value 30926f6976fSEd Tanous if (!optChallengePassword->empty()) 31030215816SMarri Devender Rao { 3117e860f15SJohn Edward Broadbent messages::actionParameterNotSupported( 3127e860f15SJohn Edward Broadbent asyncResp->res, "GenerateCSR", "ChallengePassword"); 31330215816SMarri Devender Rao return; 31430215816SMarri Devender Rao } 31530215816SMarri Devender Rao 31630215816SMarri Devender Rao std::string certURI; 3177e860f15SJohn Edward Broadbent if (!redfish::json_util::readJson(certificateCollection, 3187e860f15SJohn Edward Broadbent asyncResp->res, "@odata.id", 3197e860f15SJohn Edward Broadbent certURI)) 32030215816SMarri Devender Rao { 32130215816SMarri Devender Rao return; 32230215816SMarri Devender Rao } 32330215816SMarri Devender Rao 32430215816SMarri Devender Rao std::string objectPath; 32530215816SMarri Devender Rao std::string service; 3260fda0f12SGeorge Liu if (boost::starts_with( 3270fda0f12SGeorge Liu certURI, 3280fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) 32930215816SMarri Devender Rao { 33030215816SMarri Devender Rao objectPath = certs::httpsObjectPath; 33130215816SMarri Devender Rao service = certs::httpsServiceName; 33230215816SMarri Devender Rao } 3333b7f0149SMarri Devender Rao else if (boost::starts_with( 3347e860f15SJohn Edward Broadbent certURI, 3357e860f15SJohn Edward Broadbent "/redfish/v1/AccountService/LDAP/Certificates")) 3363b7f0149SMarri Devender Rao { 3373b7f0149SMarri Devender Rao objectPath = certs::ldapObjectPath; 3383b7f0149SMarri Devender Rao service = certs::ldapServiceName; 3393b7f0149SMarri Devender Rao } 34030215816SMarri Devender Rao else 34130215816SMarri Devender Rao { 34230215816SMarri Devender Rao messages::actionParameterNotSupported( 34330215816SMarri Devender Rao asyncResp->res, "CertificateCollection", "GenerateCSR"); 34430215816SMarri Devender Rao return; 34530215816SMarri Devender Rao } 34630215816SMarri Devender Rao 34730215816SMarri Devender Rao // supporting only EC and RSA algorithm 3480fda0f12SGeorge Liu if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA") 34930215816SMarri Devender Rao { 35030215816SMarri Devender Rao messages::actionParameterNotSupported( 35130215816SMarri Devender Rao asyncResp->res, "KeyPairAlgorithm", "GenerateCSR"); 35230215816SMarri Devender Rao return; 35330215816SMarri Devender Rao } 35430215816SMarri Devender Rao 3557e860f15SJohn Edward Broadbent // supporting only 2048 key bit length for RSA algorithm due to 3567e860f15SJohn Edward Broadbent // time consumed in generating private key 35730215816SMarri Devender Rao if (*optKeyPairAlgorithm == "RSA" && 3582c70f800SEd Tanous *optKeyBitLength != rsaKeyBitLength) 35930215816SMarri Devender Rao { 3607e860f15SJohn Edward Broadbent messages::propertyValueNotInList( 3617e860f15SJohn Edward Broadbent asyncResp->res, std::to_string(*optKeyBitLength), 36230215816SMarri Devender Rao "KeyBitLength"); 36330215816SMarri Devender Rao return; 36430215816SMarri Devender Rao } 36530215816SMarri Devender Rao 36630215816SMarri Devender Rao // validate KeyUsage supporting only 1 type based on URL 3670fda0f12SGeorge Liu if (boost::starts_with( 3680fda0f12SGeorge Liu certURI, 3690fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) 37030215816SMarri Devender Rao { 37126f6976fSEd Tanous if (optKeyUsage->empty()) 37230215816SMarri Devender Rao { 37330215816SMarri Devender Rao optKeyUsage->push_back("ServerAuthentication"); 37430215816SMarri Devender Rao } 37530215816SMarri Devender Rao else if (optKeyUsage->size() == 1) 37630215816SMarri Devender Rao { 37730215816SMarri Devender Rao if ((*optKeyUsage)[0] != "ServerAuthentication") 37830215816SMarri Devender Rao { 37930215816SMarri Devender Rao messages::propertyValueNotInList( 38030215816SMarri Devender Rao asyncResp->res, (*optKeyUsage)[0], "KeyUsage"); 38130215816SMarri Devender Rao return; 38230215816SMarri Devender Rao } 38330215816SMarri Devender Rao } 38430215816SMarri Devender Rao else 38530215816SMarri Devender Rao { 38630215816SMarri Devender Rao messages::actionParameterNotSupported( 38730215816SMarri Devender Rao asyncResp->res, "KeyUsage", "GenerateCSR"); 38830215816SMarri Devender Rao return; 38930215816SMarri Devender Rao } 39030215816SMarri Devender Rao } 3913b7f0149SMarri Devender Rao else if (boost::starts_with( 3927e860f15SJohn Edward Broadbent certURI, 3937e860f15SJohn Edward Broadbent "/redfish/v1/AccountService/LDAP/Certificates")) 3943b7f0149SMarri Devender Rao { 39526f6976fSEd Tanous if (optKeyUsage->empty()) 3963b7f0149SMarri Devender Rao { 3973b7f0149SMarri Devender Rao optKeyUsage->push_back("ClientAuthentication"); 3983b7f0149SMarri Devender Rao } 3993b7f0149SMarri Devender Rao else if (optKeyUsage->size() == 1) 4003b7f0149SMarri Devender Rao { 4013b7f0149SMarri Devender Rao if ((*optKeyUsage)[0] != "ClientAuthentication") 4023b7f0149SMarri Devender Rao { 4033b7f0149SMarri Devender Rao messages::propertyValueNotInList( 4043b7f0149SMarri Devender Rao asyncResp->res, (*optKeyUsage)[0], "KeyUsage"); 4053b7f0149SMarri Devender Rao return; 4063b7f0149SMarri Devender Rao } 4073b7f0149SMarri Devender Rao } 4083b7f0149SMarri Devender Rao else 4093b7f0149SMarri Devender Rao { 4103b7f0149SMarri Devender Rao messages::actionParameterNotSupported( 4113b7f0149SMarri Devender Rao asyncResp->res, "KeyUsage", "GenerateCSR"); 4123b7f0149SMarri Devender Rao return; 4133b7f0149SMarri Devender Rao } 4143b7f0149SMarri Devender Rao } 41530215816SMarri Devender Rao 4167e860f15SJohn Edward Broadbent // Only allow one CSR matcher at a time so setting retry 4177e860f15SJohn Edward Broadbent // time-out and timer expiry to 10 seconds for now. 4182c70f800SEd Tanous static const int timeOut = 10; 41930215816SMarri Devender Rao if (csrMatcher) 42030215816SMarri Devender Rao { 4217e860f15SJohn Edward Broadbent messages::serviceTemporarilyUnavailable( 4227e860f15SJohn Edward Broadbent asyncResp->res, std::to_string(timeOut)); 42330215816SMarri Devender Rao return; 42430215816SMarri Devender Rao } 42530215816SMarri Devender Rao 42630215816SMarri Devender Rao // Make this static so it survives outside this method 42730215816SMarri Devender Rao static boost::asio::steady_timer timeout(*req.ioService); 4282c70f800SEd Tanous timeout.expires_after(std::chrono::seconds(timeOut)); 4290fda0f12SGeorge Liu timeout.async_wait( 4300fda0f12SGeorge Liu [asyncResp](const boost::system::error_code& ec) { 43130215816SMarri Devender Rao csrMatcher = nullptr; 43230215816SMarri Devender Rao if (ec) 43330215816SMarri Devender Rao { 4347e860f15SJohn Edward Broadbent // operation_aborted is expected if timer is canceled 4357e860f15SJohn Edward Broadbent // before completion. 43630215816SMarri Devender Rao if (ec != boost::asio::error::operation_aborted) 43730215816SMarri Devender Rao { 43830215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Async_wait failed " << ec; 43930215816SMarri Devender Rao } 44030215816SMarri Devender Rao return; 44130215816SMarri Devender Rao } 44230215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR"; 44330215816SMarri Devender Rao messages::internalError(asyncResp->res); 44430215816SMarri Devender Rao }); 44530215816SMarri Devender Rao 44630215816SMarri Devender Rao // create a matcher to wait on CSR object 44730215816SMarri Devender Rao BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath; 4480fda0f12SGeorge Liu std::string match("type='signal'," 44930215816SMarri Devender Rao "interface='org.freedesktop.DBus.ObjectManager'," 45030215816SMarri Devender Rao "path='" + 45130215816SMarri Devender Rao objectPath + 45230215816SMarri Devender Rao "'," 45330215816SMarri Devender Rao "member='InterfacesAdded'"); 45430215816SMarri Devender Rao csrMatcher = std::make_unique<sdbusplus::bus::match::match>( 45530215816SMarri Devender Rao *crow::connections::systemBus, match, 45630215816SMarri Devender Rao [asyncResp, service, objectPath, 45730215816SMarri Devender Rao certURI](sdbusplus::message::message& m) { 458271584abSEd Tanous timeout.cancel(); 45930215816SMarri Devender Rao if (m.is_method_error()) 46030215816SMarri Devender Rao { 46130215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Dbus method error!!!"; 46230215816SMarri Devender Rao messages::internalError(asyncResp->res); 46330215816SMarri Devender Rao return; 46430215816SMarri Devender Rao } 465b9d36b47SEd Tanous 466b9d36b47SEd Tanous dbus::utility::DBusInteracesMap interfacesProperties; 467b9d36b47SEd Tanous 46830215816SMarri Devender Rao sdbusplus::message::object_path csrObjectPath; 46930215816SMarri Devender Rao m.read(csrObjectPath, interfacesProperties); 4700fda0f12SGeorge Liu BMCWEB_LOG_DEBUG << "CSR object added" << csrObjectPath.str; 47130215816SMarri Devender Rao for (auto& interface : interfacesProperties) 47230215816SMarri Devender Rao { 4730fda0f12SGeorge Liu if (interface.first == "xyz.openbmc_project.Certs.CSR") 47430215816SMarri Devender Rao { 47530215816SMarri Devender Rao getCSR(asyncResp, certURI, service, objectPath, 47630215816SMarri Devender Rao csrObjectPath.str); 47730215816SMarri Devender Rao break; 47830215816SMarri Devender Rao } 47930215816SMarri Devender Rao } 48030215816SMarri Devender Rao }); 48130215816SMarri Devender Rao crow::connections::systemBus->async_method_call( 482914e2d5dSEd Tanous [asyncResp](const boost::system::error_code ec, 483cb13a392SEd Tanous const std::string&) { 48430215816SMarri Devender Rao if (ec) 48530215816SMarri Devender Rao { 4867e860f15SJohn Edward Broadbent BMCWEB_LOG_ERROR << "DBUS response error: " 4877e860f15SJohn Edward Broadbent << ec.message(); 48830215816SMarri Devender Rao messages::internalError(asyncResp->res); 48930215816SMarri Devender Rao return; 49030215816SMarri Devender Rao } 49130215816SMarri Devender Rao }, 49230215816SMarri Devender Rao service, objectPath, "xyz.openbmc_project.Certs.CSR.Create", 4937e860f15SJohn Edward Broadbent "GenerateCSR", *optAlternativeNames, *optChallengePassword, 4947e860f15SJohn Edward Broadbent city, commonName, *optContactPerson, country, *optEmail, 4950fda0f12SGeorge Liu *optGivenName, *optInitials, *optKeyBitLength, *optKeyCurveId, 4960fda0f12SGeorge Liu *optKeyPairAlgorithm, *optKeyUsage, organization, 4970fda0f12SGeorge Liu organizationalUnit, state, *optSurname, *optUnstructuredName); 4987e860f15SJohn Edward Broadbent }); 4997e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionGenerateCSR 50030215816SMarri Devender Rao 5015968caeeSMarri Devender Rao /** 5024e0453b1SGunnar Mills * @brief Parse and update Certificate Issue/Subject property 5035968caeeSMarri Devender Rao * 5045968caeeSMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 5055968caeeSMarri Devender Rao * @param[in] str Issuer/Subject value in key=value pairs 5065968caeeSMarri Devender Rao * @param[in] type Issuer/Subject 5075968caeeSMarri Devender Rao * @return None 5085968caeeSMarri Devender Rao */ 5095968caeeSMarri Devender Rao static void updateCertIssuerOrSubject(nlohmann::json& out, 5105968caeeSMarri Devender Rao const std::string_view value) 5115968caeeSMarri Devender Rao { 5125968caeeSMarri Devender Rao // example: O=openbmc-project.xyz,CN=localhost 5135968caeeSMarri Devender Rao std::string_view::iterator i = value.begin(); 5145968caeeSMarri Devender Rao while (i != value.end()) 5155968caeeSMarri Devender Rao { 5165968caeeSMarri Devender Rao std::string_view::iterator tokenBegin = i; 5175968caeeSMarri Devender Rao while (i != value.end() && *i != '=') 5185968caeeSMarri Devender Rao { 51917a897dfSManojkiran Eda ++i; 5205968caeeSMarri Devender Rao } 5215968caeeSMarri Devender Rao if (i == value.end()) 5225968caeeSMarri Devender Rao { 5235968caeeSMarri Devender Rao break; 5245968caeeSMarri Devender Rao } 525271584abSEd Tanous const std::string_view key(tokenBegin, 526271584abSEd Tanous static_cast<size_t>(i - tokenBegin)); 52717a897dfSManojkiran Eda ++i; 5285968caeeSMarri Devender Rao tokenBegin = i; 5295968caeeSMarri Devender Rao while (i != value.end() && *i != ',') 5305968caeeSMarri Devender Rao { 53117a897dfSManojkiran Eda ++i; 5325968caeeSMarri Devender Rao } 533271584abSEd Tanous const std::string_view val(tokenBegin, 534271584abSEd Tanous static_cast<size_t>(i - tokenBegin)); 5355968caeeSMarri Devender Rao if (key == "L") 5365968caeeSMarri Devender Rao { 5375968caeeSMarri Devender Rao out["City"] = val; 5385968caeeSMarri Devender Rao } 5395968caeeSMarri Devender Rao else if (key == "CN") 5405968caeeSMarri Devender Rao { 5415968caeeSMarri Devender Rao out["CommonName"] = val; 5425968caeeSMarri Devender Rao } 5435968caeeSMarri Devender Rao else if (key == "C") 5445968caeeSMarri Devender Rao { 5455968caeeSMarri Devender Rao out["Country"] = val; 5465968caeeSMarri Devender Rao } 5475968caeeSMarri Devender Rao else if (key == "O") 5485968caeeSMarri Devender Rao { 5495968caeeSMarri Devender Rao out["Organization"] = val; 5505968caeeSMarri Devender Rao } 5515968caeeSMarri Devender Rao else if (key == "OU") 5525968caeeSMarri Devender Rao { 5535968caeeSMarri Devender Rao out["OrganizationalUnit"] = val; 5545968caeeSMarri Devender Rao } 5555968caeeSMarri Devender Rao else if (key == "ST") 5565968caeeSMarri Devender Rao { 5575968caeeSMarri Devender Rao out["State"] = val; 5585968caeeSMarri Devender Rao } 5595968caeeSMarri Devender Rao // skip comma character 5605968caeeSMarri Devender Rao if (i != value.end()) 5615968caeeSMarri Devender Rao { 56217a897dfSManojkiran Eda ++i; 5635968caeeSMarri Devender Rao } 5645968caeeSMarri Devender Rao } 5655968caeeSMarri Devender Rao } 5665968caeeSMarri Devender Rao 5675968caeeSMarri Devender Rao /** 5685968caeeSMarri Devender Rao * @brief Retrieve the certificates properties and append to the response 5695968caeeSMarri Devender Rao * message 5705968caeeSMarri Devender Rao * 5715968caeeSMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 5725968caeeSMarri Devender Rao * @param[in] objectPath Path of the D-Bus service object 5735968caeeSMarri Devender Rao * @param[in] certId Id of the certificate 5745968caeeSMarri Devender Rao * @param[in] certURL URL of the certificate object 5755968caeeSMarri Devender Rao * @param[in] name name of the certificate 5765968caeeSMarri Devender Rao * @return None 5775968caeeSMarri Devender Rao */ 5785968caeeSMarri Devender Rao static void getCertificateProperties( 5798d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 5808d1b46d7Szhanghch05 const std::string& objectPath, const std::string& service, long certId, 5818d1b46d7Szhanghch05 const std::string& certURL, const std::string& name) 5825968caeeSMarri Devender Rao { 5835968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "getCertificateProperties Path=" << objectPath 5845968caeeSMarri Devender Rao << " certId=" << certId << " certURl=" << certURL; 5855968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 586b9d36b47SEd Tanous [asyncResp, certURL, certId, 587b9d36b47SEd Tanous name](const boost::system::error_code ec, 588b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& properties) { 5895968caeeSMarri Devender Rao if (ec) 5905968caeeSMarri Devender Rao { 5915968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 5928aae75adSMarri Devender Rao messages::resourceNotFound(asyncResp->res, name, 5938aae75adSMarri Devender Rao std::to_string(certId)); 5945968caeeSMarri Devender Rao return; 5955968caeeSMarri Devender Rao } 5965968caeeSMarri Devender Rao asyncResp->res.jsonValue = { 5975968caeeSMarri Devender Rao {"@odata.id", certURL}, 5985968caeeSMarri Devender Rao {"@odata.type", "#Certificate.v1_0_0.Certificate"}, 5995968caeeSMarri Devender Rao {"Id", std::to_string(certId)}, 6005968caeeSMarri Devender Rao {"Name", name}, 6015968caeeSMarri Devender Rao {"Description", name}}; 6025968caeeSMarri Devender Rao for (const auto& property : properties) 6035968caeeSMarri Devender Rao { 6045968caeeSMarri Devender Rao if (property.first == "CertificateString") 6055968caeeSMarri Devender Rao { 6065968caeeSMarri Devender Rao asyncResp->res.jsonValue["CertificateString"] = ""; 6075968caeeSMarri Devender Rao const std::string* value = 6085968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 609e662eae8SEd Tanous if (value != nullptr) 6105968caeeSMarri Devender Rao { 61137cce918SMarri Devender Rao asyncResp->res.jsonValue["CertificateString"] = *value; 6125968caeeSMarri Devender Rao } 6135968caeeSMarri Devender Rao } 6145968caeeSMarri Devender Rao else if (property.first == "KeyUsage") 6155968caeeSMarri Devender Rao { 6165968caeeSMarri Devender Rao nlohmann::json& keyUsage = 6175968caeeSMarri Devender Rao asyncResp->res.jsonValue["KeyUsage"]; 6185968caeeSMarri Devender Rao keyUsage = nlohmann::json::array(); 6195968caeeSMarri Devender Rao const std::vector<std::string>* value = 62037cce918SMarri Devender Rao std::get_if<std::vector<std::string>>(&property.second); 621e662eae8SEd Tanous if (value != nullptr) 6225968caeeSMarri Devender Rao { 6235968caeeSMarri Devender Rao for (const std::string& usage : *value) 6245968caeeSMarri Devender Rao { 6255968caeeSMarri Devender Rao keyUsage.push_back(usage); 6265968caeeSMarri Devender Rao } 6275968caeeSMarri Devender Rao } 6285968caeeSMarri Devender Rao } 6295968caeeSMarri Devender Rao else if (property.first == "Issuer") 6305968caeeSMarri Devender Rao { 6315968caeeSMarri Devender Rao const std::string* value = 6325968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 633e662eae8SEd Tanous if (value != nullptr) 6345968caeeSMarri Devender Rao { 6355968caeeSMarri Devender Rao updateCertIssuerOrSubject( 6365968caeeSMarri Devender Rao asyncResp->res.jsonValue["Issuer"], *value); 6375968caeeSMarri Devender Rao } 6385968caeeSMarri Devender Rao } 6395968caeeSMarri Devender Rao else if (property.first == "Subject") 6405968caeeSMarri Devender Rao { 6415968caeeSMarri Devender Rao const std::string* value = 6425968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 643e662eae8SEd Tanous if (value != nullptr) 6445968caeeSMarri Devender Rao { 6455968caeeSMarri Devender Rao updateCertIssuerOrSubject( 64637cce918SMarri Devender Rao asyncResp->res.jsonValue["Subject"], *value); 6475968caeeSMarri Devender Rao } 6485968caeeSMarri Devender Rao } 6495968caeeSMarri Devender Rao else if (property.first == "ValidNotAfter") 6505968caeeSMarri Devender Rao { 6515968caeeSMarri Devender Rao const uint64_t* value = 6525968caeeSMarri Devender Rao std::get_if<uint64_t>(&property.second); 653e662eae8SEd Tanous if (value != nullptr) 6545968caeeSMarri Devender Rao { 6555968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotAfter"] = 6561d8782e7SNan Zhou crow::utility::getDateTimeUint(*value); 6575968caeeSMarri Devender Rao } 6585968caeeSMarri Devender Rao } 6595968caeeSMarri Devender Rao else if (property.first == "ValidNotBefore") 6605968caeeSMarri Devender Rao { 6615968caeeSMarri Devender Rao const uint64_t* value = 6625968caeeSMarri Devender Rao std::get_if<uint64_t>(&property.second); 663e662eae8SEd Tanous if (value != nullptr) 6645968caeeSMarri Devender Rao { 6655968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotBefore"] = 6661d8782e7SNan Zhou crow::utility::getDateTimeUint(*value); 6675968caeeSMarri Devender Rao } 6685968caeeSMarri Devender Rao } 6695968caeeSMarri Devender Rao } 6705968caeeSMarri Devender Rao asyncResp->res.addHeader("Location", certURL); 6715968caeeSMarri Devender Rao }, 6725968caeeSMarri Devender Rao service, objectPath, certs::dbusPropIntf, "GetAll", 6735968caeeSMarri Devender Rao certs::certPropIntf); 6745968caeeSMarri Devender Rao } 6755968caeeSMarri Devender Rao 6765968caeeSMarri Devender Rao /** 6775968caeeSMarri Devender Rao * Action to replace an existing certificate 6785968caeeSMarri Devender Rao */ 6797e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionsReplaceCertificate(App& app) 6805968caeeSMarri Devender Rao { 6810fda0f12SGeorge Liu BMCWEB_ROUTE( 6820fda0f12SGeorge Liu app, 6830fda0f12SGeorge Liu "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate/") 684ed398213SEd Tanous .privileges(redfish::privileges::postCertificateService) 6857e860f15SJohn Edward Broadbent .methods( 6867e860f15SJohn Edward Broadbent boost::beast::http::verb:: 687*45ca1b86SEd Tanous post)([&app]( 688*45ca1b86SEd Tanous const crow::Request& req, 6897e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 690*45ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 691*45ca1b86SEd Tanous { 692*45ca1b86SEd Tanous return; 693*45ca1b86SEd Tanous } 6945968caeeSMarri Devender Rao std::string certificate; 6955968caeeSMarri Devender Rao nlohmann::json certificateUri; 6965968caeeSMarri Devender Rao std::optional<std::string> certificateType = "PEM"; 6978d1b46d7Szhanghch05 69815ed6780SWilly Tu if (!json_util::readJsonAction(req, asyncResp->res, 69915ed6780SWilly Tu "CertificateString", certificate, 70015ed6780SWilly Tu "CertificateUri", certificateUri, 70115ed6780SWilly Tu "CertificateType", certificateType)) 7025968caeeSMarri Devender Rao { 7035968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Required parameters are missing"; 7045968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 7055968caeeSMarri Devender Rao return; 7065968caeeSMarri Devender Rao } 7075968caeeSMarri Devender Rao 7085968caeeSMarri Devender Rao if (!certificateType) 7095968caeeSMarri Devender Rao { 7105968caeeSMarri Devender Rao // should never happen, but it never hurts to be paranoid. 7115968caeeSMarri Devender Rao return; 7125968caeeSMarri Devender Rao } 7135968caeeSMarri Devender Rao if (certificateType != "PEM") 7145968caeeSMarri Devender Rao { 7155968caeeSMarri Devender Rao messages::actionParameterNotSupported( 7165968caeeSMarri Devender Rao asyncResp->res, "CertificateType", "ReplaceCertificate"); 7175968caeeSMarri Devender Rao return; 7185968caeeSMarri Devender Rao } 7195968caeeSMarri Devender Rao 7205968caeeSMarri Devender Rao std::string certURI; 7215968caeeSMarri Devender Rao if (!redfish::json_util::readJson(certificateUri, asyncResp->res, 7225968caeeSMarri Devender Rao "@odata.id", certURI)) 7235968caeeSMarri Devender Rao { 7245968caeeSMarri Devender Rao messages::actionParameterMissing( 7255968caeeSMarri Devender Rao asyncResp->res, "ReplaceCertificate", "CertificateUri"); 7265968caeeSMarri Devender Rao return; 7275968caeeSMarri Devender Rao } 7285968caeeSMarri Devender Rao 7295968caeeSMarri Devender Rao BMCWEB_LOG_INFO << "Certificate URI to replace" << certURI; 7305968caeeSMarri Devender Rao long id = getIDFromURL(certURI); 7315968caeeSMarri Devender Rao if (id < 0) 7325968caeeSMarri Devender Rao { 7337e860f15SJohn Edward Broadbent messages::actionParameterValueFormatError( 7347e860f15SJohn Edward Broadbent asyncResp->res, certURI, "CertificateUri", 7355968caeeSMarri Devender Rao "ReplaceCertificate"); 7365968caeeSMarri Devender Rao return; 7375968caeeSMarri Devender Rao } 7385968caeeSMarri Devender Rao std::string objectPath; 7395968caeeSMarri Devender Rao std::string name; 74037cce918SMarri Devender Rao std::string service; 7410fda0f12SGeorge Liu if (boost::starts_with( 7420fda0f12SGeorge Liu certURI, 7430fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/")) 7445968caeeSMarri Devender Rao { 7457e860f15SJohn Edward Broadbent objectPath = std::string(certs::httpsObjectPath) + "/" + 7467e860f15SJohn Edward Broadbent std::to_string(id); 7475968caeeSMarri Devender Rao name = "HTTPS certificate"; 74837cce918SMarri Devender Rao service = certs::httpsServiceName; 74937cce918SMarri Devender Rao } 75037cce918SMarri Devender Rao else if (boost::starts_with( 7517e860f15SJohn Edward Broadbent certURI, 7527e860f15SJohn Edward Broadbent "/redfish/v1/AccountService/LDAP/Certificates/")) 75337cce918SMarri Devender Rao { 7547e860f15SJohn Edward Broadbent objectPath = std::string(certs::ldapObjectPath) + "/" + 7557e860f15SJohn Edward Broadbent std::to_string(id); 75637cce918SMarri Devender Rao name = "LDAP certificate"; 75737cce918SMarri Devender Rao service = certs::ldapServiceName; 7585968caeeSMarri Devender Rao } 759cfcd5f6bSMarri Devender Rao else if (boost::starts_with( 760cfcd5f6bSMarri Devender Rao certURI, 761cfcd5f6bSMarri Devender Rao "/redfish/v1/Managers/bmc/Truststore/Certificates/")) 762cfcd5f6bSMarri Devender Rao { 763cfcd5f6bSMarri Devender Rao objectPath = std::string(certs::authorityObjectPath) + "/" + 764cfcd5f6bSMarri Devender Rao std::to_string(id); 765cfcd5f6bSMarri Devender Rao name = "TrustStore certificate"; 766cfcd5f6bSMarri Devender Rao service = certs::authorityServiceName; 767cfcd5f6bSMarri Devender Rao } 7685968caeeSMarri Devender Rao else 7695968caeeSMarri Devender Rao { 7705968caeeSMarri Devender Rao messages::actionParameterNotSupported( 7715968caeeSMarri Devender Rao asyncResp->res, "CertificateUri", "ReplaceCertificate"); 7725968caeeSMarri Devender Rao return; 7735968caeeSMarri Devender Rao } 7745968caeeSMarri Devender Rao 7755968caeeSMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 7765968caeeSMarri Devender Rao std::make_shared<CertificateFile>(certificate); 7775968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 77837cce918SMarri Devender Rao [asyncResp, certFile, objectPath, service, certURI, id, 7795968caeeSMarri Devender Rao name](const boost::system::error_code ec) { 7805968caeeSMarri Devender Rao if (ec) 7815968caeeSMarri Devender Rao { 7825968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 7838aae75adSMarri Devender Rao messages::resourceNotFound(asyncResp->res, name, 7848aae75adSMarri Devender Rao std::to_string(id)); 7855968caeeSMarri Devender Rao return; 7865968caeeSMarri Devender Rao } 78737cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, service, id, 7885968caeeSMarri Devender Rao certURI, name); 7895968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" 7905968caeeSMarri Devender Rao << certFile->getCertFilePath(); 7915968caeeSMarri Devender Rao }, 7925968caeeSMarri Devender Rao service, objectPath, certs::certReplaceIntf, "Replace", 7935968caeeSMarri Devender Rao certFile->getCertFilePath()); 7947e860f15SJohn Edward Broadbent }); 7957e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionsReplaceCertificate 7965968caeeSMarri Devender Rao 7975968caeeSMarri Devender Rao /** 7985968caeeSMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 7995968caeeSMarri Devender Rao * of a component, account or service. 8005968caeeSMarri Devender Rao */ 8015968caeeSMarri Devender Rao 8027e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificate(App& app) 8035968caeeSMarri Devender Rao { 8047e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 8057e860f15SJohn Edward Broadbent app, 8067e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/<str>/") 807ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 8087e860f15SJohn Edward Broadbent .methods( 8097e860f15SJohn Edward Broadbent boost::beast::http::verb:: 810*45ca1b86SEd Tanous get)([&app](const crow::Request& req, 8117e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 8127e860f15SJohn Edward Broadbent const std::string& param) -> void { 813*45ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 814*45ca1b86SEd Tanous { 815*45ca1b86SEd Tanous return; 816*45ca1b86SEd Tanous } 8177e860f15SJohn Edward Broadbent if (param.empty()) 8185968caeeSMarri Devender Rao { 8195968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 8205968caeeSMarri Devender Rao return; 8215968caeeSMarri Devender Rao } 8225968caeeSMarri Devender Rao long id = getIDFromURL(req.url); 8235968caeeSMarri Devender Rao 8247e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG << "HTTPSCertificate::doGet ID=" 8257e860f15SJohn Edward Broadbent << std::to_string(id); 8265968caeeSMarri Devender Rao std::string certURL = 8275968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" + 8285968caeeSMarri Devender Rao std::to_string(id); 8295968caeeSMarri Devender Rao std::string objectPath = certs::httpsObjectPath; 8305968caeeSMarri Devender Rao objectPath += "/"; 8315968caeeSMarri Devender Rao objectPath += std::to_string(id); 8327e860f15SJohn Edward Broadbent getCertificateProperties(asyncResp, objectPath, 8337e860f15SJohn Edward Broadbent certs::httpsServiceName, id, certURL, 8347e860f15SJohn Edward Broadbent "HTTPS Certificate"); 8357e860f15SJohn Edward Broadbent }); 8365968caeeSMarri Devender Rao } 8375968caeeSMarri Devender Rao 8385968caeeSMarri Devender Rao /** 8395968caeeSMarri Devender Rao * Collection of HTTPS certificates 8405968caeeSMarri Devender Rao */ 8417e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificateCollection(App& app) 8425968caeeSMarri Devender Rao { 8437e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 8445968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/") 845ed398213SEd Tanous .privileges(redfish::privileges::getCertificateCollection) 846*45ca1b86SEd Tanous .methods(boost::beast::http::verb::get)([&app](const crow::Request& req, 847*45ca1b86SEd Tanous const std::shared_ptr< 848*45ca1b86SEd Tanous bmcweb::AsyncResp>& 849*45ca1b86SEd Tanous asyncResp) { 850*45ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 851*45ca1b86SEd Tanous { 852*45ca1b86SEd Tanous return; 853*45ca1b86SEd Tanous } 8548d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 8555968caeeSMarri Devender Rao {"@odata.id", 8565968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"}, 8575968caeeSMarri Devender Rao {"@odata.type", "#CertificateCollection.CertificateCollection"}, 8585968caeeSMarri Devender Rao {"Name", "HTTPS Certificates Collection"}, 8595968caeeSMarri Devender Rao {"Description", "A Collection of HTTPS certificate instances"}}; 8608d1b46d7Szhanghch05 8615968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 8625968caeeSMarri Devender Rao [asyncResp](const boost::system::error_code ec, 863711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& certs) { 8645968caeeSMarri Devender Rao if (ec) 8655968caeeSMarri Devender Rao { 8665968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 8675968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 8685968caeeSMarri Devender Rao return; 8695968caeeSMarri Devender Rao } 8707e860f15SJohn Edward Broadbent nlohmann::json& members = 8717e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Members"]; 8725968caeeSMarri Devender Rao members = nlohmann::json::array(); 8735968caeeSMarri Devender Rao for (const auto& cert : certs) 8745968caeeSMarri Devender Rao { 8755968caeeSMarri Devender Rao long id = getIDFromURL(cert.first.str); 87637cce918SMarri Devender Rao if (id >= 0) 8775968caeeSMarri Devender Rao { 8785968caeeSMarri Devender Rao members.push_back( 8795968caeeSMarri Devender Rao {{"@odata.id", 8800fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" + 8815968caeeSMarri Devender Rao std::to_string(id)}}); 8825968caeeSMarri Devender Rao } 8835968caeeSMarri Devender Rao } 8845968caeeSMarri Devender Rao asyncResp->res.jsonValue["Members@odata.count"] = 8855968caeeSMarri Devender Rao members.size(); 8865968caeeSMarri Devender Rao }, 88737cce918SMarri Devender Rao certs::httpsServiceName, certs::httpsObjectPath, 88837cce918SMarri Devender Rao certs::dbusObjManagerIntf, "GetManagedObjects"); 8897e860f15SJohn Edward Broadbent }); 8905968caeeSMarri Devender Rao 8917e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 8927e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/") 893ed398213SEd Tanous .privileges(redfish::privileges::postCertificateCollection) 8940fda0f12SGeorge Liu .methods( 8950fda0f12SGeorge Liu boost::beast::http::verb:: 896*45ca1b86SEd Tanous post)([&app]( 897*45ca1b86SEd Tanous const crow::Request& req, 8987e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 899*45ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 900*45ca1b86SEd Tanous { 901*45ca1b86SEd Tanous return; 902*45ca1b86SEd Tanous } 9035968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost"; 9048d1b46d7Szhanghch05 9050fda0f12SGeorge Liu asyncResp->res.jsonValue = {{"Name", "HTTPS Certificate"}, 9065968caeeSMarri Devender Rao {"Description", "HTTPS Certificate"}}; 9075968caeeSMarri Devender Rao 9087e860f15SJohn Edward Broadbent std::string certFileBody = 9097e860f15SJohn Edward Broadbent getCertificateFromReqBody(asyncResp, req); 91058eb238fSKowalski, Kamil 91158eb238fSKowalski, Kamil if (certFileBody.empty()) 91258eb238fSKowalski, Kamil { 9130fda0f12SGeorge Liu BMCWEB_LOG_ERROR << "Cannot get certificate from request body."; 914a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 91558eb238fSKowalski, Kamil return; 91658eb238fSKowalski, Kamil } 91758eb238fSKowalski, Kamil 9185968caeeSMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 91958eb238fSKowalski, Kamil std::make_shared<CertificateFile>(certFileBody); 9205968caeeSMarri Devender Rao 9215968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 922656ec7e3SZbigniew Kurzynski [asyncResp, certFile](const boost::system::error_code ec, 923656ec7e3SZbigniew Kurzynski const std::string& objectPath) { 9245968caeeSMarri Devender Rao if (ec) 9255968caeeSMarri Devender Rao { 9265968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 9275968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 9285968caeeSMarri Devender Rao return; 9295968caeeSMarri Devender Rao } 930656ec7e3SZbigniew Kurzynski long certId = getIDFromURL(objectPath); 931656ec7e3SZbigniew Kurzynski if (certId < 0) 932656ec7e3SZbigniew Kurzynski { 933656ec7e3SZbigniew Kurzynski BMCWEB_LOG_ERROR << "Invalid objectPath value" 934656ec7e3SZbigniew Kurzynski << objectPath; 935656ec7e3SZbigniew Kurzynski messages::internalError(asyncResp->res); 936656ec7e3SZbigniew Kurzynski return; 937656ec7e3SZbigniew Kurzynski } 9385968caeeSMarri Devender Rao std::string certURL = 9390fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" + 9405968caeeSMarri Devender Rao std::to_string(certId); 9410fda0f12SGeorge Liu getCertificateProperties(asyncResp, objectPath, 9420fda0f12SGeorge Liu certs::httpsServiceName, certId, 9430fda0f12SGeorge Liu certURL, "HTTPS Certificate"); 9445968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" 9455968caeeSMarri Devender Rao << certFile->getCertFilePath(); 9465968caeeSMarri Devender Rao }, 94737cce918SMarri Devender Rao certs::httpsServiceName, certs::httpsObjectPath, 9480fda0f12SGeorge Liu certs::certInstallIntf, "Install", certFile->getCertFilePath()); 9497e860f15SJohn Edward Broadbent }); 9507e860f15SJohn Edward Broadbent } // requestRoutesHTTPSCertificateCollection 9515968caeeSMarri Devender Rao 9525968caeeSMarri Devender Rao /** 95337cce918SMarri Devender Rao * @brief Retrieve the certificates installed list and append to the 95437cce918SMarri Devender Rao * response 95537cce918SMarri Devender Rao * 95637cce918SMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 95737cce918SMarri Devender Rao * @param[in] certURL Path of the certificate object 95837cce918SMarri Devender Rao * @param[in] path Path of the D-Bus service object 95937cce918SMarri Devender Rao * @return None 96037cce918SMarri Devender Rao */ 9614f48d5f6SEd Tanous inline void 9624f48d5f6SEd Tanous getCertificateLocations(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 9638d1b46d7Szhanghch05 const std::string& certURL, const std::string& path, 96437cce918SMarri Devender Rao const std::string& service) 96537cce918SMarri Devender Rao { 96637cce918SMarri Devender Rao BMCWEB_LOG_DEBUG << "getCertificateLocations URI=" << certURL 96737cce918SMarri Devender Rao << " Path=" << path << " service= " << service; 96837cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 96937cce918SMarri Devender Rao [asyncResp, certURL](const boost::system::error_code ec, 970711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& certs) { 97137cce918SMarri Devender Rao if (ec) 97237cce918SMarri Devender Rao { 9739c8e039eSJonathan Doman BMCWEB_LOG_WARNING 9749c8e039eSJonathan Doman << "Certificate collection query failed: " << ec 9759c8e039eSJonathan Doman << ", skipping " << certURL; 97637cce918SMarri Devender Rao return; 97737cce918SMarri Devender Rao } 97837cce918SMarri Devender Rao nlohmann::json& links = 97937cce918SMarri Devender Rao asyncResp->res.jsonValue["Links"]["Certificates"]; 9809eb808c1SEd Tanous for (const auto& cert : certs) 98137cce918SMarri Devender Rao { 98237cce918SMarri Devender Rao long id = getIDFromURL(cert.first.str); 98337cce918SMarri Devender Rao if (id >= 0) 98437cce918SMarri Devender Rao { 98537cce918SMarri Devender Rao links.push_back( 98637cce918SMarri Devender Rao {{"@odata.id", certURL + std::to_string(id)}}); 98737cce918SMarri Devender Rao } 98837cce918SMarri Devender Rao } 98937cce918SMarri Devender Rao asyncResp->res.jsonValue["Links"]["Certificates@odata.count"] = 99037cce918SMarri Devender Rao links.size(); 99137cce918SMarri Devender Rao }, 99237cce918SMarri Devender Rao service, path, certs::dbusObjManagerIntf, "GetManagedObjects"); 9935968caeeSMarri Devender Rao } 9947e860f15SJohn Edward Broadbent 9957e860f15SJohn Edward Broadbent /** 9967e860f15SJohn Edward Broadbent * The certificate location schema defines a resource that an administrator 9977e860f15SJohn Edward Broadbent * can use in order to locate all certificates installed on a given service. 9987e860f15SJohn Edward Broadbent */ 9997e860f15SJohn Edward Broadbent inline void requestRoutesCertificateLocations(App& app) 10007e860f15SJohn Edward Broadbent { 10017e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/") 1002ed398213SEd Tanous .privileges(redfish::privileges::getCertificateLocations) 1003*45ca1b86SEd Tanous .methods(boost::beast::http::verb::get)([&app](const crow::Request& req, 1004*45ca1b86SEd Tanous const std::shared_ptr< 1005*45ca1b86SEd Tanous bmcweb::AsyncResp>& 1006*45ca1b86SEd Tanous asyncResp) { 1007*45ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 1008*45ca1b86SEd Tanous { 1009*45ca1b86SEd Tanous return; 1010*45ca1b86SEd Tanous } 10117e860f15SJohn Edward Broadbent asyncResp->res.jsonValue = { 10127e860f15SJohn Edward Broadbent {"@odata.id", 10137e860f15SJohn Edward Broadbent "/redfish/v1/CertificateService/CertificateLocations"}, 10147e860f15SJohn Edward Broadbent {"@odata.type", 10157e860f15SJohn Edward Broadbent "#CertificateLocations.v1_0_0.CertificateLocations"}, 10167e860f15SJohn Edward Broadbent {"Name", "Certificate Locations"}, 10177e860f15SJohn Edward Broadbent {"Id", "CertificateLocations"}, 10187e860f15SJohn Edward Broadbent {"Description", 10197e860f15SJohn Edward Broadbent "Defines a resource that an administrator can use in order to " 10207e860f15SJohn Edward Broadbent "locate all certificates installed on a given service"}}; 10217e860f15SJohn Edward Broadbent 10227e860f15SJohn Edward Broadbent nlohmann::json& links = 10237e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Links"]["Certificates"]; 10247e860f15SJohn Edward Broadbent links = nlohmann::json::array(); 10257e860f15SJohn Edward Broadbent getCertificateLocations( 10267e860f15SJohn Edward Broadbent asyncResp, 10277e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/", 10287e860f15SJohn Edward Broadbent certs::httpsObjectPath, certs::httpsServiceName); 10297e860f15SJohn Edward Broadbent getCertificateLocations( 10307e860f15SJohn Edward Broadbent asyncResp, "/redfish/v1/AccountService/LDAP/Certificates/", 10317e860f15SJohn Edward Broadbent certs::ldapObjectPath, certs::ldapServiceName); 10327e860f15SJohn Edward Broadbent getCertificateLocations( 10337e860f15SJohn Edward Broadbent asyncResp, "/redfish/v1/Managers/bmc/Truststore/Certificates/", 10347e860f15SJohn Edward Broadbent certs::authorityObjectPath, certs::authorityServiceName); 10357e860f15SJohn Edward Broadbent }); 10367e860f15SJohn Edward Broadbent } 10377e860f15SJohn Edward Broadbent // requestRoutesCertificateLocations 103837cce918SMarri Devender Rao 103937cce918SMarri Devender Rao /** 104037cce918SMarri Devender Rao * Collection of LDAP certificates 104137cce918SMarri Devender Rao */ 10427e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificateCollection(App& app) 104337cce918SMarri Devender Rao { 10447e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/") 1045ed398213SEd Tanous .privileges(redfish::privileges::getCertificateCollection) 1046*45ca1b86SEd Tanous .methods(boost::beast::http::verb::get)([&app](const crow::Request& req, 1047*45ca1b86SEd Tanous const std::shared_ptr< 1048*45ca1b86SEd Tanous bmcweb::AsyncResp>& 1049*45ca1b86SEd Tanous asyncResp) { 1050*45ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 1051*45ca1b86SEd Tanous { 1052*45ca1b86SEd Tanous return; 1053*45ca1b86SEd Tanous } 10548d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 10550fda0f12SGeorge Liu {"@odata.id", "/redfish/v1/AccountService/LDAP/Certificates"}, 10560fda0f12SGeorge Liu {"@odata.type", "#CertificateCollection.CertificateCollection"}, 105737cce918SMarri Devender Rao {"Name", "LDAP Certificates Collection"}, 10580fda0f12SGeorge Liu {"Description", "A Collection of LDAP certificate instances"}}; 10598d1b46d7Szhanghch05 106037cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 106137cce918SMarri Devender Rao [asyncResp](const boost::system::error_code ec, 1062711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& certs) { 10637e860f15SJohn Edward Broadbent nlohmann::json& members = 10647e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Members"]; 10659c8e039eSJonathan Doman nlohmann::json& count = 10669c8e039eSJonathan Doman asyncResp->res.jsonValue["Members@odata.count"]; 10679c8e039eSJonathan Doman members = nlohmann::json::array(); 10689c8e039eSJonathan Doman count = 0; 106937cce918SMarri Devender Rao if (ec) 107037cce918SMarri Devender Rao { 10710fda0f12SGeorge Liu BMCWEB_LOG_WARNING << "LDAP certificate query failed: " 10720fda0f12SGeorge Liu << ec; 107337cce918SMarri Devender Rao return; 107437cce918SMarri Devender Rao } 107537cce918SMarri Devender Rao for (const auto& cert : certs) 107637cce918SMarri Devender Rao { 107737cce918SMarri Devender Rao long id = getIDFromURL(cert.first.str); 107837cce918SMarri Devender Rao if (id >= 0) 107937cce918SMarri Devender Rao { 108037cce918SMarri Devender Rao members.push_back( 10810fda0f12SGeorge Liu {{"@odata.id", 10820fda0f12SGeorge Liu "/redfish/v1/AccountService/LDAP/Certificates/" + 108337cce918SMarri Devender Rao std::to_string(id)}}); 108437cce918SMarri Devender Rao } 108537cce918SMarri Devender Rao } 10869c8e039eSJonathan Doman count = members.size(); 108737cce918SMarri Devender Rao }, 108837cce918SMarri Devender Rao certs::ldapServiceName, certs::ldapObjectPath, 108937cce918SMarri Devender Rao certs::dbusObjManagerIntf, "GetManagedObjects"); 10907e860f15SJohn Edward Broadbent }); 109137cce918SMarri Devender Rao 10927e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/") 1093ed398213SEd Tanous .privileges(redfish::privileges::postCertificateCollection) 10947e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 1095*45ca1b86SEd Tanous [&app](const crow::Request& req, 10967e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 1097*45ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 1098*45ca1b86SEd Tanous { 1099*45ca1b86SEd Tanous return; 1100*45ca1b86SEd Tanous } 11017e860f15SJohn Edward Broadbent std::string certFileBody = 11027e860f15SJohn Edward Broadbent getCertificateFromReqBody(asyncResp, req); 110358eb238fSKowalski, Kamil 110458eb238fSKowalski, Kamil if (certFileBody.empty()) 110558eb238fSKowalski, Kamil { 11067e860f15SJohn Edward Broadbent BMCWEB_LOG_ERROR 11077e860f15SJohn Edward Broadbent << "Cannot get certificate from request body."; 1108a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 110958eb238fSKowalski, Kamil return; 111058eb238fSKowalski, Kamil } 111158eb238fSKowalski, Kamil 111258eb238fSKowalski, Kamil std::shared_ptr<CertificateFile> certFile = 111358eb238fSKowalski, Kamil std::make_shared<CertificateFile>(certFileBody); 111458eb238fSKowalski, Kamil 111537cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 1116656ec7e3SZbigniew Kurzynski [asyncResp, certFile](const boost::system::error_code ec, 1117656ec7e3SZbigniew Kurzynski const std::string& objectPath) { 111837cce918SMarri Devender Rao if (ec) 111937cce918SMarri Devender Rao { 112037cce918SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 112137cce918SMarri Devender Rao messages::internalError(asyncResp->res); 112237cce918SMarri Devender Rao return; 112337cce918SMarri Devender Rao } 1124656ec7e3SZbigniew Kurzynski long certId = getIDFromURL(objectPath); 1125656ec7e3SZbigniew Kurzynski if (certId < 0) 1126656ec7e3SZbigniew Kurzynski { 1127656ec7e3SZbigniew Kurzynski BMCWEB_LOG_ERROR << "Invalid objectPath value" 1128656ec7e3SZbigniew Kurzynski << objectPath; 1129656ec7e3SZbigniew Kurzynski messages::internalError(asyncResp->res); 1130656ec7e3SZbigniew Kurzynski return; 1131656ec7e3SZbigniew Kurzynski } 113237cce918SMarri Devender Rao std::string certURL = 113337cce918SMarri Devender Rao "/redfish/v1/AccountService/LDAP/Certificates/" + 113437cce918SMarri Devender Rao std::to_string(certId); 113537cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, 113637cce918SMarri Devender Rao certs::ldapServiceName, certId, 113737cce918SMarri Devender Rao certURL, "LDAP Certificate"); 113837cce918SMarri Devender Rao BMCWEB_LOG_DEBUG << "LDAP certificate install file=" 113937cce918SMarri Devender Rao << certFile->getCertFilePath(); 114037cce918SMarri Devender Rao }, 114137cce918SMarri Devender Rao certs::ldapServiceName, certs::ldapObjectPath, 11427e860f15SJohn Edward Broadbent certs::certInstallIntf, "Install", 11437e860f15SJohn Edward Broadbent certFile->getCertFilePath()); 11447e860f15SJohn Edward Broadbent }); 11457e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificateCollection 114637cce918SMarri Devender Rao 114737cce918SMarri Devender Rao /** 114837cce918SMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 114937cce918SMarri Devender Rao * of a component, account or service. 115037cce918SMarri Devender Rao */ 11517e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificate(App& app) 115237cce918SMarri Devender Rao { 11537e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/") 1154ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 11557e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 1156*45ca1b86SEd Tanous [&app](const crow::Request& req, 11577e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 11587e860f15SJohn Edward Broadbent const std::string&) { 1159*45ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 1160*45ca1b86SEd Tanous { 1161*45ca1b86SEd Tanous return; 1162*45ca1b86SEd Tanous } 116337cce918SMarri Devender Rao long id = getIDFromURL(req.url); 116437cce918SMarri Devender Rao if (id < 0) 116537cce918SMarri Devender Rao { 116637cce918SMarri Devender Rao BMCWEB_LOG_ERROR << "Invalid url value" << req.url; 116737cce918SMarri Devender Rao messages::internalError(asyncResp->res); 116837cce918SMarri Devender Rao return; 116937cce918SMarri Devender Rao } 11707e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" 11717e860f15SJohn Edward Broadbent << std::to_string(id); 11727e860f15SJohn Edward Broadbent std::string certURL = 11737e860f15SJohn Edward Broadbent "/redfish/v1/AccountService/LDAP/Certificates/" + 117437cce918SMarri Devender Rao std::to_string(id); 117537cce918SMarri Devender Rao std::string objectPath = certs::ldapObjectPath; 117637cce918SMarri Devender Rao objectPath += "/"; 117737cce918SMarri Devender Rao objectPath += std::to_string(id); 11787e860f15SJohn Edward Broadbent getCertificateProperties(asyncResp, objectPath, 11797e860f15SJohn Edward Broadbent certs::ldapServiceName, id, certURL, 11807e860f15SJohn Edward Broadbent "LDAP Certificate"); 11817e860f15SJohn Edward Broadbent }); 11827e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificate 1183cfcd5f6bSMarri Devender Rao /** 1184cfcd5f6bSMarri Devender Rao * Collection of TrustStoreCertificate certificates 1185cfcd5f6bSMarri Devender Rao */ 11867e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificateCollection(App& app) 1187cfcd5f6bSMarri Devender Rao { 11887e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/") 1189ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 1190*45ca1b86SEd Tanous .methods(boost::beast::http::verb::get)([&app](const crow::Request& req, 1191*45ca1b86SEd Tanous const std::shared_ptr< 1192*45ca1b86SEd Tanous bmcweb::AsyncResp>& 1193*45ca1b86SEd Tanous asyncResp) { 1194*45ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 1195*45ca1b86SEd Tanous { 1196*45ca1b86SEd Tanous return; 1197*45ca1b86SEd Tanous } 11988d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 11997e860f15SJohn Edward Broadbent {"@odata.id", 12007e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc/Truststore/Certificates/"}, 12010fda0f12SGeorge Liu {"@odata.type", "#CertificateCollection.CertificateCollection"}, 1202cfcd5f6bSMarri Devender Rao {"Name", "TrustStore Certificates Collection"}, 1203cfcd5f6bSMarri Devender Rao {"Description", 1204cfcd5f6bSMarri Devender Rao "A Collection of TrustStore certificate instances"}}; 12058d1b46d7Szhanghch05 1206cfcd5f6bSMarri Devender Rao crow::connections::systemBus->async_method_call( 1207cfcd5f6bSMarri Devender Rao [asyncResp](const boost::system::error_code ec, 1208711ac7a9SEd Tanous const dbus::utility::ManagedObjectType& certs) { 1209cfcd5f6bSMarri Devender Rao if (ec) 1210cfcd5f6bSMarri Devender Rao { 1211cfcd5f6bSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 1212cfcd5f6bSMarri Devender Rao messages::internalError(asyncResp->res); 1213cfcd5f6bSMarri Devender Rao return; 1214cfcd5f6bSMarri Devender Rao } 12157e860f15SJohn Edward Broadbent nlohmann::json& members = 12167e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Members"]; 1217cfcd5f6bSMarri Devender Rao members = nlohmann::json::array(); 1218cfcd5f6bSMarri Devender Rao for (const auto& cert : certs) 1219cfcd5f6bSMarri Devender Rao { 1220cfcd5f6bSMarri Devender Rao long id = getIDFromURL(cert.first.str); 1221cfcd5f6bSMarri Devender Rao if (id >= 0) 1222cfcd5f6bSMarri Devender Rao { 1223cfcd5f6bSMarri Devender Rao members.push_back( 12240fda0f12SGeorge Liu {{"@odata.id", 12250fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/Truststore/Certificates/" + 1226cfcd5f6bSMarri Devender Rao std::to_string(id)}}); 1227cfcd5f6bSMarri Devender Rao } 1228cfcd5f6bSMarri Devender Rao } 1229cfcd5f6bSMarri Devender Rao asyncResp->res.jsonValue["Members@odata.count"] = 1230cfcd5f6bSMarri Devender Rao members.size(); 1231cfcd5f6bSMarri Devender Rao }, 1232cfcd5f6bSMarri Devender Rao certs::authorityServiceName, certs::authorityObjectPath, 1233cfcd5f6bSMarri Devender Rao certs::dbusObjManagerIntf, "GetManagedObjects"); 12347e860f15SJohn Edward Broadbent }); 1235cfcd5f6bSMarri Devender Rao 12367e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/") 1237ed398213SEd Tanous .privileges(redfish::privileges::postCertificateCollection) 12380fda0f12SGeorge Liu .methods( 12390fda0f12SGeorge Liu boost::beast::http::verb:: 1240*45ca1b86SEd Tanous post)([&app]( 1241*45ca1b86SEd Tanous const crow::Request& req, 12427e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 1243*45ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 1244*45ca1b86SEd Tanous { 1245*45ca1b86SEd Tanous return; 1246*45ca1b86SEd Tanous } 12477e860f15SJohn Edward Broadbent std::string certFileBody = 12487e860f15SJohn Edward Broadbent getCertificateFromReqBody(asyncResp, req); 1249a08752f5SZbigniew Kurzynski 1250a08752f5SZbigniew Kurzynski if (certFileBody.empty()) 1251a08752f5SZbigniew Kurzynski { 12520fda0f12SGeorge Liu BMCWEB_LOG_ERROR << "Cannot get certificate from request body."; 1253a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 1254a08752f5SZbigniew Kurzynski return; 1255a08752f5SZbigniew Kurzynski } 1256a08752f5SZbigniew Kurzynski 1257a08752f5SZbigniew Kurzynski std::shared_ptr<CertificateFile> certFile = 1258a08752f5SZbigniew Kurzynski std::make_shared<CertificateFile>(certFileBody); 1259cfcd5f6bSMarri Devender Rao crow::connections::systemBus->async_method_call( 1260656ec7e3SZbigniew Kurzynski [asyncResp, certFile](const boost::system::error_code ec, 1261656ec7e3SZbigniew Kurzynski const std::string& objectPath) { 1262cfcd5f6bSMarri Devender Rao if (ec) 1263cfcd5f6bSMarri Devender Rao { 1264cfcd5f6bSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 1265cfcd5f6bSMarri Devender Rao messages::internalError(asyncResp->res); 1266cfcd5f6bSMarri Devender Rao return; 1267cfcd5f6bSMarri Devender Rao } 1268656ec7e3SZbigniew Kurzynski long certId = getIDFromURL(objectPath); 1269656ec7e3SZbigniew Kurzynski if (certId < 0) 1270656ec7e3SZbigniew Kurzynski { 1271656ec7e3SZbigniew Kurzynski BMCWEB_LOG_ERROR << "Invalid objectPath value" 1272656ec7e3SZbigniew Kurzynski << objectPath; 1273656ec7e3SZbigniew Kurzynski messages::internalError(asyncResp->res); 1274656ec7e3SZbigniew Kurzynski return; 1275656ec7e3SZbigniew Kurzynski } 12760fda0f12SGeorge Liu std::string certURL = 12770fda0f12SGeorge Liu "/redfish/v1/Managers/bmc/Truststore/Certificates/" + 1278cfcd5f6bSMarri Devender Rao std::to_string(certId); 1279656ec7e3SZbigniew Kurzynski 12807e860f15SJohn Edward Broadbent getCertificateProperties( 12817e860f15SJohn Edward Broadbent asyncResp, objectPath, certs::authorityServiceName, 12827e860f15SJohn Edward Broadbent certId, certURL, "TrustStore Certificate"); 12830fda0f12SGeorge Liu BMCWEB_LOG_DEBUG << "TrustStore certificate install file=" 1284cfcd5f6bSMarri Devender Rao << certFile->getCertFilePath(); 1285cfcd5f6bSMarri Devender Rao }, 1286cfcd5f6bSMarri Devender Rao certs::authorityServiceName, certs::authorityObjectPath, 12870fda0f12SGeorge Liu certs::certInstallIntf, "Install", certFile->getCertFilePath()); 12887e860f15SJohn Edward Broadbent }); 12897e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificateCollection 1290cfcd5f6bSMarri Devender Rao 1291cfcd5f6bSMarri Devender Rao /** 1292cfcd5f6bSMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 1293cfcd5f6bSMarri Devender Rao * of a component, account or service. 1294cfcd5f6bSMarri Devender Rao */ 12957e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificate(App& app) 1296cfcd5f6bSMarri Devender Rao { 12977e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/") 1298ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 12997e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 1300*45ca1b86SEd Tanous [&app](const crow::Request& req, 13017e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 13027e860f15SJohn Edward Broadbent const std::string&) { 1303*45ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 1304*45ca1b86SEd Tanous { 1305*45ca1b86SEd Tanous return; 1306*45ca1b86SEd Tanous } 1307cfcd5f6bSMarri Devender Rao long id = getIDFromURL(req.url); 1308cfcd5f6bSMarri Devender Rao if (id < 0) 1309cfcd5f6bSMarri Devender Rao { 1310cfcd5f6bSMarri Devender Rao BMCWEB_LOG_ERROR << "Invalid url value" << req.url; 1311cfcd5f6bSMarri Devender Rao messages::internalError(asyncResp->res); 1312cfcd5f6bSMarri Devender Rao return; 1313cfcd5f6bSMarri Devender Rao } 1314cfcd5f6bSMarri Devender Rao BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doGet ID=" 1315cfcd5f6bSMarri Devender Rao << std::to_string(id); 1316cfcd5f6bSMarri Devender Rao std::string certURL = 1317cfcd5f6bSMarri Devender Rao "/redfish/v1/Managers/bmc/Truststore/Certificates/" + 1318cfcd5f6bSMarri Devender Rao std::to_string(id); 1319cfcd5f6bSMarri Devender Rao std::string objectPath = certs::authorityObjectPath; 1320cfcd5f6bSMarri Devender Rao objectPath += "/"; 1321cfcd5f6bSMarri Devender Rao objectPath += std::to_string(id); 1322cfcd5f6bSMarri Devender Rao getCertificateProperties(asyncResp, objectPath, 13237e860f15SJohn Edward Broadbent certs::authorityServiceName, id, 13247e860f15SJohn Edward Broadbent certURL, "TrustStore Certificate"); 13257e860f15SJohn Edward Broadbent }); 132607a60299SZbigniew Kurzynski 13277e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/") 1328ed398213SEd Tanous .privileges(redfish::privileges::deleteCertificate) 13297e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::delete_)( 1330*45ca1b86SEd Tanous [&app](const crow::Request& req, 13317e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 13327e860f15SJohn Edward Broadbent const std::string& param) { 1333*45ca1b86SEd Tanous if (!redfish::setUpRedfishRoute(app, req, asyncResp->res)) 1334*45ca1b86SEd Tanous { 1335*45ca1b86SEd Tanous return; 1336*45ca1b86SEd Tanous } 13377e860f15SJohn Edward Broadbent if (param.empty()) 133807a60299SZbigniew Kurzynski { 133907a60299SZbigniew Kurzynski messages::internalError(asyncResp->res); 134007a60299SZbigniew Kurzynski return; 134107a60299SZbigniew Kurzynski } 134207a60299SZbigniew Kurzynski 134307a60299SZbigniew Kurzynski long id = getIDFromURL(req.url); 134407a60299SZbigniew Kurzynski if (id < 0) 134507a60299SZbigniew Kurzynski { 134607a60299SZbigniew Kurzynski BMCWEB_LOG_ERROR << "Invalid url value: " << req.url; 13477e860f15SJohn Edward Broadbent messages::resourceNotFound(asyncResp->res, 13487e860f15SJohn Edward Broadbent "TrustStore Certificate", 134907a60299SZbigniew Kurzynski std::string(req.url)); 135007a60299SZbigniew Kurzynski return; 135107a60299SZbigniew Kurzynski } 135207a60299SZbigniew Kurzynski BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doDelete ID=" 135307a60299SZbigniew Kurzynski << std::to_string(id); 135407a60299SZbigniew Kurzynski std::string certPath = certs::authorityObjectPath; 135507a60299SZbigniew Kurzynski certPath += "/"; 135607a60299SZbigniew Kurzynski certPath += std::to_string(id); 135707a60299SZbigniew Kurzynski 135807a60299SZbigniew Kurzynski crow::connections::systemBus->async_method_call( 135907a60299SZbigniew Kurzynski [asyncResp, id](const boost::system::error_code ec) { 136007a60299SZbigniew Kurzynski if (ec) 136107a60299SZbigniew Kurzynski { 136207a60299SZbigniew Kurzynski messages::resourceNotFound(asyncResp->res, 136307a60299SZbigniew Kurzynski "TrustStore Certificate", 136407a60299SZbigniew Kurzynski std::to_string(id)); 136507a60299SZbigniew Kurzynski return; 136607a60299SZbigniew Kurzynski } 136707a60299SZbigniew Kurzynski BMCWEB_LOG_INFO << "Certificate deleted"; 13687e860f15SJohn Edward Broadbent asyncResp->res.result( 13697e860f15SJohn Edward Broadbent boost::beast::http::status::no_content); 137007a60299SZbigniew Kurzynski }, 137107a60299SZbigniew Kurzynski certs::authorityServiceName, certPath, certs::objDeleteIntf, 137207a60299SZbigniew Kurzynski "Delete"); 13737e860f15SJohn Edward Broadbent }); 13747e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificate 13755968caeeSMarri Devender Rao } // namespace redfish 1376