15968caeeSMarri Devender Rao #pragma once 25968caeeSMarri Devender Rao 3*7e860f15SJohn Edward Broadbent #include <app.hpp> 4e6604b11SIwona Klimaszewska #include <boost/convert.hpp> 5e6604b11SIwona Klimaszewska #include <boost/convert/strtol.hpp> 61214b7e7SGunnar Mills 75968caeeSMarri Devender Rao #include <variant> 85968caeeSMarri Devender Rao namespace redfish 95968caeeSMarri Devender Rao { 105968caeeSMarri Devender Rao namespace certs 115968caeeSMarri Devender Rao { 125968caeeSMarri Devender Rao constexpr char const* httpsObjectPath = 135968caeeSMarri Devender Rao "/xyz/openbmc_project/certs/server/https"; 145968caeeSMarri Devender Rao constexpr char const* certInstallIntf = "xyz.openbmc_project.Certs.Install"; 155968caeeSMarri Devender Rao constexpr char const* certReplaceIntf = "xyz.openbmc_project.Certs.Replace"; 1607a60299SZbigniew Kurzynski constexpr char const* objDeleteIntf = "xyz.openbmc_project.Object.Delete"; 175968caeeSMarri Devender Rao constexpr char const* certPropIntf = "xyz.openbmc_project.Certs.Certificate"; 185968caeeSMarri Devender Rao constexpr char const* dbusPropIntf = "org.freedesktop.DBus.Properties"; 195968caeeSMarri Devender Rao constexpr char const* dbusObjManagerIntf = "org.freedesktop.DBus.ObjectManager"; 2037cce918SMarri Devender Rao constexpr char const* ldapObjectPath = "/xyz/openbmc_project/certs/client/ldap"; 2137cce918SMarri Devender Rao constexpr char const* httpsServiceName = 2237cce918SMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Server.Https"; 2337cce918SMarri Devender Rao constexpr char const* ldapServiceName = 2437cce918SMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Client.Ldap"; 25cfcd5f6bSMarri Devender Rao constexpr char const* authorityServiceName = 26cfcd5f6bSMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Authority.Ldap"; 27cfcd5f6bSMarri Devender Rao constexpr char const* authorityObjectPath = 28cfcd5f6bSMarri Devender Rao "/xyz/openbmc_project/certs/authority/ldap"; 295968caeeSMarri Devender Rao } // namespace certs 305968caeeSMarri Devender Rao 315968caeeSMarri Devender Rao /** 325968caeeSMarri Devender Rao * The Certificate schema defines a Certificate Service which represents the 335968caeeSMarri Devender Rao * actions available to manage certificates and links to where certificates 345968caeeSMarri Devender Rao * are installed. 355968caeeSMarri Devender Rao */ 36*7e860f15SJohn Edward Broadbent 375968caeeSMarri Devender Rao // TODO: Issue#61 No entries are available for Certificate 384e0453b1SGunnar Mills // service at https://www.dmtf.org/standards/redfish 395968caeeSMarri Devender Rao // "redfish standard registries". Need to modify after DMTF 405968caeeSMarri Devender Rao // publish Privilege details for certificate service 415968caeeSMarri Devender Rao 42*7e860f15SJohn Edward Broadbent inline void requestRoutesCertificateService(App& app) 435968caeeSMarri Devender Rao { 44*7e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/") 45*7e860f15SJohn Edward Broadbent .privileges({"Login"}) 46*7e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 47*7e860f15SJohn Edward Broadbent [](const crow::Request&, 48*7e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 498d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 50*7e860f15SJohn Edward Broadbent {"@odata.type", 51*7e860f15SJohn Edward Broadbent "#CertificateService.v1_0_0.CertificateService"}, 525968caeeSMarri Devender Rao {"@odata.id", "/redfish/v1/CertificateService"}, 535968caeeSMarri Devender Rao {"Id", "CertificateService"}, 545968caeeSMarri Devender Rao {"Name", "Certificate Service"}, 55*7e860f15SJohn Edward Broadbent {"Description", 56*7e860f15SJohn Edward Broadbent "Actions available to manage certificates"}}; 578d1b46d7Szhanghch05 asyncResp->res.jsonValue["CertificateLocations"] = { 585968caeeSMarri Devender Rao {"@odata.id", 595968caeeSMarri Devender Rao "/redfish/v1/CertificateService/CertificateLocations"}}; 608d1b46d7Szhanghch05 asyncResp->res 61*7e860f15SJohn Edward Broadbent .jsonValue["Actions"] 62*7e860f15SJohn Edward Broadbent ["#CertificateService.ReplaceCertificate"] = { 635968caeeSMarri Devender Rao {"target", "/redfish/v1/CertificateService/Actions/" 645968caeeSMarri Devender Rao "CertificateService.ReplaceCertificate"}, 655968caeeSMarri Devender Rao {"CertificateType@Redfish.AllowableValues", {"PEM"}}}; 66*7e860f15SJohn Edward Broadbent asyncResp->res 67*7e860f15SJohn Edward Broadbent .jsonValue["Actions"]["#CertificateService.GenerateCSR"] = { 68*7e860f15SJohn Edward Broadbent {"target", "/redfish/v1/CertificateService/Actions/" 6930215816SMarri Devender Rao "CertificateService.GenerateCSR"}}; 70*7e860f15SJohn Edward Broadbent }); 71*7e860f15SJohn Edward Broadbent } // requestRoutesCertificateService 7237cce918SMarri Devender Rao 735968caeeSMarri Devender Rao /** 745968caeeSMarri Devender Rao * @brief Find the ID specified in the URL 755968caeeSMarri Devender Rao * Finds the numbers specified after the last "/" in the URL and returns. 765968caeeSMarri Devender Rao * @param[in] path URL 775968caeeSMarri Devender Rao * @return -1 on failure and number on success 785968caeeSMarri Devender Rao */ 7923a21a1cSEd Tanous inline long getIDFromURL(const std::string_view url) 805968caeeSMarri Devender Rao { 81f23b7296SEd Tanous std::size_t found = url.rfind('/'); 825968caeeSMarri Devender Rao if (found == std::string::npos) 835968caeeSMarri Devender Rao { 845968caeeSMarri Devender Rao return -1; 855968caeeSMarri Devender Rao } 86e6604b11SIwona Klimaszewska 875968caeeSMarri Devender Rao if ((found + 1) < url.length()) 885968caeeSMarri Devender Rao { 895968caeeSMarri Devender Rao std::string_view str = url.substr(found + 1); 90e6604b11SIwona Klimaszewska 91e6604b11SIwona Klimaszewska return boost::convert<long>(str, boost::cnv::strtol()).value_or(-1); 925968caeeSMarri Devender Rao } 93e6604b11SIwona Klimaszewska 945968caeeSMarri Devender Rao return -1; 955968caeeSMarri Devender Rao } 965968caeeSMarri Devender Rao 978d1b46d7Szhanghch05 inline std::string getCertificateFromReqBody( 988d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 9958eb238fSKowalski, Kamil const crow::Request& req) 10058eb238fSKowalski, Kamil { 10158eb238fSKowalski, Kamil nlohmann::json reqJson = nlohmann::json::parse(req.body, nullptr, false); 10258eb238fSKowalski, Kamil 10358eb238fSKowalski, Kamil if (reqJson.is_discarded()) 10458eb238fSKowalski, Kamil { 10558eb238fSKowalski, Kamil // We did not receive JSON request, proceed as it is RAW data 10658eb238fSKowalski, Kamil return req.body; 10758eb238fSKowalski, Kamil } 10858eb238fSKowalski, Kamil 10958eb238fSKowalski, Kamil std::string certificate; 11058eb238fSKowalski, Kamil std::optional<std::string> certificateType = "PEM"; 11158eb238fSKowalski, Kamil 11258eb238fSKowalski, Kamil if (!json_util::readJson(reqJson, asyncResp->res, "CertificateString", 11358eb238fSKowalski, Kamil certificate, "CertificateType", certificateType)) 11458eb238fSKowalski, Kamil { 11558eb238fSKowalski, Kamil BMCWEB_LOG_ERROR << "Required parameters are missing"; 11658eb238fSKowalski, Kamil messages::internalError(asyncResp->res); 11758eb238fSKowalski, Kamil return std::string(); 11858eb238fSKowalski, Kamil } 11958eb238fSKowalski, Kamil 12058eb238fSKowalski, Kamil if (*certificateType != "PEM") 12158eb238fSKowalski, Kamil { 12258eb238fSKowalski, Kamil messages::propertyValueNotInList(asyncResp->res, *certificateType, 12358eb238fSKowalski, Kamil "CertificateType"); 12458eb238fSKowalski, Kamil return std::string(); 12558eb238fSKowalski, Kamil } 12658eb238fSKowalski, Kamil 12758eb238fSKowalski, Kamil return certificate; 12858eb238fSKowalski, Kamil } 12958eb238fSKowalski, Kamil 1305968caeeSMarri Devender Rao /** 1315968caeeSMarri Devender Rao * Class to create a temporary certificate file for uploading to system 1325968caeeSMarri Devender Rao */ 1335968caeeSMarri Devender Rao class CertificateFile 1345968caeeSMarri Devender Rao { 1355968caeeSMarri Devender Rao public: 1365968caeeSMarri Devender Rao CertificateFile() = delete; 1375968caeeSMarri Devender Rao CertificateFile(const CertificateFile&) = delete; 1385968caeeSMarri Devender Rao CertificateFile& operator=(const CertificateFile&) = delete; 1395968caeeSMarri Devender Rao CertificateFile(CertificateFile&&) = delete; 1405968caeeSMarri Devender Rao CertificateFile& operator=(CertificateFile&&) = delete; 1415968caeeSMarri Devender Rao CertificateFile(const std::string& certString) 1425968caeeSMarri Devender Rao { 14372d52d25SEd Tanous std::array<char, 18> dirTemplate = {'/', 't', 'm', 'p', '/', 'C', 1445207438cSEd Tanous 'e', 'r', 't', 's', '.', 'X', 1455207438cSEd Tanous 'X', 'X', 'X', 'X', 'X', '\0'}; 1465207438cSEd Tanous char* tempDirectory = mkdtemp(dirTemplate.data()); 1475968caeeSMarri Devender Rao if (tempDirectory) 1485968caeeSMarri Devender Rao { 1495968caeeSMarri Devender Rao certDirectory = tempDirectory; 1505968caeeSMarri Devender Rao certificateFile = certDirectory / "cert.pem"; 1515968caeeSMarri Devender Rao std::ofstream out(certificateFile, std::ofstream::out | 1525968caeeSMarri Devender Rao std::ofstream::binary | 1535968caeeSMarri Devender Rao std::ofstream::trunc); 1545968caeeSMarri Devender Rao out << certString; 1555968caeeSMarri Devender Rao out.close(); 1565968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "Creating certificate file" << certificateFile; 1575968caeeSMarri Devender Rao } 1585968caeeSMarri Devender Rao } 1595968caeeSMarri Devender Rao ~CertificateFile() 1605968caeeSMarri Devender Rao { 1615968caeeSMarri Devender Rao if (std::filesystem::exists(certDirectory)) 1625968caeeSMarri Devender Rao { 1635968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "Removing certificate file" << certificateFile; 16423a21a1cSEd Tanous std::error_code ec; 16523a21a1cSEd Tanous std::filesystem::remove_all(certDirectory, ec); 16623a21a1cSEd Tanous if (ec) 1675968caeeSMarri Devender Rao { 1685968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Failed to remove temp directory" 1695968caeeSMarri Devender Rao << certDirectory; 1705968caeeSMarri Devender Rao } 1715968caeeSMarri Devender Rao } 1725968caeeSMarri Devender Rao } 1735968caeeSMarri Devender Rao std::string getCertFilePath() 1745968caeeSMarri Devender Rao { 1755968caeeSMarri Devender Rao return certificateFile; 1765968caeeSMarri Devender Rao } 1775968caeeSMarri Devender Rao 1785968caeeSMarri Devender Rao private: 1795968caeeSMarri Devender Rao std::filesystem::path certificateFile; 1805968caeeSMarri Devender Rao std::filesystem::path certDirectory; 1815968caeeSMarri Devender Rao }; 1825968caeeSMarri Devender Rao 18330215816SMarri Devender Rao static std::unique_ptr<sdbusplus::bus::match::match> csrMatcher; 18430215816SMarri Devender Rao /** 18530215816SMarri Devender Rao * @brief Read data from CSR D-bus object and set to response 18630215816SMarri Devender Rao * 18730215816SMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 18830215816SMarri Devender Rao * @param[in] certURI Link to certifiate collection URI 18930215816SMarri Devender Rao * @param[in] service D-Bus service name 19030215816SMarri Devender Rao * @param[in] certObjPath certificate D-Bus object path 19130215816SMarri Devender Rao * @param[in] csrObjPath CSR D-Bus object path 19230215816SMarri Devender Rao * @return None 19330215816SMarri Devender Rao */ 1948d1b46d7Szhanghch05 static void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 19530215816SMarri Devender Rao const std::string& certURI, const std::string& service, 19630215816SMarri Devender Rao const std::string& certObjPath, 19730215816SMarri Devender Rao const std::string& csrObjPath) 19830215816SMarri Devender Rao { 19930215816SMarri Devender Rao BMCWEB_LOG_DEBUG << "getCSR CertObjectPath" << certObjPath 20030215816SMarri Devender Rao << " CSRObjectPath=" << csrObjPath 20130215816SMarri Devender Rao << " service=" << service; 20230215816SMarri Devender Rao crow::connections::systemBus->async_method_call( 20330215816SMarri Devender Rao [asyncResp, certURI](const boost::system::error_code ec, 20430215816SMarri Devender Rao const std::string& csr) { 20530215816SMarri Devender Rao if (ec) 20630215816SMarri Devender Rao { 20730215816SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 20830215816SMarri Devender Rao messages::internalError(asyncResp->res); 20930215816SMarri Devender Rao return; 21030215816SMarri Devender Rao } 21130215816SMarri Devender Rao if (csr.empty()) 21230215816SMarri Devender Rao { 21330215816SMarri Devender Rao BMCWEB_LOG_ERROR << "CSR read is empty"; 21430215816SMarri Devender Rao messages::internalError(asyncResp->res); 21530215816SMarri Devender Rao return; 21630215816SMarri Devender Rao } 21730215816SMarri Devender Rao asyncResp->res.jsonValue["CSRString"] = csr; 21830215816SMarri Devender Rao asyncResp->res.jsonValue["CertificateCollection"] = { 21930215816SMarri Devender Rao {"@odata.id", certURI}}; 22030215816SMarri Devender Rao }, 22130215816SMarri Devender Rao service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR"); 22230215816SMarri Devender Rao } 22330215816SMarri Devender Rao 22430215816SMarri Devender Rao /** 22530215816SMarri Devender Rao * Action to Generate CSR 22630215816SMarri Devender Rao */ 227*7e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionGenerateCSR(App& app) 22830215816SMarri Devender Rao { 229*7e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/Actions/" 23030215816SMarri Devender Rao "CertificateService.GenerateCSR/") 231*7e860f15SJohn Edward Broadbent .privileges({"ConfigureComponents"}) 232*7e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 233*7e860f15SJohn Edward Broadbent [](const crow::Request& req, 234*7e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 2352c70f800SEd Tanous static const int rsaKeyBitLength = 2048; 2368d1b46d7Szhanghch05 23730215816SMarri Devender Rao // Required parameters 23830215816SMarri Devender Rao std::string city; 23930215816SMarri Devender Rao std::string commonName; 24030215816SMarri Devender Rao std::string country; 24130215816SMarri Devender Rao std::string organization; 24230215816SMarri Devender Rao std::string organizationalUnit; 24330215816SMarri Devender Rao std::string state; 24430215816SMarri Devender Rao nlohmann::json certificateCollection; 24530215816SMarri Devender Rao 24630215816SMarri Devender Rao // Optional parameters 24730215816SMarri Devender Rao std::optional<std::vector<std::string>> optAlternativeNames = 24830215816SMarri Devender Rao std::vector<std::string>(); 24930215816SMarri Devender Rao std::optional<std::string> optContactPerson = ""; 25030215816SMarri Devender Rao std::optional<std::string> optChallengePassword = ""; 25130215816SMarri Devender Rao std::optional<std::string> optEmail = ""; 25230215816SMarri Devender Rao std::optional<std::string> optGivenName = ""; 25330215816SMarri Devender Rao std::optional<std::string> optInitials = ""; 2542c70f800SEd Tanous std::optional<int64_t> optKeyBitLength = rsaKeyBitLength; 255aaf3206fSVernon Mauery std::optional<std::string> optKeyCurveId = "secp384r1"; 25630215816SMarri Devender Rao std::optional<std::string> optKeyPairAlgorithm = "EC"; 25730215816SMarri Devender Rao std::optional<std::vector<std::string>> optKeyUsage = 25830215816SMarri Devender Rao std::vector<std::string>(); 25930215816SMarri Devender Rao std::optional<std::string> optSurname = ""; 26030215816SMarri Devender Rao std::optional<std::string> optUnstructuredName = ""; 26130215816SMarri Devender Rao if (!json_util::readJson( 262*7e860f15SJohn Edward Broadbent req, asyncResp->res, "City", city, "CommonName", 263*7e860f15SJohn Edward Broadbent commonName, "ContactPerson", optContactPerson, 264*7e860f15SJohn Edward Broadbent "Country", country, "Organization", organization, 265*7e860f15SJohn Edward Broadbent "OrganizationalUnit", organizationalUnit, "State", 266*7e860f15SJohn Edward Broadbent state, "CertificateCollection", certificateCollection, 267*7e860f15SJohn Edward Broadbent "AlternativeNames", optAlternativeNames, 268*7e860f15SJohn Edward Broadbent "ChallengePassword", optChallengePassword, "Email", 269*7e860f15SJohn Edward Broadbent optEmail, "GivenName", optGivenName, "Initials", 270*7e860f15SJohn Edward Broadbent optInitials, "KeyBitLength", optKeyBitLength, 271*7e860f15SJohn Edward Broadbent "KeyCurveId", optKeyCurveId, "KeyPairAlgorithm", 272*7e860f15SJohn Edward Broadbent optKeyPairAlgorithm, "KeyUsage", optKeyUsage, "Surname", 273*7e860f15SJohn Edward Broadbent optSurname, "UnstructuredName", optUnstructuredName)) 27430215816SMarri Devender Rao { 27530215816SMarri Devender Rao return; 27630215816SMarri Devender Rao } 27730215816SMarri Devender Rao 27830215816SMarri Devender Rao // bmcweb has no way to store or decode a private key challenge 279*7e860f15SJohn Edward Broadbent // password, which will likely cause bmcweb to crash on startup 280*7e860f15SJohn Edward Broadbent // if this is not set on a post so not allowing the user to set 281*7e860f15SJohn Edward Broadbent // value 28230215816SMarri Devender Rao if (*optChallengePassword != "") 28330215816SMarri Devender Rao { 284*7e860f15SJohn Edward Broadbent messages::actionParameterNotSupported( 285*7e860f15SJohn Edward Broadbent asyncResp->res, "GenerateCSR", "ChallengePassword"); 28630215816SMarri Devender Rao return; 28730215816SMarri Devender Rao } 28830215816SMarri Devender Rao 28930215816SMarri Devender Rao std::string certURI; 290*7e860f15SJohn Edward Broadbent if (!redfish::json_util::readJson(certificateCollection, 291*7e860f15SJohn Edward Broadbent asyncResp->res, "@odata.id", 292*7e860f15SJohn Edward Broadbent certURI)) 29330215816SMarri Devender Rao { 29430215816SMarri Devender Rao return; 29530215816SMarri Devender Rao } 29630215816SMarri Devender Rao 29730215816SMarri Devender Rao std::string objectPath; 29830215816SMarri Devender Rao std::string service; 299*7e860f15SJohn Edward Broadbent if (boost::starts_with(certURI, 300*7e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc/" 301*7e860f15SJohn Edward Broadbent "NetworkProtocol/HTTPS/Certificates")) 30230215816SMarri Devender Rao { 30330215816SMarri Devender Rao objectPath = certs::httpsObjectPath; 30430215816SMarri Devender Rao service = certs::httpsServiceName; 30530215816SMarri Devender Rao } 3063b7f0149SMarri Devender Rao else if (boost::starts_with( 307*7e860f15SJohn Edward Broadbent certURI, 308*7e860f15SJohn Edward Broadbent "/redfish/v1/AccountService/LDAP/Certificates")) 3093b7f0149SMarri Devender Rao { 3103b7f0149SMarri Devender Rao objectPath = certs::ldapObjectPath; 3113b7f0149SMarri Devender Rao service = certs::ldapServiceName; 3123b7f0149SMarri Devender Rao } 31330215816SMarri Devender Rao else 31430215816SMarri Devender Rao { 31530215816SMarri Devender Rao messages::actionParameterNotSupported( 31630215816SMarri Devender Rao asyncResp->res, "CertificateCollection", "GenerateCSR"); 31730215816SMarri Devender Rao return; 31830215816SMarri Devender Rao } 31930215816SMarri Devender Rao 32030215816SMarri Devender Rao // supporting only EC and RSA algorithm 321*7e860f15SJohn Edward Broadbent if (*optKeyPairAlgorithm != "EC" && 322*7e860f15SJohn Edward Broadbent *optKeyPairAlgorithm != "RSA") 32330215816SMarri Devender Rao { 32430215816SMarri Devender Rao messages::actionParameterNotSupported( 32530215816SMarri Devender Rao asyncResp->res, "KeyPairAlgorithm", "GenerateCSR"); 32630215816SMarri Devender Rao return; 32730215816SMarri Devender Rao } 32830215816SMarri Devender Rao 329*7e860f15SJohn Edward Broadbent // supporting only 2048 key bit length for RSA algorithm due to 330*7e860f15SJohn Edward Broadbent // time consumed in generating private key 33130215816SMarri Devender Rao if (*optKeyPairAlgorithm == "RSA" && 3322c70f800SEd Tanous *optKeyBitLength != rsaKeyBitLength) 33330215816SMarri Devender Rao { 334*7e860f15SJohn Edward Broadbent messages::propertyValueNotInList( 335*7e860f15SJohn Edward Broadbent asyncResp->res, std::to_string(*optKeyBitLength), 33630215816SMarri Devender Rao "KeyBitLength"); 33730215816SMarri Devender Rao return; 33830215816SMarri Devender Rao } 33930215816SMarri Devender Rao 34030215816SMarri Devender Rao // validate KeyUsage supporting only 1 type based on URL 341*7e860f15SJohn Edward Broadbent if (boost::starts_with(certURI, 342*7e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc/" 343*7e860f15SJohn Edward Broadbent "NetworkProtocol/HTTPS/Certificates")) 34430215816SMarri Devender Rao { 34530215816SMarri Devender Rao if (optKeyUsage->size() == 0) 34630215816SMarri Devender Rao { 34730215816SMarri Devender Rao optKeyUsage->push_back("ServerAuthentication"); 34830215816SMarri Devender Rao } 34930215816SMarri Devender Rao else if (optKeyUsage->size() == 1) 35030215816SMarri Devender Rao { 35130215816SMarri Devender Rao if ((*optKeyUsage)[0] != "ServerAuthentication") 35230215816SMarri Devender Rao { 35330215816SMarri Devender Rao messages::propertyValueNotInList( 35430215816SMarri Devender Rao asyncResp->res, (*optKeyUsage)[0], "KeyUsage"); 35530215816SMarri Devender Rao return; 35630215816SMarri Devender Rao } 35730215816SMarri Devender Rao } 35830215816SMarri Devender Rao else 35930215816SMarri Devender Rao { 36030215816SMarri Devender Rao messages::actionParameterNotSupported( 36130215816SMarri Devender Rao asyncResp->res, "KeyUsage", "GenerateCSR"); 36230215816SMarri Devender Rao return; 36330215816SMarri Devender Rao } 36430215816SMarri Devender Rao } 3653b7f0149SMarri Devender Rao else if (boost::starts_with( 366*7e860f15SJohn Edward Broadbent certURI, 367*7e860f15SJohn Edward Broadbent "/redfish/v1/AccountService/LDAP/Certificates")) 3683b7f0149SMarri Devender Rao { 3693b7f0149SMarri Devender Rao if (optKeyUsage->size() == 0) 3703b7f0149SMarri Devender Rao { 3713b7f0149SMarri Devender Rao optKeyUsage->push_back("ClientAuthentication"); 3723b7f0149SMarri Devender Rao } 3733b7f0149SMarri Devender Rao else if (optKeyUsage->size() == 1) 3743b7f0149SMarri Devender Rao { 3753b7f0149SMarri Devender Rao if ((*optKeyUsage)[0] != "ClientAuthentication") 3763b7f0149SMarri Devender Rao { 3773b7f0149SMarri Devender Rao messages::propertyValueNotInList( 3783b7f0149SMarri Devender Rao asyncResp->res, (*optKeyUsage)[0], "KeyUsage"); 3793b7f0149SMarri Devender Rao return; 3803b7f0149SMarri Devender Rao } 3813b7f0149SMarri Devender Rao } 3823b7f0149SMarri Devender Rao else 3833b7f0149SMarri Devender Rao { 3843b7f0149SMarri Devender Rao messages::actionParameterNotSupported( 3853b7f0149SMarri Devender Rao asyncResp->res, "KeyUsage", "GenerateCSR"); 3863b7f0149SMarri Devender Rao return; 3873b7f0149SMarri Devender Rao } 3883b7f0149SMarri Devender Rao } 38930215816SMarri Devender Rao 390*7e860f15SJohn Edward Broadbent // Only allow one CSR matcher at a time so setting retry 391*7e860f15SJohn Edward Broadbent // time-out and timer expiry to 10 seconds for now. 3922c70f800SEd Tanous static const int timeOut = 10; 39330215816SMarri Devender Rao if (csrMatcher) 39430215816SMarri Devender Rao { 395*7e860f15SJohn Edward Broadbent messages::serviceTemporarilyUnavailable( 396*7e860f15SJohn Edward Broadbent asyncResp->res, std::to_string(timeOut)); 39730215816SMarri Devender Rao return; 39830215816SMarri Devender Rao } 39930215816SMarri Devender Rao 40030215816SMarri Devender Rao // Make this static so it survives outside this method 40130215816SMarri Devender Rao static boost::asio::steady_timer timeout(*req.ioService); 4022c70f800SEd Tanous timeout.expires_after(std::chrono::seconds(timeOut)); 403*7e860f15SJohn Edward Broadbent timeout.async_wait([asyncResp]( 404*7e860f15SJohn Edward Broadbent const boost::system::error_code& ec) { 40530215816SMarri Devender Rao csrMatcher = nullptr; 40630215816SMarri Devender Rao if (ec) 40730215816SMarri Devender Rao { 408*7e860f15SJohn Edward Broadbent // operation_aborted is expected if timer is canceled 409*7e860f15SJohn Edward Broadbent // before completion. 41030215816SMarri Devender Rao if (ec != boost::asio::error::operation_aborted) 41130215816SMarri Devender Rao { 41230215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Async_wait failed " << ec; 41330215816SMarri Devender Rao } 41430215816SMarri Devender Rao return; 41530215816SMarri Devender Rao } 41630215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Timed out waiting for Generating CSR"; 41730215816SMarri Devender Rao messages::internalError(asyncResp->res); 41830215816SMarri Devender Rao }); 41930215816SMarri Devender Rao 42030215816SMarri Devender Rao // create a matcher to wait on CSR object 42130215816SMarri Devender Rao BMCWEB_LOG_DEBUG << "create matcher with path " << objectPath; 422*7e860f15SJohn Edward Broadbent std::string match( 423*7e860f15SJohn Edward Broadbent "type='signal'," 42430215816SMarri Devender Rao "interface='org.freedesktop.DBus.ObjectManager'," 42530215816SMarri Devender Rao "path='" + 42630215816SMarri Devender Rao objectPath + 42730215816SMarri Devender Rao "'," 42830215816SMarri Devender Rao "member='InterfacesAdded'"); 42930215816SMarri Devender Rao csrMatcher = std::make_unique<sdbusplus::bus::match::match>( 43030215816SMarri Devender Rao *crow::connections::systemBus, match, 43130215816SMarri Devender Rao [asyncResp, service, objectPath, 43230215816SMarri Devender Rao certURI](sdbusplus::message::message& m) { 433271584abSEd Tanous timeout.cancel(); 43430215816SMarri Devender Rao if (m.is_method_error()) 43530215816SMarri Devender Rao { 43630215816SMarri Devender Rao BMCWEB_LOG_ERROR << "Dbus method error!!!"; 43730215816SMarri Devender Rao messages::internalError(asyncResp->res); 43830215816SMarri Devender Rao return; 43930215816SMarri Devender Rao } 44030215816SMarri Devender Rao std::vector<std::pair< 441*7e860f15SJohn Edward Broadbent std::string, 442*7e860f15SJohn Edward Broadbent std::vector<std::pair<std::string, 443*7e860f15SJohn Edward Broadbent std::variant<std::string>>>>> 44430215816SMarri Devender Rao interfacesProperties; 44530215816SMarri Devender Rao sdbusplus::message::object_path csrObjectPath; 44630215816SMarri Devender Rao m.read(csrObjectPath, interfacesProperties); 447*7e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG << "CSR object added" 448*7e860f15SJohn Edward Broadbent << csrObjectPath.str; 44930215816SMarri Devender Rao for (auto& interface : interfacesProperties) 45030215816SMarri Devender Rao { 451*7e860f15SJohn Edward Broadbent if (interface.first == 452*7e860f15SJohn Edward Broadbent "xyz.openbmc_project.Certs.CSR") 45330215816SMarri Devender Rao { 45430215816SMarri Devender Rao getCSR(asyncResp, certURI, service, objectPath, 45530215816SMarri Devender Rao csrObjectPath.str); 45630215816SMarri Devender Rao break; 45730215816SMarri Devender Rao } 45830215816SMarri Devender Rao } 45930215816SMarri Devender Rao }); 46030215816SMarri Devender Rao crow::connections::systemBus->async_method_call( 461271584abSEd Tanous [asyncResp](const boost::system::error_code& ec, 462cb13a392SEd Tanous const std::string&) { 46330215816SMarri Devender Rao if (ec) 46430215816SMarri Devender Rao { 465*7e860f15SJohn Edward Broadbent BMCWEB_LOG_ERROR << "DBUS response error: " 466*7e860f15SJohn Edward Broadbent << ec.message(); 46730215816SMarri Devender Rao messages::internalError(asyncResp->res); 46830215816SMarri Devender Rao return; 46930215816SMarri Devender Rao } 47030215816SMarri Devender Rao }, 47130215816SMarri Devender Rao service, objectPath, "xyz.openbmc_project.Certs.CSR.Create", 472*7e860f15SJohn Edward Broadbent "GenerateCSR", *optAlternativeNames, *optChallengePassword, 473*7e860f15SJohn Edward Broadbent city, commonName, *optContactPerson, country, *optEmail, 474*7e860f15SJohn Edward Broadbent *optGivenName, *optInitials, *optKeyBitLength, 475*7e860f15SJohn Edward Broadbent *optKeyCurveId, *optKeyPairAlgorithm, *optKeyUsage, 476*7e860f15SJohn Edward Broadbent organization, organizationalUnit, state, *optSurname, 477*7e860f15SJohn Edward Broadbent *optUnstructuredName); 478*7e860f15SJohn Edward Broadbent }); 479*7e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionGenerateCSR 48030215816SMarri Devender Rao 4815968caeeSMarri Devender Rao /** 4824e0453b1SGunnar Mills * @brief Parse and update Certificate Issue/Subject property 4835968caeeSMarri Devender Rao * 4845968caeeSMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 4855968caeeSMarri Devender Rao * @param[in] str Issuer/Subject value in key=value pairs 4865968caeeSMarri Devender Rao * @param[in] type Issuer/Subject 4875968caeeSMarri Devender Rao * @return None 4885968caeeSMarri Devender Rao */ 4895968caeeSMarri Devender Rao static void updateCertIssuerOrSubject(nlohmann::json& out, 4905968caeeSMarri Devender Rao const std::string_view value) 4915968caeeSMarri Devender Rao { 4925968caeeSMarri Devender Rao // example: O=openbmc-project.xyz,CN=localhost 4935968caeeSMarri Devender Rao std::string_view::iterator i = value.begin(); 4945968caeeSMarri Devender Rao while (i != value.end()) 4955968caeeSMarri Devender Rao { 4965968caeeSMarri Devender Rao std::string_view::iterator tokenBegin = i; 4975968caeeSMarri Devender Rao while (i != value.end() && *i != '=') 4985968caeeSMarri Devender Rao { 49917a897dfSManojkiran Eda ++i; 5005968caeeSMarri Devender Rao } 5015968caeeSMarri Devender Rao if (i == value.end()) 5025968caeeSMarri Devender Rao { 5035968caeeSMarri Devender Rao break; 5045968caeeSMarri Devender Rao } 505271584abSEd Tanous const std::string_view key(tokenBegin, 506271584abSEd Tanous static_cast<size_t>(i - tokenBegin)); 50717a897dfSManojkiran Eda ++i; 5085968caeeSMarri Devender Rao tokenBegin = i; 5095968caeeSMarri Devender Rao while (i != value.end() && *i != ',') 5105968caeeSMarri Devender Rao { 51117a897dfSManojkiran Eda ++i; 5125968caeeSMarri Devender Rao } 513271584abSEd Tanous const std::string_view val(tokenBegin, 514271584abSEd Tanous static_cast<size_t>(i - tokenBegin)); 5155968caeeSMarri Devender Rao if (key == "L") 5165968caeeSMarri Devender Rao { 5175968caeeSMarri Devender Rao out["City"] = val; 5185968caeeSMarri Devender Rao } 5195968caeeSMarri Devender Rao else if (key == "CN") 5205968caeeSMarri Devender Rao { 5215968caeeSMarri Devender Rao out["CommonName"] = val; 5225968caeeSMarri Devender Rao } 5235968caeeSMarri Devender Rao else if (key == "C") 5245968caeeSMarri Devender Rao { 5255968caeeSMarri Devender Rao out["Country"] = val; 5265968caeeSMarri Devender Rao } 5275968caeeSMarri Devender Rao else if (key == "O") 5285968caeeSMarri Devender Rao { 5295968caeeSMarri Devender Rao out["Organization"] = val; 5305968caeeSMarri Devender Rao } 5315968caeeSMarri Devender Rao else if (key == "OU") 5325968caeeSMarri Devender Rao { 5335968caeeSMarri Devender Rao out["OrganizationalUnit"] = val; 5345968caeeSMarri Devender Rao } 5355968caeeSMarri Devender Rao else if (key == "ST") 5365968caeeSMarri Devender Rao { 5375968caeeSMarri Devender Rao out["State"] = val; 5385968caeeSMarri Devender Rao } 5395968caeeSMarri Devender Rao // skip comma character 5405968caeeSMarri Devender Rao if (i != value.end()) 5415968caeeSMarri Devender Rao { 54217a897dfSManojkiran Eda ++i; 5435968caeeSMarri Devender Rao } 5445968caeeSMarri Devender Rao } 5455968caeeSMarri Devender Rao } 5465968caeeSMarri Devender Rao 5475968caeeSMarri Devender Rao /** 5485968caeeSMarri Devender Rao * @brief Retrieve the certificates properties and append to the response 5495968caeeSMarri Devender Rao * message 5505968caeeSMarri Devender Rao * 5515968caeeSMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 5525968caeeSMarri Devender Rao * @param[in] objectPath Path of the D-Bus service object 5535968caeeSMarri Devender Rao * @param[in] certId Id of the certificate 5545968caeeSMarri Devender Rao * @param[in] certURL URL of the certificate object 5555968caeeSMarri Devender Rao * @param[in] name name of the certificate 5565968caeeSMarri Devender Rao * @return None 5575968caeeSMarri Devender Rao */ 5585968caeeSMarri Devender Rao static void getCertificateProperties( 5598d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 5608d1b46d7Szhanghch05 const std::string& objectPath, const std::string& service, long certId, 5618d1b46d7Szhanghch05 const std::string& certURL, const std::string& name) 5625968caeeSMarri Devender Rao { 5635968caeeSMarri Devender Rao using PropertyType = 5645968caeeSMarri Devender Rao std::variant<std::string, uint64_t, std::vector<std::string>>; 5655968caeeSMarri Devender Rao using PropertiesMap = boost::container::flat_map<std::string, PropertyType>; 5665968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "getCertificateProperties Path=" << objectPath 5675968caeeSMarri Devender Rao << " certId=" << certId << " certURl=" << certURL; 5685968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 56937cce918SMarri Devender Rao [asyncResp, certURL, certId, name](const boost::system::error_code ec, 5705968caeeSMarri Devender Rao const PropertiesMap& properties) { 5715968caeeSMarri Devender Rao if (ec) 5725968caeeSMarri Devender Rao { 5735968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 5748aae75adSMarri Devender Rao messages::resourceNotFound(asyncResp->res, name, 5758aae75adSMarri Devender Rao std::to_string(certId)); 5765968caeeSMarri Devender Rao return; 5775968caeeSMarri Devender Rao } 5785968caeeSMarri Devender Rao asyncResp->res.jsonValue = { 5795968caeeSMarri Devender Rao {"@odata.id", certURL}, 5805968caeeSMarri Devender Rao {"@odata.type", "#Certificate.v1_0_0.Certificate"}, 5815968caeeSMarri Devender Rao {"Id", std::to_string(certId)}, 5825968caeeSMarri Devender Rao {"Name", name}, 5835968caeeSMarri Devender Rao {"Description", name}}; 5845968caeeSMarri Devender Rao for (const auto& property : properties) 5855968caeeSMarri Devender Rao { 5865968caeeSMarri Devender Rao if (property.first == "CertificateString") 5875968caeeSMarri Devender Rao { 5885968caeeSMarri Devender Rao asyncResp->res.jsonValue["CertificateString"] = ""; 5895968caeeSMarri Devender Rao const std::string* value = 5905968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 5915968caeeSMarri Devender Rao if (value) 5925968caeeSMarri Devender Rao { 59337cce918SMarri Devender Rao asyncResp->res.jsonValue["CertificateString"] = *value; 5945968caeeSMarri Devender Rao } 5955968caeeSMarri Devender Rao } 5965968caeeSMarri Devender Rao else if (property.first == "KeyUsage") 5975968caeeSMarri Devender Rao { 5985968caeeSMarri Devender Rao nlohmann::json& keyUsage = 5995968caeeSMarri Devender Rao asyncResp->res.jsonValue["KeyUsage"]; 6005968caeeSMarri Devender Rao keyUsage = nlohmann::json::array(); 6015968caeeSMarri Devender Rao const std::vector<std::string>* value = 60237cce918SMarri Devender Rao std::get_if<std::vector<std::string>>(&property.second); 6035968caeeSMarri Devender Rao if (value) 6045968caeeSMarri Devender Rao { 6055968caeeSMarri Devender Rao for (const std::string& usage : *value) 6065968caeeSMarri Devender Rao { 6075968caeeSMarri Devender Rao keyUsage.push_back(usage); 6085968caeeSMarri Devender Rao } 6095968caeeSMarri Devender Rao } 6105968caeeSMarri Devender Rao } 6115968caeeSMarri Devender Rao else if (property.first == "Issuer") 6125968caeeSMarri Devender Rao { 6135968caeeSMarri Devender Rao const std::string* value = 6145968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 6155968caeeSMarri Devender Rao if (value) 6165968caeeSMarri Devender Rao { 6175968caeeSMarri Devender Rao updateCertIssuerOrSubject( 6185968caeeSMarri Devender Rao asyncResp->res.jsonValue["Issuer"], *value); 6195968caeeSMarri Devender Rao } 6205968caeeSMarri Devender Rao } 6215968caeeSMarri Devender Rao else if (property.first == "Subject") 6225968caeeSMarri Devender Rao { 6235968caeeSMarri Devender Rao const std::string* value = 6245968caeeSMarri Devender Rao std::get_if<std::string>(&property.second); 6255968caeeSMarri Devender Rao if (value) 6265968caeeSMarri Devender Rao { 6275968caeeSMarri Devender Rao updateCertIssuerOrSubject( 62837cce918SMarri Devender Rao asyncResp->res.jsonValue["Subject"], *value); 6295968caeeSMarri Devender Rao } 6305968caeeSMarri Devender Rao } 6315968caeeSMarri Devender Rao else if (property.first == "ValidNotAfter") 6325968caeeSMarri Devender Rao { 6335968caeeSMarri Devender Rao const uint64_t* value = 6345968caeeSMarri Devender Rao std::get_if<uint64_t>(&property.second); 6355968caeeSMarri Devender Rao if (value) 6365968caeeSMarri Devender Rao { 63737cce918SMarri Devender Rao std::time_t time = static_cast<std::time_t>(*value); 6385968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotAfter"] = 6395968caeeSMarri Devender Rao crow::utility::getDateTime(time); 6405968caeeSMarri Devender Rao } 6415968caeeSMarri Devender Rao } 6425968caeeSMarri Devender Rao else if (property.first == "ValidNotBefore") 6435968caeeSMarri Devender Rao { 6445968caeeSMarri Devender Rao const uint64_t* value = 6455968caeeSMarri Devender Rao std::get_if<uint64_t>(&property.second); 6465968caeeSMarri Devender Rao if (value) 6475968caeeSMarri Devender Rao { 64837cce918SMarri Devender Rao std::time_t time = static_cast<std::time_t>(*value); 6495968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotBefore"] = 6505968caeeSMarri Devender Rao crow::utility::getDateTime(time); 6515968caeeSMarri Devender Rao } 6525968caeeSMarri Devender Rao } 6535968caeeSMarri Devender Rao } 6545968caeeSMarri Devender Rao asyncResp->res.addHeader("Location", certURL); 6555968caeeSMarri Devender Rao }, 6565968caeeSMarri Devender Rao service, objectPath, certs::dbusPropIntf, "GetAll", 6575968caeeSMarri Devender Rao certs::certPropIntf); 6585968caeeSMarri Devender Rao } 6595968caeeSMarri Devender Rao 6605968caeeSMarri Devender Rao using GetObjectType = 6615968caeeSMarri Devender Rao std::vector<std::pair<std::string, std::vector<std::string>>>; 6625968caeeSMarri Devender Rao 6635968caeeSMarri Devender Rao /** 6645968caeeSMarri Devender Rao * Action to replace an existing certificate 6655968caeeSMarri Devender Rao */ 666*7e860f15SJohn Edward Broadbent inline void requestRoutesCertificateActionsReplaceCertificate(App& app) 6675968caeeSMarri Devender Rao { 668*7e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/Actions/" 6695968caeeSMarri Devender Rao "CertificateService.ReplaceCertificate/") 670*7e860f15SJohn Edward Broadbent .privileges({"ConfigureComponents"}) 671*7e860f15SJohn Edward Broadbent .methods( 672*7e860f15SJohn Edward Broadbent boost::beast::http::verb:: 673*7e860f15SJohn Edward Broadbent post)([](const crow::Request& req, 674*7e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 6755968caeeSMarri Devender Rao std::string certificate; 6765968caeeSMarri Devender Rao nlohmann::json certificateUri; 6775968caeeSMarri Devender Rao std::optional<std::string> certificateType = "PEM"; 6788d1b46d7Szhanghch05 6795968caeeSMarri Devender Rao if (!json_util::readJson(req, asyncResp->res, "CertificateString", 680*7e860f15SJohn Edward Broadbent certificate, "CertificateUri", 681*7e860f15SJohn Edward Broadbent certificateUri, "CertificateType", 682*7e860f15SJohn Edward Broadbent certificateType)) 6835968caeeSMarri Devender Rao { 6845968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "Required parameters are missing"; 6855968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 6865968caeeSMarri Devender Rao return; 6875968caeeSMarri Devender Rao } 6885968caeeSMarri Devender Rao 6895968caeeSMarri Devender Rao if (!certificateType) 6905968caeeSMarri Devender Rao { 6915968caeeSMarri Devender Rao // should never happen, but it never hurts to be paranoid. 6925968caeeSMarri Devender Rao return; 6935968caeeSMarri Devender Rao } 6945968caeeSMarri Devender Rao if (certificateType != "PEM") 6955968caeeSMarri Devender Rao { 6965968caeeSMarri Devender Rao messages::actionParameterNotSupported( 6975968caeeSMarri Devender Rao asyncResp->res, "CertificateType", "ReplaceCertificate"); 6985968caeeSMarri Devender Rao return; 6995968caeeSMarri Devender Rao } 7005968caeeSMarri Devender Rao 7015968caeeSMarri Devender Rao std::string certURI; 7025968caeeSMarri Devender Rao if (!redfish::json_util::readJson(certificateUri, asyncResp->res, 7035968caeeSMarri Devender Rao "@odata.id", certURI)) 7045968caeeSMarri Devender Rao { 7055968caeeSMarri Devender Rao messages::actionParameterMissing( 7065968caeeSMarri Devender Rao asyncResp->res, "ReplaceCertificate", "CertificateUri"); 7075968caeeSMarri Devender Rao return; 7085968caeeSMarri Devender Rao } 7095968caeeSMarri Devender Rao 7105968caeeSMarri Devender Rao BMCWEB_LOG_INFO << "Certificate URI to replace" << certURI; 7115968caeeSMarri Devender Rao long id = getIDFromURL(certURI); 7125968caeeSMarri Devender Rao if (id < 0) 7135968caeeSMarri Devender Rao { 714*7e860f15SJohn Edward Broadbent messages::actionParameterValueFormatError( 715*7e860f15SJohn Edward Broadbent asyncResp->res, certURI, "CertificateUri", 7165968caeeSMarri Devender Rao "ReplaceCertificate"); 7175968caeeSMarri Devender Rao return; 7185968caeeSMarri Devender Rao } 7195968caeeSMarri Devender Rao std::string objectPath; 7205968caeeSMarri Devender Rao std::string name; 72137cce918SMarri Devender Rao std::string service; 722*7e860f15SJohn Edward Broadbent if (boost::starts_with(certURI, 723*7e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc/NetworkProtocol/" 724*7e860f15SJohn Edward Broadbent "HTTPS/Certificates/")) 7255968caeeSMarri Devender Rao { 726*7e860f15SJohn Edward Broadbent objectPath = std::string(certs::httpsObjectPath) + "/" + 727*7e860f15SJohn Edward Broadbent std::to_string(id); 7285968caeeSMarri Devender Rao name = "HTTPS certificate"; 72937cce918SMarri Devender Rao service = certs::httpsServiceName; 73037cce918SMarri Devender Rao } 73137cce918SMarri Devender Rao else if (boost::starts_with( 732*7e860f15SJohn Edward Broadbent certURI, 733*7e860f15SJohn Edward Broadbent "/redfish/v1/AccountService/LDAP/Certificates/")) 73437cce918SMarri Devender Rao { 735*7e860f15SJohn Edward Broadbent objectPath = std::string(certs::ldapObjectPath) + "/" + 736*7e860f15SJohn Edward Broadbent std::to_string(id); 73737cce918SMarri Devender Rao name = "LDAP certificate"; 73837cce918SMarri Devender Rao service = certs::ldapServiceName; 7395968caeeSMarri Devender Rao } 740cfcd5f6bSMarri Devender Rao else if (boost::starts_with( 741cfcd5f6bSMarri Devender Rao certURI, 742cfcd5f6bSMarri Devender Rao "/redfish/v1/Managers/bmc/Truststore/Certificates/")) 743cfcd5f6bSMarri Devender Rao { 744cfcd5f6bSMarri Devender Rao objectPath = std::string(certs::authorityObjectPath) + "/" + 745cfcd5f6bSMarri Devender Rao std::to_string(id); 746cfcd5f6bSMarri Devender Rao name = "TrustStore certificate"; 747cfcd5f6bSMarri Devender Rao service = certs::authorityServiceName; 748cfcd5f6bSMarri Devender Rao } 7495968caeeSMarri Devender Rao else 7505968caeeSMarri Devender Rao { 7515968caeeSMarri Devender Rao messages::actionParameterNotSupported( 7525968caeeSMarri Devender Rao asyncResp->res, "CertificateUri", "ReplaceCertificate"); 7535968caeeSMarri Devender Rao return; 7545968caeeSMarri Devender Rao } 7555968caeeSMarri Devender Rao 7565968caeeSMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 7575968caeeSMarri Devender Rao std::make_shared<CertificateFile>(certificate); 7585968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 75937cce918SMarri Devender Rao [asyncResp, certFile, objectPath, service, certURI, id, 7605968caeeSMarri Devender Rao name](const boost::system::error_code ec) { 7615968caeeSMarri Devender Rao if (ec) 7625968caeeSMarri Devender Rao { 7635968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 7648aae75adSMarri Devender Rao messages::resourceNotFound(asyncResp->res, name, 7658aae75adSMarri Devender Rao std::to_string(id)); 7665968caeeSMarri Devender Rao return; 7675968caeeSMarri Devender Rao } 76837cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, service, id, 7695968caeeSMarri Devender Rao certURI, name); 7705968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" 7715968caeeSMarri Devender Rao << certFile->getCertFilePath(); 7725968caeeSMarri Devender Rao }, 7735968caeeSMarri Devender Rao service, objectPath, certs::certReplaceIntf, "Replace", 7745968caeeSMarri Devender Rao certFile->getCertFilePath()); 775*7e860f15SJohn Edward Broadbent }); 776*7e860f15SJohn Edward Broadbent } // requestRoutesCertificateActionsReplaceCertificate 7775968caeeSMarri Devender Rao 7785968caeeSMarri Devender Rao /** 7795968caeeSMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 7805968caeeSMarri Devender Rao * of a component, account or service. 7815968caeeSMarri Devender Rao */ 7825968caeeSMarri Devender Rao 783*7e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificate(App& app) 7845968caeeSMarri Devender Rao { 785*7e860f15SJohn Edward Broadbent BMCWEB_ROUTE( 786*7e860f15SJohn Edward Broadbent app, 787*7e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/<str>/") 788*7e860f15SJohn Edward Broadbent .privileges({"Login"}) 789*7e860f15SJohn Edward Broadbent .methods( 790*7e860f15SJohn Edward Broadbent boost::beast::http::verb:: 791*7e860f15SJohn Edward Broadbent get)([](const crow::Request& req, 792*7e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 793*7e860f15SJohn Edward Broadbent const std::string& param) -> void { 794*7e860f15SJohn Edward Broadbent if (param.empty()) 7955968caeeSMarri Devender Rao { 7965968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 7975968caeeSMarri Devender Rao return; 7985968caeeSMarri Devender Rao } 7995968caeeSMarri Devender Rao long id = getIDFromURL(req.url); 8005968caeeSMarri Devender Rao 801*7e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG << "HTTPSCertificate::doGet ID=" 802*7e860f15SJohn Edward Broadbent << std::to_string(id); 8035968caeeSMarri Devender Rao std::string certURL = 8045968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/" + 8055968caeeSMarri Devender Rao std::to_string(id); 8065968caeeSMarri Devender Rao std::string objectPath = certs::httpsObjectPath; 8075968caeeSMarri Devender Rao objectPath += "/"; 8085968caeeSMarri Devender Rao objectPath += std::to_string(id); 809*7e860f15SJohn Edward Broadbent getCertificateProperties(asyncResp, objectPath, 810*7e860f15SJohn Edward Broadbent certs::httpsServiceName, id, certURL, 811*7e860f15SJohn Edward Broadbent "HTTPS Certificate"); 812*7e860f15SJohn Edward Broadbent }); 8135968caeeSMarri Devender Rao } 8145968caeeSMarri Devender Rao 8155968caeeSMarri Devender Rao /** 8165968caeeSMarri Devender Rao * Collection of HTTPS certificates 8175968caeeSMarri Devender Rao */ 818*7e860f15SJohn Edward Broadbent inline void requestRoutesHTTPSCertificateCollection(App& app) 8195968caeeSMarri Devender Rao { 820*7e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 8215968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/") 822*7e860f15SJohn Edward Broadbent .privileges({"Login"}) 823*7e860f15SJohn Edward Broadbent .methods( 824*7e860f15SJohn Edward Broadbent boost::beast::http::verb:: 825*7e860f15SJohn Edward Broadbent get)([](const crow::Request&, 826*7e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 8278d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 8285968caeeSMarri Devender Rao {"@odata.id", 8295968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"}, 8305968caeeSMarri Devender Rao {"@odata.type", "#CertificateCollection.CertificateCollection"}, 8315968caeeSMarri Devender Rao {"Name", "HTTPS Certificates Collection"}, 8325968caeeSMarri Devender Rao {"Description", "A Collection of HTTPS certificate instances"}}; 8338d1b46d7Szhanghch05 8345968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 8355968caeeSMarri Devender Rao [asyncResp](const boost::system::error_code ec, 8365968caeeSMarri Devender Rao const ManagedObjectType& certs) { 8375968caeeSMarri Devender Rao if (ec) 8385968caeeSMarri Devender Rao { 8395968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 8405968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 8415968caeeSMarri Devender Rao return; 8425968caeeSMarri Devender Rao } 843*7e860f15SJohn Edward Broadbent nlohmann::json& members = 844*7e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Members"]; 8455968caeeSMarri Devender Rao members = nlohmann::json::array(); 8465968caeeSMarri Devender Rao for (const auto& cert : certs) 8475968caeeSMarri Devender Rao { 8485968caeeSMarri Devender Rao long id = getIDFromURL(cert.first.str); 84937cce918SMarri Devender Rao if (id >= 0) 8505968caeeSMarri Devender Rao { 8515968caeeSMarri Devender Rao members.push_back( 8525968caeeSMarri Devender Rao {{"@odata.id", 8535968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/" 8545968caeeSMarri Devender Rao "NetworkProtocol/HTTPS/Certificates/" + 8555968caeeSMarri Devender Rao std::to_string(id)}}); 8565968caeeSMarri Devender Rao } 8575968caeeSMarri Devender Rao } 8585968caeeSMarri Devender Rao asyncResp->res.jsonValue["Members@odata.count"] = 8595968caeeSMarri Devender Rao members.size(); 8605968caeeSMarri Devender Rao }, 86137cce918SMarri Devender Rao certs::httpsServiceName, certs::httpsObjectPath, 86237cce918SMarri Devender Rao certs::dbusObjManagerIntf, "GetManagedObjects"); 863*7e860f15SJohn Edward Broadbent }); 8645968caeeSMarri Devender Rao 865*7e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, 866*7e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/") 867*7e860f15SJohn Edward Broadbent .privileges({"ConfigureComponents"}) 868*7e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 869*7e860f15SJohn Edward Broadbent [](const crow::Request& req, 870*7e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 8715968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPSCertificateCollection::doPost"; 8728d1b46d7Szhanghch05 873*7e860f15SJohn Edward Broadbent asyncResp->res.jsonValue = { 874*7e860f15SJohn Edward Broadbent {"Name", "HTTPS Certificate"}, 8755968caeeSMarri Devender Rao {"Description", "HTTPS Certificate"}}; 8765968caeeSMarri Devender Rao 877*7e860f15SJohn Edward Broadbent std::string certFileBody = 878*7e860f15SJohn Edward Broadbent getCertificateFromReqBody(asyncResp, req); 87958eb238fSKowalski, Kamil 88058eb238fSKowalski, Kamil if (certFileBody.empty()) 88158eb238fSKowalski, Kamil { 882*7e860f15SJohn Edward Broadbent BMCWEB_LOG_ERROR 883*7e860f15SJohn Edward Broadbent << "Cannot get certificate from request body."; 884a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 88558eb238fSKowalski, Kamil return; 88658eb238fSKowalski, Kamil } 88758eb238fSKowalski, Kamil 8885968caeeSMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 88958eb238fSKowalski, Kamil std::make_shared<CertificateFile>(certFileBody); 8905968caeeSMarri Devender Rao 8915968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 892656ec7e3SZbigniew Kurzynski [asyncResp, certFile](const boost::system::error_code ec, 893656ec7e3SZbigniew Kurzynski const std::string& objectPath) { 8945968caeeSMarri Devender Rao if (ec) 8955968caeeSMarri Devender Rao { 8965968caeeSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 8975968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 8985968caeeSMarri Devender Rao return; 8995968caeeSMarri Devender Rao } 900656ec7e3SZbigniew Kurzynski long certId = getIDFromURL(objectPath); 901656ec7e3SZbigniew Kurzynski if (certId < 0) 902656ec7e3SZbigniew Kurzynski { 903656ec7e3SZbigniew Kurzynski BMCWEB_LOG_ERROR << "Invalid objectPath value" 904656ec7e3SZbigniew Kurzynski << objectPath; 905656ec7e3SZbigniew Kurzynski messages::internalError(asyncResp->res); 906656ec7e3SZbigniew Kurzynski return; 907656ec7e3SZbigniew Kurzynski } 9085968caeeSMarri Devender Rao std::string certURL = 9095968caeeSMarri Devender Rao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/" 9105968caeeSMarri Devender Rao "Certificates/" + 9115968caeeSMarri Devender Rao std::to_string(certId); 912*7e860f15SJohn Edward Broadbent getCertificateProperties( 913*7e860f15SJohn Edward Broadbent asyncResp, objectPath, certs::httpsServiceName, 914*7e860f15SJohn Edward Broadbent certId, certURL, "HTTPS Certificate"); 9155968caeeSMarri Devender Rao BMCWEB_LOG_DEBUG << "HTTPS certificate install file=" 9165968caeeSMarri Devender Rao << certFile->getCertFilePath(); 9175968caeeSMarri Devender Rao }, 91837cce918SMarri Devender Rao certs::httpsServiceName, certs::httpsObjectPath, 919*7e860f15SJohn Edward Broadbent certs::certInstallIntf, "Install", 920*7e860f15SJohn Edward Broadbent certFile->getCertFilePath()); 921*7e860f15SJohn Edward Broadbent }); 922*7e860f15SJohn Edward Broadbent } // requestRoutesHTTPSCertificateCollection 9235968caeeSMarri Devender Rao 9245968caeeSMarri Devender Rao /** 92537cce918SMarri Devender Rao * @brief Retrieve the certificates installed list and append to the 92637cce918SMarri Devender Rao * response 92737cce918SMarri Devender Rao * 92837cce918SMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 92937cce918SMarri Devender Rao * @param[in] certURL Path of the certificate object 93037cce918SMarri Devender Rao * @param[in] path Path of the D-Bus service object 93137cce918SMarri Devender Rao * @return None 93237cce918SMarri Devender Rao */ 9338d1b46d7Szhanghch05 void getCertificateLocations( 9348d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 9358d1b46d7Szhanghch05 const std::string& certURL, const std::string& path, 93637cce918SMarri Devender Rao const std::string& service) 93737cce918SMarri Devender Rao { 93837cce918SMarri Devender Rao BMCWEB_LOG_DEBUG << "getCertificateLocations URI=" << certURL 93937cce918SMarri Devender Rao << " Path=" << path << " service= " << service; 94037cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 94137cce918SMarri Devender Rao [asyncResp, certURL](const boost::system::error_code ec, 94237cce918SMarri Devender Rao const ManagedObjectType& certs) { 94337cce918SMarri Devender Rao if (ec) 94437cce918SMarri Devender Rao { 9459c8e039eSJonathan Doman BMCWEB_LOG_WARNING 9469c8e039eSJonathan Doman << "Certificate collection query failed: " << ec 9479c8e039eSJonathan Doman << ", skipping " << certURL; 94837cce918SMarri Devender Rao return; 94937cce918SMarri Devender Rao } 95037cce918SMarri Devender Rao nlohmann::json& links = 95137cce918SMarri Devender Rao asyncResp->res.jsonValue["Links"]["Certificates"]; 95237cce918SMarri Devender Rao for (auto& cert : certs) 95337cce918SMarri Devender Rao { 95437cce918SMarri Devender Rao long id = getIDFromURL(cert.first.str); 95537cce918SMarri Devender Rao if (id >= 0) 95637cce918SMarri Devender Rao { 95737cce918SMarri Devender Rao links.push_back( 95837cce918SMarri Devender Rao {{"@odata.id", certURL + std::to_string(id)}}); 95937cce918SMarri Devender Rao } 96037cce918SMarri Devender Rao } 96137cce918SMarri Devender Rao asyncResp->res.jsonValue["Links"]["Certificates@odata.count"] = 96237cce918SMarri Devender Rao links.size(); 96337cce918SMarri Devender Rao }, 96437cce918SMarri Devender Rao service, path, certs::dbusObjManagerIntf, "GetManagedObjects"); 9655968caeeSMarri Devender Rao } 966*7e860f15SJohn Edward Broadbent 967*7e860f15SJohn Edward Broadbent /** 968*7e860f15SJohn Edward Broadbent * The certificate location schema defines a resource that an administrator 969*7e860f15SJohn Edward Broadbent * can use in order to locate all certificates installed on a given service. 970*7e860f15SJohn Edward Broadbent */ 971*7e860f15SJohn Edward Broadbent inline void requestRoutesCertificateLocations(App& app) 972*7e860f15SJohn Edward Broadbent { 973*7e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/") 974*7e860f15SJohn Edward Broadbent .privileges({"Login"}) 975*7e860f15SJohn Edward Broadbent .methods( 976*7e860f15SJohn Edward Broadbent boost::beast::http::verb:: 977*7e860f15SJohn Edward Broadbent get)([](const crow::Request&, 978*7e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 979*7e860f15SJohn Edward Broadbent asyncResp->res.jsonValue = { 980*7e860f15SJohn Edward Broadbent {"@odata.id", 981*7e860f15SJohn Edward Broadbent "/redfish/v1/CertificateService/CertificateLocations"}, 982*7e860f15SJohn Edward Broadbent {"@odata.type", 983*7e860f15SJohn Edward Broadbent "#CertificateLocations.v1_0_0.CertificateLocations"}, 984*7e860f15SJohn Edward Broadbent {"Name", "Certificate Locations"}, 985*7e860f15SJohn Edward Broadbent {"Id", "CertificateLocations"}, 986*7e860f15SJohn Edward Broadbent {"Description", 987*7e860f15SJohn Edward Broadbent "Defines a resource that an administrator can use in order to " 988*7e860f15SJohn Edward Broadbent "locate all certificates installed on a given service"}}; 989*7e860f15SJohn Edward Broadbent 990*7e860f15SJohn Edward Broadbent nlohmann::json& links = 991*7e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Links"]["Certificates"]; 992*7e860f15SJohn Edward Broadbent links = nlohmann::json::array(); 993*7e860f15SJohn Edward Broadbent getCertificateLocations( 994*7e860f15SJohn Edward Broadbent asyncResp, 995*7e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/", 996*7e860f15SJohn Edward Broadbent certs::httpsObjectPath, certs::httpsServiceName); 997*7e860f15SJohn Edward Broadbent getCertificateLocations( 998*7e860f15SJohn Edward Broadbent asyncResp, "/redfish/v1/AccountService/LDAP/Certificates/", 999*7e860f15SJohn Edward Broadbent certs::ldapObjectPath, certs::ldapServiceName); 1000*7e860f15SJohn Edward Broadbent getCertificateLocations( 1001*7e860f15SJohn Edward Broadbent asyncResp, "/redfish/v1/Managers/bmc/Truststore/Certificates/", 1002*7e860f15SJohn Edward Broadbent certs::authorityObjectPath, certs::authorityServiceName); 1003*7e860f15SJohn Edward Broadbent }); 1004*7e860f15SJohn Edward Broadbent } 1005*7e860f15SJohn Edward Broadbent // requestRoutesCertificateLocations 100637cce918SMarri Devender Rao 100737cce918SMarri Devender Rao /** 100837cce918SMarri Devender Rao * Collection of LDAP certificates 100937cce918SMarri Devender Rao */ 1010*7e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificateCollection(App& app) 101137cce918SMarri Devender Rao { 1012*7e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/") 1013*7e860f15SJohn Edward Broadbent .privileges({"Login"}) 1014*7e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 1015*7e860f15SJohn Edward Broadbent [](const crow::Request&, 1016*7e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 10178d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 1018*7e860f15SJohn Edward Broadbent {"@odata.id", 1019*7e860f15SJohn Edward Broadbent "/redfish/v1/AccountService/LDAP/Certificates"}, 1020*7e860f15SJohn Edward Broadbent {"@odata.type", 1021*7e860f15SJohn Edward Broadbent "#CertificateCollection.CertificateCollection"}, 102237cce918SMarri Devender Rao {"Name", "LDAP Certificates Collection"}, 1023*7e860f15SJohn Edward Broadbent {"Description", 1024*7e860f15SJohn Edward Broadbent "A Collection of LDAP certificate instances"}}; 10258d1b46d7Szhanghch05 102637cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 102737cce918SMarri Devender Rao [asyncResp](const boost::system::error_code ec, 102837cce918SMarri Devender Rao const ManagedObjectType& certs) { 1029*7e860f15SJohn Edward Broadbent nlohmann::json& members = 1030*7e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Members"]; 10319c8e039eSJonathan Doman nlohmann::json& count = 10329c8e039eSJonathan Doman asyncResp->res.jsonValue["Members@odata.count"]; 10339c8e039eSJonathan Doman members = nlohmann::json::array(); 10349c8e039eSJonathan Doman count = 0; 103537cce918SMarri Devender Rao if (ec) 103637cce918SMarri Devender Rao { 1037*7e860f15SJohn Edward Broadbent BMCWEB_LOG_WARNING 1038*7e860f15SJohn Edward Broadbent << "LDAP certificate query failed: " << ec; 103937cce918SMarri Devender Rao return; 104037cce918SMarri Devender Rao } 104137cce918SMarri Devender Rao for (const auto& cert : certs) 104237cce918SMarri Devender Rao { 104337cce918SMarri Devender Rao long id = getIDFromURL(cert.first.str); 104437cce918SMarri Devender Rao if (id >= 0) 104537cce918SMarri Devender Rao { 104637cce918SMarri Devender Rao members.push_back( 104737cce918SMarri Devender Rao {{"@odata.id", "/redfish/v1/AccountService/" 104837cce918SMarri Devender Rao "LDAP/Certificates/" + 104937cce918SMarri Devender Rao std::to_string(id)}}); 105037cce918SMarri Devender Rao } 105137cce918SMarri Devender Rao } 10529c8e039eSJonathan Doman count = members.size(); 105337cce918SMarri Devender Rao }, 105437cce918SMarri Devender Rao certs::ldapServiceName, certs::ldapObjectPath, 105537cce918SMarri Devender Rao certs::dbusObjManagerIntf, "GetManagedObjects"); 1056*7e860f15SJohn Edward Broadbent }); 105737cce918SMarri Devender Rao 1058*7e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/") 1059*7e860f15SJohn Edward Broadbent .privileges({"ConfigureComponents"}) 1060*7e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 1061*7e860f15SJohn Edward Broadbent [](const crow::Request& req, 1062*7e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 1063*7e860f15SJohn Edward Broadbent std::string certFileBody = 1064*7e860f15SJohn Edward Broadbent getCertificateFromReqBody(asyncResp, req); 106558eb238fSKowalski, Kamil 106658eb238fSKowalski, Kamil if (certFileBody.empty()) 106758eb238fSKowalski, Kamil { 1068*7e860f15SJohn Edward Broadbent BMCWEB_LOG_ERROR 1069*7e860f15SJohn Edward Broadbent << "Cannot get certificate from request body."; 1070a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 107158eb238fSKowalski, Kamil return; 107258eb238fSKowalski, Kamil } 107358eb238fSKowalski, Kamil 107458eb238fSKowalski, Kamil std::shared_ptr<CertificateFile> certFile = 107558eb238fSKowalski, Kamil std::make_shared<CertificateFile>(certFileBody); 107658eb238fSKowalski, Kamil 107737cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 1078656ec7e3SZbigniew Kurzynski [asyncResp, certFile](const boost::system::error_code ec, 1079656ec7e3SZbigniew Kurzynski const std::string& objectPath) { 108037cce918SMarri Devender Rao if (ec) 108137cce918SMarri Devender Rao { 108237cce918SMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 108337cce918SMarri Devender Rao messages::internalError(asyncResp->res); 108437cce918SMarri Devender Rao return; 108537cce918SMarri Devender Rao } 1086656ec7e3SZbigniew Kurzynski long certId = getIDFromURL(objectPath); 1087656ec7e3SZbigniew Kurzynski if (certId < 0) 1088656ec7e3SZbigniew Kurzynski { 1089656ec7e3SZbigniew Kurzynski BMCWEB_LOG_ERROR << "Invalid objectPath value" 1090656ec7e3SZbigniew Kurzynski << objectPath; 1091656ec7e3SZbigniew Kurzynski messages::internalError(asyncResp->res); 1092656ec7e3SZbigniew Kurzynski return; 1093656ec7e3SZbigniew Kurzynski } 109437cce918SMarri Devender Rao std::string certURL = 109537cce918SMarri Devender Rao "/redfish/v1/AccountService/LDAP/Certificates/" + 109637cce918SMarri Devender Rao std::to_string(certId); 109737cce918SMarri Devender Rao getCertificateProperties(asyncResp, objectPath, 109837cce918SMarri Devender Rao certs::ldapServiceName, certId, 109937cce918SMarri Devender Rao certURL, "LDAP Certificate"); 110037cce918SMarri Devender Rao BMCWEB_LOG_DEBUG << "LDAP certificate install file=" 110137cce918SMarri Devender Rao << certFile->getCertFilePath(); 110237cce918SMarri Devender Rao }, 110337cce918SMarri Devender Rao certs::ldapServiceName, certs::ldapObjectPath, 1104*7e860f15SJohn Edward Broadbent certs::certInstallIntf, "Install", 1105*7e860f15SJohn Edward Broadbent certFile->getCertFilePath()); 1106*7e860f15SJohn Edward Broadbent }); 1107*7e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificateCollection 110837cce918SMarri Devender Rao 110937cce918SMarri Devender Rao /** 111037cce918SMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 111137cce918SMarri Devender Rao * of a component, account or service. 111237cce918SMarri Devender Rao */ 1113*7e860f15SJohn Edward Broadbent inline void requestRoutesLDAPCertificate(App& app) 111437cce918SMarri Devender Rao { 1115*7e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/") 1116*7e860f15SJohn Edward Broadbent .privileges({"Login"}) 1117*7e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 1118*7e860f15SJohn Edward Broadbent [](const crow::Request& req, 1119*7e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1120*7e860f15SJohn Edward Broadbent const std::string&) { 112137cce918SMarri Devender Rao long id = getIDFromURL(req.url); 112237cce918SMarri Devender Rao if (id < 0) 112337cce918SMarri Devender Rao { 112437cce918SMarri Devender Rao BMCWEB_LOG_ERROR << "Invalid url value" << req.url; 112537cce918SMarri Devender Rao messages::internalError(asyncResp->res); 112637cce918SMarri Devender Rao return; 112737cce918SMarri Devender Rao } 1128*7e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG << "LDAP Certificate ID=" 1129*7e860f15SJohn Edward Broadbent << std::to_string(id); 1130*7e860f15SJohn Edward Broadbent std::string certURL = 1131*7e860f15SJohn Edward Broadbent "/redfish/v1/AccountService/LDAP/Certificates/" + 113237cce918SMarri Devender Rao std::to_string(id); 113337cce918SMarri Devender Rao std::string objectPath = certs::ldapObjectPath; 113437cce918SMarri Devender Rao objectPath += "/"; 113537cce918SMarri Devender Rao objectPath += std::to_string(id); 1136*7e860f15SJohn Edward Broadbent getCertificateProperties(asyncResp, objectPath, 1137*7e860f15SJohn Edward Broadbent certs::ldapServiceName, id, certURL, 1138*7e860f15SJohn Edward Broadbent "LDAP Certificate"); 1139*7e860f15SJohn Edward Broadbent }); 1140*7e860f15SJohn Edward Broadbent } // requestRoutesLDAPCertificate 1141cfcd5f6bSMarri Devender Rao /** 1142cfcd5f6bSMarri Devender Rao * Collection of TrustStoreCertificate certificates 1143cfcd5f6bSMarri Devender Rao */ 1144*7e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificateCollection(App& app) 1145cfcd5f6bSMarri Devender Rao { 1146*7e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/") 1147*7e860f15SJohn Edward Broadbent .privileges({"Login"}) 1148*7e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 1149*7e860f15SJohn Edward Broadbent [](const crow::Request&, 1150*7e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 11518d1b46d7Szhanghch05 asyncResp->res.jsonValue = { 1152*7e860f15SJohn Edward Broadbent {"@odata.id", 1153*7e860f15SJohn Edward Broadbent "/redfish/v1/Managers/bmc/Truststore/Certificates/"}, 1154*7e860f15SJohn Edward Broadbent {"@odata.type", 1155*7e860f15SJohn Edward Broadbent "#CertificateCollection.CertificateCollection"}, 1156cfcd5f6bSMarri Devender Rao {"Name", "TrustStore Certificates Collection"}, 1157cfcd5f6bSMarri Devender Rao {"Description", 1158cfcd5f6bSMarri Devender Rao "A Collection of TrustStore certificate instances"}}; 11598d1b46d7Szhanghch05 1160cfcd5f6bSMarri Devender Rao crow::connections::systemBus->async_method_call( 1161cfcd5f6bSMarri Devender Rao [asyncResp](const boost::system::error_code ec, 1162cfcd5f6bSMarri Devender Rao const ManagedObjectType& certs) { 1163cfcd5f6bSMarri Devender Rao if (ec) 1164cfcd5f6bSMarri Devender Rao { 1165cfcd5f6bSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 1166cfcd5f6bSMarri Devender Rao messages::internalError(asyncResp->res); 1167cfcd5f6bSMarri Devender Rao return; 1168cfcd5f6bSMarri Devender Rao } 1169*7e860f15SJohn Edward Broadbent nlohmann::json& members = 1170*7e860f15SJohn Edward Broadbent asyncResp->res.jsonValue["Members"]; 1171cfcd5f6bSMarri Devender Rao members = nlohmann::json::array(); 1172cfcd5f6bSMarri Devender Rao for (const auto& cert : certs) 1173cfcd5f6bSMarri Devender Rao { 1174cfcd5f6bSMarri Devender Rao long id = getIDFromURL(cert.first.str); 1175cfcd5f6bSMarri Devender Rao if (id >= 0) 1176cfcd5f6bSMarri Devender Rao { 1177cfcd5f6bSMarri Devender Rao members.push_back( 1178cfcd5f6bSMarri Devender Rao {{"@odata.id", "/redfish/v1/Managers/bmc/" 1179cfcd5f6bSMarri Devender Rao "Truststore/Certificates/" + 1180cfcd5f6bSMarri Devender Rao std::to_string(id)}}); 1181cfcd5f6bSMarri Devender Rao } 1182cfcd5f6bSMarri Devender Rao } 1183cfcd5f6bSMarri Devender Rao asyncResp->res.jsonValue["Members@odata.count"] = 1184cfcd5f6bSMarri Devender Rao members.size(); 1185cfcd5f6bSMarri Devender Rao }, 1186cfcd5f6bSMarri Devender Rao certs::authorityServiceName, certs::authorityObjectPath, 1187cfcd5f6bSMarri Devender Rao certs::dbusObjManagerIntf, "GetManagedObjects"); 1188*7e860f15SJohn Edward Broadbent }); 1189cfcd5f6bSMarri Devender Rao 1190*7e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/") 1191*7e860f15SJohn Edward Broadbent .privileges({"ConfigureComponents"}) 1192*7e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::post)( 1193*7e860f15SJohn Edward Broadbent [](const crow::Request& req, 1194*7e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) { 1195*7e860f15SJohn Edward Broadbent std::string certFileBody = 1196*7e860f15SJohn Edward Broadbent getCertificateFromReqBody(asyncResp, req); 1197a08752f5SZbigniew Kurzynski 1198a08752f5SZbigniew Kurzynski if (certFileBody.empty()) 1199a08752f5SZbigniew Kurzynski { 1200*7e860f15SJohn Edward Broadbent BMCWEB_LOG_ERROR 1201*7e860f15SJohn Edward Broadbent << "Cannot get certificate from request body."; 1202a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 1203a08752f5SZbigniew Kurzynski return; 1204a08752f5SZbigniew Kurzynski } 1205a08752f5SZbigniew Kurzynski 1206a08752f5SZbigniew Kurzynski std::shared_ptr<CertificateFile> certFile = 1207a08752f5SZbigniew Kurzynski std::make_shared<CertificateFile>(certFileBody); 1208cfcd5f6bSMarri Devender Rao crow::connections::systemBus->async_method_call( 1209656ec7e3SZbigniew Kurzynski [asyncResp, certFile](const boost::system::error_code ec, 1210656ec7e3SZbigniew Kurzynski const std::string& objectPath) { 1211cfcd5f6bSMarri Devender Rao if (ec) 1212cfcd5f6bSMarri Devender Rao { 1213cfcd5f6bSMarri Devender Rao BMCWEB_LOG_ERROR << "DBUS response error: " << ec; 1214cfcd5f6bSMarri Devender Rao messages::internalError(asyncResp->res); 1215cfcd5f6bSMarri Devender Rao return; 1216cfcd5f6bSMarri Devender Rao } 1217656ec7e3SZbigniew Kurzynski long certId = getIDFromURL(objectPath); 1218656ec7e3SZbigniew Kurzynski if (certId < 0) 1219656ec7e3SZbigniew Kurzynski { 1220656ec7e3SZbigniew Kurzynski BMCWEB_LOG_ERROR << "Invalid objectPath value" 1221656ec7e3SZbigniew Kurzynski << objectPath; 1222656ec7e3SZbigniew Kurzynski messages::internalError(asyncResp->res); 1223656ec7e3SZbigniew Kurzynski return; 1224656ec7e3SZbigniew Kurzynski } 1225cfcd5f6bSMarri Devender Rao std::string certURL = "/redfish/v1/Managers/bmc/" 1226cfcd5f6bSMarri Devender Rao "Truststore/Certificates/" + 1227cfcd5f6bSMarri Devender Rao std::to_string(certId); 1228656ec7e3SZbigniew Kurzynski 1229*7e860f15SJohn Edward Broadbent getCertificateProperties( 1230*7e860f15SJohn Edward Broadbent asyncResp, objectPath, certs::authorityServiceName, 1231*7e860f15SJohn Edward Broadbent certId, certURL, "TrustStore Certificate"); 1232*7e860f15SJohn Edward Broadbent BMCWEB_LOG_DEBUG 1233*7e860f15SJohn Edward Broadbent << "TrustStore certificate install file=" 1234cfcd5f6bSMarri Devender Rao << certFile->getCertFilePath(); 1235cfcd5f6bSMarri Devender Rao }, 1236cfcd5f6bSMarri Devender Rao certs::authorityServiceName, certs::authorityObjectPath, 1237*7e860f15SJohn Edward Broadbent certs::certInstallIntf, "Install", 1238*7e860f15SJohn Edward Broadbent certFile->getCertFilePath()); 1239*7e860f15SJohn Edward Broadbent }); 1240*7e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificateCollection 1241cfcd5f6bSMarri Devender Rao 1242cfcd5f6bSMarri Devender Rao /** 1243cfcd5f6bSMarri Devender Rao * Certificate resource describes a certificate used to prove the identity 1244cfcd5f6bSMarri Devender Rao * of a component, account or service. 1245cfcd5f6bSMarri Devender Rao */ 1246*7e860f15SJohn Edward Broadbent inline void requestRoutesTrustStoreCertificate(App& app) 1247cfcd5f6bSMarri Devender Rao { 1248*7e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/") 1249*7e860f15SJohn Edward Broadbent .privileges({"Loign"}) 1250*7e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::get)( 1251*7e860f15SJohn Edward Broadbent [](const crow::Request& req, 1252*7e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1253*7e860f15SJohn Edward Broadbent const std::string&) { 1254cfcd5f6bSMarri Devender Rao long id = getIDFromURL(req.url); 1255cfcd5f6bSMarri Devender Rao if (id < 0) 1256cfcd5f6bSMarri Devender Rao { 1257cfcd5f6bSMarri Devender Rao BMCWEB_LOG_ERROR << "Invalid url value" << req.url; 1258cfcd5f6bSMarri Devender Rao messages::internalError(asyncResp->res); 1259cfcd5f6bSMarri Devender Rao return; 1260cfcd5f6bSMarri Devender Rao } 1261cfcd5f6bSMarri Devender Rao BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doGet ID=" 1262cfcd5f6bSMarri Devender Rao << std::to_string(id); 1263cfcd5f6bSMarri Devender Rao std::string certURL = 1264cfcd5f6bSMarri Devender Rao "/redfish/v1/Managers/bmc/Truststore/Certificates/" + 1265cfcd5f6bSMarri Devender Rao std::to_string(id); 1266cfcd5f6bSMarri Devender Rao std::string objectPath = certs::authorityObjectPath; 1267cfcd5f6bSMarri Devender Rao objectPath += "/"; 1268cfcd5f6bSMarri Devender Rao objectPath += std::to_string(id); 1269cfcd5f6bSMarri Devender Rao getCertificateProperties(asyncResp, objectPath, 1270*7e860f15SJohn Edward Broadbent certs::authorityServiceName, id, 1271*7e860f15SJohn Edward Broadbent certURL, "TrustStore Certificate"); 1272*7e860f15SJohn Edward Broadbent }); 127307a60299SZbigniew Kurzynski 1274*7e860f15SJohn Edward Broadbent BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/") 1275*7e860f15SJohn Edward Broadbent .privileges({"ConfigureComponents"}) 1276*7e860f15SJohn Edward Broadbent .methods(boost::beast::http::verb::delete_)( 1277*7e860f15SJohn Edward Broadbent [](const crow::Request& req, 1278*7e860f15SJohn Edward Broadbent const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 1279*7e860f15SJohn Edward Broadbent const std::string& param) { 1280*7e860f15SJohn Edward Broadbent if (param.empty()) 128107a60299SZbigniew Kurzynski { 128207a60299SZbigniew Kurzynski messages::internalError(asyncResp->res); 128307a60299SZbigniew Kurzynski return; 128407a60299SZbigniew Kurzynski } 128507a60299SZbigniew Kurzynski 128607a60299SZbigniew Kurzynski long id = getIDFromURL(req.url); 128707a60299SZbigniew Kurzynski if (id < 0) 128807a60299SZbigniew Kurzynski { 128907a60299SZbigniew Kurzynski BMCWEB_LOG_ERROR << "Invalid url value: " << req.url; 1290*7e860f15SJohn Edward Broadbent messages::resourceNotFound(asyncResp->res, 1291*7e860f15SJohn Edward Broadbent "TrustStore Certificate", 129207a60299SZbigniew Kurzynski std::string(req.url)); 129307a60299SZbigniew Kurzynski return; 129407a60299SZbigniew Kurzynski } 129507a60299SZbigniew Kurzynski BMCWEB_LOG_DEBUG << "TrustStoreCertificate::doDelete ID=" 129607a60299SZbigniew Kurzynski << std::to_string(id); 129707a60299SZbigniew Kurzynski std::string certPath = certs::authorityObjectPath; 129807a60299SZbigniew Kurzynski certPath += "/"; 129907a60299SZbigniew Kurzynski certPath += std::to_string(id); 130007a60299SZbigniew Kurzynski 130107a60299SZbigniew Kurzynski crow::connections::systemBus->async_method_call( 130207a60299SZbigniew Kurzynski [asyncResp, id](const boost::system::error_code ec) { 130307a60299SZbigniew Kurzynski if (ec) 130407a60299SZbigniew Kurzynski { 130507a60299SZbigniew Kurzynski messages::resourceNotFound(asyncResp->res, 130607a60299SZbigniew Kurzynski "TrustStore Certificate", 130707a60299SZbigniew Kurzynski std::to_string(id)); 130807a60299SZbigniew Kurzynski return; 130907a60299SZbigniew Kurzynski } 131007a60299SZbigniew Kurzynski BMCWEB_LOG_INFO << "Certificate deleted"; 1311*7e860f15SJohn Edward Broadbent asyncResp->res.result( 1312*7e860f15SJohn Edward Broadbent boost::beast::http::status::no_content); 131307a60299SZbigniew Kurzynski }, 131407a60299SZbigniew Kurzynski certs::authorityServiceName, certPath, certs::objDeleteIntf, 131507a60299SZbigniew Kurzynski "Delete"); 1316*7e860f15SJohn Edward Broadbent }); 1317*7e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificate 13185968caeeSMarri Devender Rao } // namespace redfish 1319