15968caeeSMarri Devender Rao #pragma once 25968caeeSMarri Devender Rao 33ccb3adbSEd Tanous #include "app.hpp" 43ccb3adbSEd Tanous #include "async_resp.hpp" 57a1dbc48SGeorge Liu #include "dbus_utility.hpp" 61aa0c2b8SEd Tanous #include "http/parsing.hpp" 73ccb3adbSEd Tanous #include "http_response.hpp" 83ccb3adbSEd Tanous #include "query.hpp" 93ccb3adbSEd Tanous #include "registries/privilege_registry.hpp" 109b12d1f9SKrzysztof Grobelny #include "utils/dbus_utils.hpp" 113ccb3adbSEd Tanous #include "utils/json_utils.hpp" 123ccb3adbSEd Tanous #include "utils/time_utils.hpp" 139b12d1f9SKrzysztof Grobelny 1490d2d1e8SJiaqing Zhao #include <boost/system/linux_error.hpp> 15ef4c65b7SEd Tanous #include <boost/url/format.hpp> 169b12d1f9SKrzysztof Grobelny #include <sdbusplus/asio/property.hpp> 173ccb3adbSEd Tanous #include <sdbusplus/bus/match.hpp> 189b12d1f9SKrzysztof Grobelny #include <sdbusplus/unpack_properties.hpp> 191214b7e7SGunnar Mills 207a1dbc48SGeorge Liu #include <array> 213ccb3adbSEd Tanous #include <memory> 227a1dbc48SGeorge Liu #include <string_view> 237a1dbc48SGeorge Liu 245968caeeSMarri Devender Rao namespace redfish 255968caeeSMarri Devender Rao { 265968caeeSMarri Devender Rao namespace certs 275968caeeSMarri Devender Rao { 2889492a15SPatrick Williams constexpr const char* certInstallIntf = "xyz.openbmc_project.Certs.Install"; 2989492a15SPatrick Williams constexpr const char* certReplaceIntf = "xyz.openbmc_project.Certs.Replace"; 3089492a15SPatrick Williams constexpr const char* objDeleteIntf = "xyz.openbmc_project.Object.Delete"; 3189492a15SPatrick Williams constexpr const char* certPropIntf = "xyz.openbmc_project.Certs.Certificate"; 3289492a15SPatrick Williams constexpr const char* dbusPropIntf = "org.freedesktop.DBus.Properties"; 3389492a15SPatrick Williams constexpr const char* dbusObjManagerIntf = "org.freedesktop.DBus.ObjectManager"; 3489492a15SPatrick Williams constexpr const char* httpsServiceName = 3537cce918SMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Server.Https"; 3689492a15SPatrick Williams constexpr const char* ldapServiceName = 3737cce918SMarri Devender Rao "xyz.openbmc_project.Certs.Manager.Client.Ldap"; 3889492a15SPatrick Williams constexpr const char* authorityServiceName = 39b2254ccdSMichal Orzel "xyz.openbmc_project.Certs.Manager.Authority.Truststore"; 4089492a15SPatrick Williams constexpr const char* baseObjectPath = "/xyz/openbmc_project/certs"; 4189492a15SPatrick Williams constexpr const char* httpsObjectPath = 42c6a8dfb1SJiaqing Zhao "/xyz/openbmc_project/certs/server/https"; 4389492a15SPatrick Williams constexpr const char* ldapObjectPath = "/xyz/openbmc_project/certs/client/ldap"; 4489492a15SPatrick Williams constexpr const char* authorityObjectPath = 45b2254ccdSMichal Orzel "/xyz/openbmc_project/certs/authority/truststore"; 465968caeeSMarri Devender Rao } // namespace certs 475968caeeSMarri Devender Rao 485968caeeSMarri Devender Rao /** 495968caeeSMarri Devender Rao * The Certificate schema defines a Certificate Service which represents the 505968caeeSMarri Devender Rao * actions available to manage certificates and links to where certificates 515968caeeSMarri Devender Rao * are installed. 525968caeeSMarri Devender Rao */ 537e860f15SJohn Edward Broadbent 548d1b46d7Szhanghch05 inline std::string getCertificateFromReqBody( 558d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 5658eb238fSKowalski, Kamil const crow::Request& req) 5758eb238fSKowalski, Kamil { 581aa0c2b8SEd Tanous nlohmann::json reqJson; 591aa0c2b8SEd Tanous JsonParseResult ret = parseRequestAsJson(req, reqJson); 601aa0c2b8SEd Tanous if (ret != JsonParseResult::Success) 6158eb238fSKowalski, Kamil { 6258eb238fSKowalski, Kamil // We did not receive JSON request, proceed as it is RAW data 6333c6b580SEd Tanous return req.body(); 6458eb238fSKowalski, Kamil } 6558eb238fSKowalski, Kamil 6658eb238fSKowalski, Kamil std::string certificate; 6758eb238fSKowalski, Kamil std::optional<std::string> certificateType = "PEM"; 6858eb238fSKowalski, Kamil 6915ed6780SWilly Tu if (!json_util::readJsonPatch(req, asyncResp->res, "CertificateString", 7015ed6780SWilly Tu certificate, "CertificateType", 7115ed6780SWilly Tu certificateType)) 7258eb238fSKowalski, Kamil { 7362598e31SEd Tanous BMCWEB_LOG_ERROR("Required parameters are missing"); 7458eb238fSKowalski, Kamil messages::internalError(asyncResp->res); 75abb93cddSEd Tanous return {}; 7658eb238fSKowalski, Kamil } 7758eb238fSKowalski, Kamil 7858eb238fSKowalski, Kamil if (*certificateType != "PEM") 7958eb238fSKowalski, Kamil { 8058eb238fSKowalski, Kamil messages::propertyValueNotInList(asyncResp->res, *certificateType, 8158eb238fSKowalski, Kamil "CertificateType"); 82abb93cddSEd Tanous return {}; 8358eb238fSKowalski, Kamil } 8458eb238fSKowalski, Kamil 8558eb238fSKowalski, Kamil return certificate; 8658eb238fSKowalski, Kamil } 8758eb238fSKowalski, Kamil 885968caeeSMarri Devender Rao /** 895968caeeSMarri Devender Rao * Class to create a temporary certificate file for uploading to system 905968caeeSMarri Devender Rao */ 915968caeeSMarri Devender Rao class CertificateFile 925968caeeSMarri Devender Rao { 935968caeeSMarri Devender Rao public: 945968caeeSMarri Devender Rao CertificateFile() = delete; 955968caeeSMarri Devender Rao CertificateFile(const CertificateFile&) = delete; 965968caeeSMarri Devender Rao CertificateFile& operator=(const CertificateFile&) = delete; 975968caeeSMarri Devender Rao CertificateFile(CertificateFile&&) = delete; 985968caeeSMarri Devender Rao CertificateFile& operator=(CertificateFile&&) = delete; 994e23a444SEd Tanous explicit CertificateFile(const std::string& certString) 1005968caeeSMarri Devender Rao { 10172d52d25SEd Tanous std::array<char, 18> dirTemplate = {'/', 't', 'm', 'p', '/', 'C', 1025207438cSEd Tanous 'e', 'r', 't', 's', '.', 'X', 1035207438cSEd Tanous 'X', 'X', 'X', 'X', 'X', '\0'}; 1045207438cSEd Tanous char* tempDirectory = mkdtemp(dirTemplate.data()); 105e662eae8SEd Tanous if (tempDirectory != nullptr) 1065968caeeSMarri Devender Rao { 1075968caeeSMarri Devender Rao certDirectory = tempDirectory; 1085968caeeSMarri Devender Rao certificateFile = certDirectory / "cert.pem"; 1095968caeeSMarri Devender Rao std::ofstream out(certificateFile, std::ofstream::out | 1105968caeeSMarri Devender Rao std::ofstream::binary | 1115968caeeSMarri Devender Rao std::ofstream::trunc); 1125968caeeSMarri Devender Rao out << certString; 1135968caeeSMarri Devender Rao out.close(); 11462598e31SEd Tanous BMCWEB_LOG_DEBUG("Creating certificate file{}", 11562598e31SEd Tanous certificateFile.string()); 1165968caeeSMarri Devender Rao } 1175968caeeSMarri Devender Rao } 1185968caeeSMarri Devender Rao ~CertificateFile() 1195968caeeSMarri Devender Rao { 1205968caeeSMarri Devender Rao if (std::filesystem::exists(certDirectory)) 1215968caeeSMarri Devender Rao { 12262598e31SEd Tanous BMCWEB_LOG_DEBUG("Removing certificate file{}", 12362598e31SEd Tanous certificateFile.string()); 12423a21a1cSEd Tanous std::error_code ec; 12523a21a1cSEd Tanous std::filesystem::remove_all(certDirectory, ec); 12623a21a1cSEd Tanous if (ec) 1275968caeeSMarri Devender Rao { 12862598e31SEd Tanous BMCWEB_LOG_ERROR("Failed to remove temp directory{}", 12962598e31SEd Tanous certDirectory.string()); 1305968caeeSMarri Devender Rao } 1315968caeeSMarri Devender Rao } 1325968caeeSMarri Devender Rao } 1335968caeeSMarri Devender Rao std::string getCertFilePath() 1345968caeeSMarri Devender Rao { 1355968caeeSMarri Devender Rao return certificateFile; 1365968caeeSMarri Devender Rao } 1375968caeeSMarri Devender Rao 1385968caeeSMarri Devender Rao private: 1395968caeeSMarri Devender Rao std::filesystem::path certificateFile; 1405968caeeSMarri Devender Rao std::filesystem::path certDirectory; 1415968caeeSMarri Devender Rao }; 1425968caeeSMarri Devender Rao 1435968caeeSMarri Devender Rao /** 1444e0453b1SGunnar Mills * @brief Parse and update Certificate Issue/Subject property 1455968caeeSMarri Devender Rao * 1465968caeeSMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 1475968caeeSMarri Devender Rao * @param[in] str Issuer/Subject value in key=value pairs 1485968caeeSMarri Devender Rao * @param[in] type Issuer/Subject 1495968caeeSMarri Devender Rao * @return None 1505968caeeSMarri Devender Rao */ 1515968caeeSMarri Devender Rao static void updateCertIssuerOrSubject(nlohmann::json& out, 15226ccae32SEd Tanous std::string_view value) 1535968caeeSMarri Devender Rao { 1545968caeeSMarri Devender Rao // example: O=openbmc-project.xyz,CN=localhost 1555968caeeSMarri Devender Rao std::string_view::iterator i = value.begin(); 1565968caeeSMarri Devender Rao while (i != value.end()) 1575968caeeSMarri Devender Rao { 1585968caeeSMarri Devender Rao std::string_view::iterator tokenBegin = i; 1595968caeeSMarri Devender Rao while (i != value.end() && *i != '=') 1605968caeeSMarri Devender Rao { 1616da47babSPatrick Williams std::advance(i, 1); 1625968caeeSMarri Devender Rao } 1635968caeeSMarri Devender Rao if (i == value.end()) 1645968caeeSMarri Devender Rao { 1655968caeeSMarri Devender Rao break; 1665968caeeSMarri Devender Rao } 16726ccae32SEd Tanous std::string_view key(tokenBegin, static_cast<size_t>(i - tokenBegin)); 1686da47babSPatrick Williams std::advance(i, 1); 1695968caeeSMarri Devender Rao tokenBegin = i; 1705968caeeSMarri Devender Rao while (i != value.end() && *i != ',') 1715968caeeSMarri Devender Rao { 1726da47babSPatrick Williams std::advance(i, 1); 1735968caeeSMarri Devender Rao } 17426ccae32SEd Tanous std::string_view val(tokenBegin, static_cast<size_t>(i - tokenBegin)); 1755968caeeSMarri Devender Rao if (key == "L") 1765968caeeSMarri Devender Rao { 1775968caeeSMarri Devender Rao out["City"] = val; 1785968caeeSMarri Devender Rao } 1795968caeeSMarri Devender Rao else if (key == "CN") 1805968caeeSMarri Devender Rao { 1815968caeeSMarri Devender Rao out["CommonName"] = val; 1825968caeeSMarri Devender Rao } 1835968caeeSMarri Devender Rao else if (key == "C") 1845968caeeSMarri Devender Rao { 1855968caeeSMarri Devender Rao out["Country"] = val; 1865968caeeSMarri Devender Rao } 1875968caeeSMarri Devender Rao else if (key == "O") 1885968caeeSMarri Devender Rao { 1895968caeeSMarri Devender Rao out["Organization"] = val; 1905968caeeSMarri Devender Rao } 1915968caeeSMarri Devender Rao else if (key == "OU") 1925968caeeSMarri Devender Rao { 1935968caeeSMarri Devender Rao out["OrganizationalUnit"] = val; 1945968caeeSMarri Devender Rao } 1955968caeeSMarri Devender Rao else if (key == "ST") 1965968caeeSMarri Devender Rao { 1975968caeeSMarri Devender Rao out["State"] = val; 1985968caeeSMarri Devender Rao } 1995968caeeSMarri Devender Rao // skip comma character 2005968caeeSMarri Devender Rao if (i != value.end()) 2015968caeeSMarri Devender Rao { 2026da47babSPatrick Williams std::advance(i, 1); 2035968caeeSMarri Devender Rao } 2045968caeeSMarri Devender Rao } 2055968caeeSMarri Devender Rao } 2065968caeeSMarri Devender Rao 2075968caeeSMarri Devender Rao /** 208d3f92ce7SJiaqing Zhao * @brief Retrieve the installed certificate list 209d3f92ce7SJiaqing Zhao * 210d3f92ce7SJiaqing Zhao * @param[in] asyncResp Shared pointer to the response message 211d3f92ce7SJiaqing Zhao * @param[in] basePath DBus object path to search 212d3f92ce7SJiaqing Zhao * @param[in] listPtr Json pointer to the list in asyncResp 213d3f92ce7SJiaqing Zhao * @param[in] countPtr Json pointer to the count in asyncResp 214d3f92ce7SJiaqing Zhao * @return None 215d3f92ce7SJiaqing Zhao */ 216d3f92ce7SJiaqing Zhao static void 217d3f92ce7SJiaqing Zhao getCertificateList(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 218d3f92ce7SJiaqing Zhao const std::string& basePath, 219d3f92ce7SJiaqing Zhao const nlohmann::json::json_pointer& listPtr, 220d3f92ce7SJiaqing Zhao const nlohmann::json::json_pointer& countPtr) 221d3f92ce7SJiaqing Zhao { 2227a1dbc48SGeorge Liu constexpr std::array<std::string_view, 1> interfaces = { 2237a1dbc48SGeorge Liu certs::certPropIntf}; 2247a1dbc48SGeorge Liu dbus::utility::getSubTreePaths( 2257a1dbc48SGeorge Liu basePath, 0, interfaces, 226d3f92ce7SJiaqing Zhao [asyncResp, listPtr, countPtr]( 2277a1dbc48SGeorge Liu const boost::system::error_code& ec, 228d3f92ce7SJiaqing Zhao const dbus::utility::MapperGetSubTreePathsResponse& certPaths) { 229d3f92ce7SJiaqing Zhao if (ec) 230d3f92ce7SJiaqing Zhao { 23162598e31SEd Tanous BMCWEB_LOG_ERROR("Certificate collection query failed: {}", ec); 232d3f92ce7SJiaqing Zhao messages::internalError(asyncResp->res); 233d3f92ce7SJiaqing Zhao return; 234d3f92ce7SJiaqing Zhao } 235d3f92ce7SJiaqing Zhao 236d3f92ce7SJiaqing Zhao nlohmann::json& links = asyncResp->res.jsonValue[listPtr]; 237d3f92ce7SJiaqing Zhao links = nlohmann::json::array(); 238d3f92ce7SJiaqing Zhao for (const auto& certPath : certPaths) 239d3f92ce7SJiaqing Zhao { 240d3f92ce7SJiaqing Zhao sdbusplus::message::object_path objPath(certPath); 241d3f92ce7SJiaqing Zhao std::string certId = objPath.filename(); 242d3f92ce7SJiaqing Zhao if (certId.empty()) 243d3f92ce7SJiaqing Zhao { 24462598e31SEd Tanous BMCWEB_LOG_ERROR("Invalid certificate objPath {}", certPath); 245d3f92ce7SJiaqing Zhao continue; 246d3f92ce7SJiaqing Zhao } 247d3f92ce7SJiaqing Zhao 248d3f92ce7SJiaqing Zhao boost::urls::url certURL; 249d3f92ce7SJiaqing Zhao if (objPath.parent_path() == certs::httpsObjectPath) 250d3f92ce7SJiaqing Zhao { 251ef4c65b7SEd Tanous certURL = boost::urls::format( 252ef4c65b7SEd Tanous "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/{}", 253ef4c65b7SEd Tanous certId); 254d3f92ce7SJiaqing Zhao } 255d3f92ce7SJiaqing Zhao else if (objPath.parent_path() == certs::ldapObjectPath) 256d3f92ce7SJiaqing Zhao { 257ef4c65b7SEd Tanous certURL = boost::urls::format( 258ef4c65b7SEd Tanous "/redfish/v1/AccountService/LDAP/Certificates/{}", certId); 259d3f92ce7SJiaqing Zhao } 260d3f92ce7SJiaqing Zhao else if (objPath.parent_path() == certs::authorityObjectPath) 261d3f92ce7SJiaqing Zhao { 262ef4c65b7SEd Tanous certURL = boost::urls::format( 263ef4c65b7SEd Tanous "/redfish/v1/Managers/bmc/Truststore/Certificates/{}", 264ef4c65b7SEd Tanous certId); 265d3f92ce7SJiaqing Zhao } 266d3f92ce7SJiaqing Zhao else 267d3f92ce7SJiaqing Zhao { 268d3f92ce7SJiaqing Zhao continue; 269d3f92ce7SJiaqing Zhao } 270d3f92ce7SJiaqing Zhao 271d3f92ce7SJiaqing Zhao nlohmann::json::object_t link; 272d3f92ce7SJiaqing Zhao link["@odata.id"] = certURL; 273d3f92ce7SJiaqing Zhao links.emplace_back(std::move(link)); 274d3f92ce7SJiaqing Zhao } 275d3f92ce7SJiaqing Zhao 276d3f92ce7SJiaqing Zhao asyncResp->res.jsonValue[countPtr] = links.size(); 2777a1dbc48SGeorge Liu }); 278d3f92ce7SJiaqing Zhao } 279d3f92ce7SJiaqing Zhao 280d3f92ce7SJiaqing Zhao /** 2815968caeeSMarri Devender Rao * @brief Retrieve the certificates properties and append to the response 2825968caeeSMarri Devender Rao * message 2835968caeeSMarri Devender Rao * 2845968caeeSMarri Devender Rao * @param[in] asyncResp Shared pointer to the response message 2855968caeeSMarri Devender Rao * @param[in] objectPath Path of the D-Bus service object 2865968caeeSMarri Devender Rao * @param[in] certId Id of the certificate 2875968caeeSMarri Devender Rao * @param[in] certURL URL of the certificate object 2885968caeeSMarri Devender Rao * @param[in] name name of the certificate 2895968caeeSMarri Devender Rao * @return None 2905968caeeSMarri Devender Rao */ 2915968caeeSMarri Devender Rao static void getCertificateProperties( 2928d1b46d7Szhanghch05 const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 293e19e97e2SJiaqing Zhao const std::string& objectPath, const std::string& service, 2941e312598SJiaqing Zhao const std::string& certId, const boost::urls::url& certURL, 295e19e97e2SJiaqing Zhao const std::string& name) 2965968caeeSMarri Devender Rao { 29762598e31SEd Tanous BMCWEB_LOG_DEBUG("getCertificateProperties Path={} certId={} certURl={}", 29862598e31SEd Tanous objectPath, certId, certURL); 2999b12d1f9SKrzysztof Grobelny sdbusplus::asio::getAllProperties( 3009b12d1f9SKrzysztof Grobelny *crow::connections::systemBus, service, objectPath, certs::certPropIntf, 301b9d36b47SEd Tanous [asyncResp, certURL, certId, 3025e7e2dc5SEd Tanous name](const boost::system::error_code& ec, 303b9d36b47SEd Tanous const dbus::utility::DBusPropertiesMap& properties) { 3045968caeeSMarri Devender Rao if (ec) 3055968caeeSMarri Devender Rao { 30662598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error: {}", ec); 307d8a5d5d8SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "Certificate", certId); 3085968caeeSMarri Devender Rao return; 3095968caeeSMarri Devender Rao } 3109b12d1f9SKrzysztof Grobelny 3119b12d1f9SKrzysztof Grobelny const std::string* certificateString = nullptr; 3129b12d1f9SKrzysztof Grobelny const std::vector<std::string>* keyUsage = nullptr; 3139b12d1f9SKrzysztof Grobelny const std::string* issuer = nullptr; 3149b12d1f9SKrzysztof Grobelny const std::string* subject = nullptr; 3159b12d1f9SKrzysztof Grobelny const uint64_t* validNotAfter = nullptr; 3169b12d1f9SKrzysztof Grobelny const uint64_t* validNotBefore = nullptr; 3179b12d1f9SKrzysztof Grobelny 3189b12d1f9SKrzysztof Grobelny const bool success = sdbusplus::unpackPropertiesNoThrow( 3199b12d1f9SKrzysztof Grobelny dbus_utils::UnpackErrorPrinter(), properties, "CertificateString", 3209b12d1f9SKrzysztof Grobelny certificateString, "KeyUsage", keyUsage, "Issuer", issuer, 3219b12d1f9SKrzysztof Grobelny "Subject", subject, "ValidNotAfter", validNotAfter, 3229b12d1f9SKrzysztof Grobelny "ValidNotBefore", validNotBefore); 3239b12d1f9SKrzysztof Grobelny 3249b12d1f9SKrzysztof Grobelny if (!success) 3259b12d1f9SKrzysztof Grobelny { 3269b12d1f9SKrzysztof Grobelny messages::internalError(asyncResp->res); 3279b12d1f9SKrzysztof Grobelny return; 3289b12d1f9SKrzysztof Grobelny } 3299b12d1f9SKrzysztof Grobelny 3301476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = certURL; 3311476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 3321476687dSEd Tanous "#Certificate.v1_0_0.Certificate"; 333e19e97e2SJiaqing Zhao asyncResp->res.jsonValue["Id"] = certId; 3341476687dSEd Tanous asyncResp->res.jsonValue["Name"] = name; 3351476687dSEd Tanous asyncResp->res.jsonValue["Description"] = name; 3365968caeeSMarri Devender Rao asyncResp->res.jsonValue["CertificateString"] = ""; 3379b12d1f9SKrzysztof Grobelny asyncResp->res.jsonValue["KeyUsage"] = nlohmann::json::array(); 3389b12d1f9SKrzysztof Grobelny 3399b12d1f9SKrzysztof Grobelny if (certificateString != nullptr) 3405968caeeSMarri Devender Rao { 3419b12d1f9SKrzysztof Grobelny asyncResp->res.jsonValue["CertificateString"] = *certificateString; 3425968caeeSMarri Devender Rao } 3439b12d1f9SKrzysztof Grobelny 3449b12d1f9SKrzysztof Grobelny if (keyUsage != nullptr) 3455968caeeSMarri Devender Rao { 3469b12d1f9SKrzysztof Grobelny asyncResp->res.jsonValue["KeyUsage"] = *keyUsage; 3475968caeeSMarri Devender Rao } 3489b12d1f9SKrzysztof Grobelny 3499b12d1f9SKrzysztof Grobelny if (issuer != nullptr) 3505968caeeSMarri Devender Rao { 3519b12d1f9SKrzysztof Grobelny updateCertIssuerOrSubject(asyncResp->res.jsonValue["Issuer"], 3529b12d1f9SKrzysztof Grobelny *issuer); 3535968caeeSMarri Devender Rao } 3549b12d1f9SKrzysztof Grobelny 3559b12d1f9SKrzysztof Grobelny if (subject != nullptr) 3565968caeeSMarri Devender Rao { 3579b12d1f9SKrzysztof Grobelny updateCertIssuerOrSubject(asyncResp->res.jsonValue["Subject"], 3589b12d1f9SKrzysztof Grobelny *subject); 3595968caeeSMarri Devender Rao } 3609b12d1f9SKrzysztof Grobelny 3619b12d1f9SKrzysztof Grobelny if (validNotAfter != nullptr) 3625968caeeSMarri Devender Rao { 3635968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotAfter"] = 3649b12d1f9SKrzysztof Grobelny redfish::time_utils::getDateTimeUint(*validNotAfter); 3655968caeeSMarri Devender Rao } 3669b12d1f9SKrzysztof Grobelny 3679b12d1f9SKrzysztof Grobelny if (validNotBefore != nullptr) 3685968caeeSMarri Devender Rao { 3695968caeeSMarri Devender Rao asyncResp->res.jsonValue["ValidNotBefore"] = 3709b12d1f9SKrzysztof Grobelny redfish::time_utils::getDateTimeUint(*validNotBefore); 3715968caeeSMarri Devender Rao } 3729b12d1f9SKrzysztof Grobelny 3731e312598SJiaqing Zhao asyncResp->res.addHeader( 374d9f6c621SEd Tanous boost::beast::http::field::location, 375d9f6c621SEd Tanous std::string_view(certURL.data(), certURL.size())); 3769b12d1f9SKrzysztof Grobelny }); 3775968caeeSMarri Devender Rao } 3785968caeeSMarri Devender Rao 3797a3a8f7aSJiaqing Zhao static void 3807a3a8f7aSJiaqing Zhao deleteCertificate(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 3817a3a8f7aSJiaqing Zhao const std::string& service, 3827a3a8f7aSJiaqing Zhao const sdbusplus::message::object_path& objectPath) 3837a3a8f7aSJiaqing Zhao { 3847a3a8f7aSJiaqing Zhao crow::connections::systemBus->async_method_call( 3857a3a8f7aSJiaqing Zhao [asyncResp, 3865e7e2dc5SEd Tanous id{objectPath.filename()}](const boost::system::error_code& ec) { 3877a3a8f7aSJiaqing Zhao if (ec) 3887a3a8f7aSJiaqing Zhao { 3897a3a8f7aSJiaqing Zhao messages::resourceNotFound(asyncResp->res, "Certificate", id); 3907a3a8f7aSJiaqing Zhao return; 3917a3a8f7aSJiaqing Zhao } 39262598e31SEd Tanous BMCWEB_LOG_INFO("Certificate deleted"); 3937a3a8f7aSJiaqing Zhao asyncResp->res.result(boost::beast::http::status::no_content); 3947a3a8f7aSJiaqing Zhao }, 3957a3a8f7aSJiaqing Zhao service, objectPath, certs::objDeleteIntf, "Delete"); 3967a3a8f7aSJiaqing Zhao } 3977a3a8f7aSJiaqing Zhao 398828252d5SJiaqing Zhao inline void handleCertificateServiceGet( 399828252d5SJiaqing Zhao App& app, const crow::Request& req, 400828252d5SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 4015968caeeSMarri Devender Rao { 402828252d5SJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 403828252d5SJiaqing Zhao { 404828252d5SJiaqing Zhao return; 405828252d5SJiaqing Zhao } 406828252d5SJiaqing Zhao 4073e72c202SNinad Palsule if (req.session == nullptr) 4083e72c202SNinad Palsule { 4093e72c202SNinad Palsule messages::internalError(asyncResp->res); 4103e72c202SNinad Palsule return; 4113e72c202SNinad Palsule } 4123e72c202SNinad Palsule 413828252d5SJiaqing Zhao asyncResp->res.jsonValue["@odata.type"] = 414828252d5SJiaqing Zhao "#CertificateService.v1_0_0.CertificateService"; 415828252d5SJiaqing Zhao asyncResp->res.jsonValue["@odata.id"] = "/redfish/v1/CertificateService"; 416828252d5SJiaqing Zhao asyncResp->res.jsonValue["Id"] = "CertificateService"; 417828252d5SJiaqing Zhao asyncResp->res.jsonValue["Name"] = "Certificate Service"; 418828252d5SJiaqing Zhao asyncResp->res.jsonValue["Description"] = 419828252d5SJiaqing Zhao "Actions available to manage certificates"; 420828252d5SJiaqing Zhao // /redfish/v1/CertificateService/CertificateLocations is something 421828252d5SJiaqing Zhao // only ConfigureManager can access then only display when the user 422828252d5SJiaqing Zhao // has permissions ConfigureManager 423828252d5SJiaqing Zhao Privileges effectiveUserPrivileges = 4243e72c202SNinad Palsule redfish::getUserPrivileges(*req.session); 425828252d5SJiaqing Zhao if (isOperationAllowedWithPrivileges({{"ConfigureManager"}}, 426828252d5SJiaqing Zhao effectiveUserPrivileges)) 427828252d5SJiaqing Zhao { 428828252d5SJiaqing Zhao asyncResp->res.jsonValue["CertificateLocations"]["@odata.id"] = 429828252d5SJiaqing Zhao "/redfish/v1/CertificateService/CertificateLocations"; 430828252d5SJiaqing Zhao } 431828252d5SJiaqing Zhao nlohmann::json& actions = asyncResp->res.jsonValue["Actions"]; 432828252d5SJiaqing Zhao nlohmann::json& replace = actions["#CertificateService.ReplaceCertificate"]; 433828252d5SJiaqing Zhao replace["target"] = 434828252d5SJiaqing Zhao "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate"; 435828252d5SJiaqing Zhao nlohmann::json::array_t allowed; 436ad539545SPatrick Williams allowed.emplace_back("PEM"); 437828252d5SJiaqing Zhao replace["CertificateType@Redfish.AllowableValues"] = std::move(allowed); 438828252d5SJiaqing Zhao actions["#CertificateService.GenerateCSR"]["target"] = 439828252d5SJiaqing Zhao "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR"; 440828252d5SJiaqing Zhao } 441828252d5SJiaqing Zhao 442828252d5SJiaqing Zhao inline void handleCertificateLocationsGet( 443828252d5SJiaqing Zhao App& app, const crow::Request& req, 444828252d5SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 445828252d5SJiaqing Zhao { 446828252d5SJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 447828252d5SJiaqing Zhao { 448828252d5SJiaqing Zhao return; 449828252d5SJiaqing Zhao } 450828252d5SJiaqing Zhao asyncResp->res.jsonValue["@odata.id"] = 451828252d5SJiaqing Zhao "/redfish/v1/CertificateService/CertificateLocations"; 452828252d5SJiaqing Zhao asyncResp->res.jsonValue["@odata.type"] = 453828252d5SJiaqing Zhao "#CertificateLocations.v1_0_0.CertificateLocations"; 454828252d5SJiaqing Zhao asyncResp->res.jsonValue["Name"] = "Certificate Locations"; 455828252d5SJiaqing Zhao asyncResp->res.jsonValue["Id"] = "CertificateLocations"; 456828252d5SJiaqing Zhao asyncResp->res.jsonValue["Description"] = 457828252d5SJiaqing Zhao "Defines a resource that an administrator can use in order to " 458828252d5SJiaqing Zhao "locate all certificates installed on a given service"; 459828252d5SJiaqing Zhao 460828252d5SJiaqing Zhao getCertificateList(asyncResp, certs::baseObjectPath, 461828252d5SJiaqing Zhao "/Links/Certificates"_json_pointer, 462828252d5SJiaqing Zhao "/Links/Certificates@odata.count"_json_pointer); 463828252d5SJiaqing Zhao } 464828252d5SJiaqing Zhao 465828252d5SJiaqing Zhao inline void handleReplaceCertificateAction( 466828252d5SJiaqing Zhao App& app, const crow::Request& req, 467828252d5SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 468828252d5SJiaqing Zhao { 4693ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 47045ca1b86SEd Tanous { 47145ca1b86SEd Tanous return; 47245ca1b86SEd Tanous } 4735968caeeSMarri Devender Rao std::string certificate; 474*7a31e336SEd Tanous std::string certURI; 4755968caeeSMarri Devender Rao std::optional<std::string> certificateType = "PEM"; 4768d1b46d7Szhanghch05 477002d39b4SEd Tanous if (!json_util::readJsonAction(req, asyncResp->res, "CertificateString", 478*7a31e336SEd Tanous certificate, "CertificateUri/@odata.id", 479*7a31e336SEd Tanous certURI, "CertificateType", certificateType)) 4805968caeeSMarri Devender Rao { 48162598e31SEd Tanous BMCWEB_LOG_ERROR("Required parameters are missing"); 4825968caeeSMarri Devender Rao return; 4835968caeeSMarri Devender Rao } 4845968caeeSMarri Devender Rao 4855968caeeSMarri Devender Rao if (!certificateType) 4865968caeeSMarri Devender Rao { 4875968caeeSMarri Devender Rao // should never happen, but it never hurts to be paranoid. 4885968caeeSMarri Devender Rao return; 4895968caeeSMarri Devender Rao } 4905968caeeSMarri Devender Rao if (certificateType != "PEM") 4915968caeeSMarri Devender Rao { 492828252d5SJiaqing Zhao messages::actionParameterNotSupported(asyncResp->res, "CertificateType", 493828252d5SJiaqing Zhao "ReplaceCertificate"); 4945968caeeSMarri Devender Rao return; 4955968caeeSMarri Devender Rao } 4965968caeeSMarri Devender Rao 49762598e31SEd Tanous BMCWEB_LOG_INFO("Certificate URI to replace: {}", certURI); 4985968caeeSMarri Devender Rao 4996fd29553SEd Tanous boost::system::result<boost::urls::url> parsedUrl = 50075b63a2cSJiaqing Zhao boost::urls::parse_relative_ref(certURI); 50175b63a2cSJiaqing Zhao if (!parsedUrl) 5025968caeeSMarri Devender Rao { 503828252d5SJiaqing Zhao messages::actionParameterValueFormatError( 504828252d5SJiaqing Zhao asyncResp->res, certURI, "CertificateUri", "ReplaceCertificate"); 5055968caeeSMarri Devender Rao return; 5065968caeeSMarri Devender Rao } 50775b63a2cSJiaqing Zhao 50875b63a2cSJiaqing Zhao std::string id; 50975b63a2cSJiaqing Zhao sdbusplus::message::object_path objectPath; 5105968caeeSMarri Devender Rao std::string name; 51137cce918SMarri Devender Rao std::string service; 512828252d5SJiaqing Zhao if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1", "Managers", 513828252d5SJiaqing Zhao "bmc", "NetworkProtocol", "HTTPS", 514828252d5SJiaqing Zhao "Certificates", std::ref(id))) 5155968caeeSMarri Devender Rao { 51689492a15SPatrick Williams objectPath = sdbusplus::message::object_path(certs::httpsObjectPath) / 51789492a15SPatrick Williams id; 5185968caeeSMarri Devender Rao name = "HTTPS certificate"; 51937cce918SMarri Devender Rao service = certs::httpsServiceName; 52037cce918SMarri Devender Rao } 52175b63a2cSJiaqing Zhao else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1", 52275b63a2cSJiaqing Zhao "AccountService", "LDAP", 52375b63a2cSJiaqing Zhao "Certificates", std::ref(id))) 52437cce918SMarri Devender Rao { 52589492a15SPatrick Williams objectPath = sdbusplus::message::object_path(certs::ldapObjectPath) / 52689492a15SPatrick Williams id; 52737cce918SMarri Devender Rao name = "LDAP certificate"; 52837cce918SMarri Devender Rao service = certs::ldapServiceName; 5295968caeeSMarri Devender Rao } 53075b63a2cSJiaqing Zhao else if (crow::utility::readUrlSegments(*parsedUrl, "redfish", "v1", 53175b63a2cSJiaqing Zhao "Managers", "bmc", "Truststore", 53275b63a2cSJiaqing Zhao "Certificates", std::ref(id))) 533cfcd5f6bSMarri Devender Rao { 53475b63a2cSJiaqing Zhao objectPath = 535828252d5SJiaqing Zhao sdbusplus::message::object_path(certs::authorityObjectPath) / id; 536cfcd5f6bSMarri Devender Rao name = "TrustStore certificate"; 537cfcd5f6bSMarri Devender Rao service = certs::authorityServiceName; 538cfcd5f6bSMarri Devender Rao } 5395968caeeSMarri Devender Rao else 5405968caeeSMarri Devender Rao { 541828252d5SJiaqing Zhao messages::actionParameterNotSupported(asyncResp->res, "CertificateUri", 542828252d5SJiaqing Zhao "ReplaceCertificate"); 5435968caeeSMarri Devender Rao return; 5445968caeeSMarri Devender Rao } 5455968caeeSMarri Devender Rao 5465968caeeSMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 5475968caeeSMarri Devender Rao std::make_shared<CertificateFile>(certificate); 5485968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 5491e312598SJiaqing Zhao [asyncResp, certFile, objectPath, service, url{*parsedUrl}, id, 5505e7e2dc5SEd Tanous name](const boost::system::error_code& ec) { 5515968caeeSMarri Devender Rao if (ec) 5525968caeeSMarri Devender Rao { 55362598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error: {}", ec); 55490d2d1e8SJiaqing Zhao if (ec.value() == 55590d2d1e8SJiaqing Zhao boost::system::linux_error::bad_request_descriptor) 55690d2d1e8SJiaqing Zhao { 557828252d5SJiaqing Zhao messages::resourceNotFound(asyncResp->res, "Certificate", id); 5585968caeeSMarri Devender Rao return; 5595968caeeSMarri Devender Rao } 56090d2d1e8SJiaqing Zhao messages::internalError(asyncResp->res); 56190d2d1e8SJiaqing Zhao return; 56290d2d1e8SJiaqing Zhao } 563828252d5SJiaqing Zhao getCertificateProperties(asyncResp, objectPath, service, id, url, name); 56462598e31SEd Tanous BMCWEB_LOG_DEBUG("HTTPS certificate install file={}", 56562598e31SEd Tanous certFile->getCertFilePath()); 5665968caeeSMarri Devender Rao }, 5675968caeeSMarri Devender Rao service, objectPath, certs::certReplaceIntf, "Replace", 5685968caeeSMarri Devender Rao certFile->getCertFilePath()); 569828252d5SJiaqing Zhao } 5705968caeeSMarri Devender Rao 571cf9e417dSEd Tanous // NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables) 572828252d5SJiaqing Zhao static std::unique_ptr<sdbusplus::bus::match_t> csrMatcher; 5735968caeeSMarri Devender Rao /** 574828252d5SJiaqing Zhao * @brief Read data from CSR D-bus object and set to response 575828252d5SJiaqing Zhao * 576828252d5SJiaqing Zhao * @param[in] asyncResp Shared pointer to the response message 5778ece0e45SEd Tanous * @param[in] certURI Link to certificate collection URI 578828252d5SJiaqing Zhao * @param[in] service D-Bus service name 579828252d5SJiaqing Zhao * @param[in] certObjPath certificate D-Bus object path 580828252d5SJiaqing Zhao * @param[in] csrObjPath CSR D-Bus object path 581828252d5SJiaqing Zhao * @return None 5825968caeeSMarri Devender Rao */ 583828252d5SJiaqing Zhao static void getCSR(const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, 584828252d5SJiaqing Zhao const std::string& certURI, const std::string& service, 585828252d5SJiaqing Zhao const std::string& certObjPath, 586828252d5SJiaqing Zhao const std::string& csrObjPath) 5875968caeeSMarri Devender Rao { 58862598e31SEd Tanous BMCWEB_LOG_DEBUG("getCSR CertObjectPath{} CSRObjectPath={} service={}", 58962598e31SEd Tanous certObjPath, csrObjPath, service); 590828252d5SJiaqing Zhao crow::connections::systemBus->async_method_call( 5915e7e2dc5SEd Tanous [asyncResp, certURI](const boost::system::error_code& ec, 592828252d5SJiaqing Zhao const std::string& csr) { 593828252d5SJiaqing Zhao if (ec) 594828252d5SJiaqing Zhao { 59562598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error: {}", ec); 596828252d5SJiaqing Zhao messages::internalError(asyncResp->res); 597828252d5SJiaqing Zhao return; 598828252d5SJiaqing Zhao } 599828252d5SJiaqing Zhao if (csr.empty()) 600828252d5SJiaqing Zhao { 60162598e31SEd Tanous BMCWEB_LOG_ERROR("CSR read is empty"); 602828252d5SJiaqing Zhao messages::internalError(asyncResp->res); 603828252d5SJiaqing Zhao return; 604828252d5SJiaqing Zhao } 605828252d5SJiaqing Zhao asyncResp->res.jsonValue["CSRString"] = csr; 606828252d5SJiaqing Zhao asyncResp->res.jsonValue["CertificateCollection"]["@odata.id"] = 607828252d5SJiaqing Zhao certURI; 608828252d5SJiaqing Zhao }, 609828252d5SJiaqing Zhao service, csrObjPath, "xyz.openbmc_project.Certs.CSR", "CSR"); 610828252d5SJiaqing Zhao } 611828252d5SJiaqing Zhao 612828252d5SJiaqing Zhao inline void 613828252d5SJiaqing Zhao handleGenerateCSRAction(App& app, const crow::Request& req, 614828252d5SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 615828252d5SJiaqing Zhao { 6163ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 61745ca1b86SEd Tanous { 61845ca1b86SEd Tanous return; 61945ca1b86SEd Tanous } 620828252d5SJiaqing Zhao static const int rsaKeyBitLength = 2048; 6215968caeeSMarri Devender Rao 622828252d5SJiaqing Zhao // Required parameters 623828252d5SJiaqing Zhao std::string city; 624828252d5SJiaqing Zhao std::string commonName; 625828252d5SJiaqing Zhao std::string country; 626828252d5SJiaqing Zhao std::string organization; 627828252d5SJiaqing Zhao std::string organizationalUnit; 628828252d5SJiaqing Zhao std::string state; 629*7a31e336SEd Tanous std::string certURI; 630828252d5SJiaqing Zhao 631828252d5SJiaqing Zhao // Optional parameters 632828252d5SJiaqing Zhao std::optional<std::vector<std::string>> optAlternativeNames = 633828252d5SJiaqing Zhao std::vector<std::string>(); 634828252d5SJiaqing Zhao std::optional<std::string> optContactPerson = ""; 635828252d5SJiaqing Zhao std::optional<std::string> optChallengePassword = ""; 636828252d5SJiaqing Zhao std::optional<std::string> optEmail = ""; 637828252d5SJiaqing Zhao std::optional<std::string> optGivenName = ""; 638828252d5SJiaqing Zhao std::optional<std::string> optInitials = ""; 639828252d5SJiaqing Zhao std::optional<int64_t> optKeyBitLength = rsaKeyBitLength; 640828252d5SJiaqing Zhao std::optional<std::string> optKeyCurveId = "secp384r1"; 641828252d5SJiaqing Zhao std::optional<std::string> optKeyPairAlgorithm = "EC"; 642828252d5SJiaqing Zhao std::optional<std::vector<std::string>> optKeyUsage = 643828252d5SJiaqing Zhao std::vector<std::string>(); 644828252d5SJiaqing Zhao std::optional<std::string> optSurname = ""; 645828252d5SJiaqing Zhao std::optional<std::string> optUnstructuredName = ""; 646828252d5SJiaqing Zhao if (!json_util::readJsonAction( 647828252d5SJiaqing Zhao req, asyncResp->res, "City", city, "CommonName", commonName, 648828252d5SJiaqing Zhao "ContactPerson", optContactPerson, "Country", country, 649828252d5SJiaqing Zhao "Organization", organization, "OrganizationalUnit", 650*7a31e336SEd Tanous organizationalUnit, "State", state, 651*7a31e336SEd Tanous "CertificateCollection/@odata.id", certURI, "AlternativeNames", 652*7a31e336SEd Tanous optAlternativeNames, "ChallengePassword", optChallengePassword, 653*7a31e336SEd Tanous "Email", optEmail, "GivenName", optGivenName, "Initials", 654*7a31e336SEd Tanous optInitials, "KeyBitLength", optKeyBitLength, "KeyCurveId", 655*7a31e336SEd Tanous optKeyCurveId, "KeyPairAlgorithm", optKeyPairAlgorithm, "KeyUsage", 656*7a31e336SEd Tanous optKeyUsage, "Surname", optSurname, "UnstructuredName", 657*7a31e336SEd Tanous optUnstructuredName)) 658828252d5SJiaqing Zhao { 659828252d5SJiaqing Zhao return; 6605968caeeSMarri Devender Rao } 6615968caeeSMarri Devender Rao 662828252d5SJiaqing Zhao // bmcweb has no way to store or decode a private key challenge 663828252d5SJiaqing Zhao // password, which will likely cause bmcweb to crash on startup 664828252d5SJiaqing Zhao // if this is not set on a post so not allowing the user to set 665828252d5SJiaqing Zhao // value 666828252d5SJiaqing Zhao if (!optChallengePassword->empty()) 6675968caeeSMarri Devender Rao { 668828252d5SJiaqing Zhao messages::actionParameterNotSupported(asyncResp->res, "GenerateCSR", 669828252d5SJiaqing Zhao "ChallengePassword"); 670828252d5SJiaqing Zhao return; 671828252d5SJiaqing Zhao } 672828252d5SJiaqing Zhao 673828252d5SJiaqing Zhao std::string objectPath; 674828252d5SJiaqing Zhao std::string service; 675828252d5SJiaqing Zhao if (certURI.starts_with( 676828252d5SJiaqing Zhao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) 677828252d5SJiaqing Zhao { 678828252d5SJiaqing Zhao objectPath = certs::httpsObjectPath; 679828252d5SJiaqing Zhao service = certs::httpsServiceName; 680828252d5SJiaqing Zhao } 681828252d5SJiaqing Zhao else if (certURI.starts_with( 682828252d5SJiaqing Zhao "/redfish/v1/AccountService/LDAP/Certificates")) 683828252d5SJiaqing Zhao { 684828252d5SJiaqing Zhao objectPath = certs::ldapObjectPath; 685828252d5SJiaqing Zhao service = certs::ldapServiceName; 686828252d5SJiaqing Zhao } 687828252d5SJiaqing Zhao else 688828252d5SJiaqing Zhao { 689828252d5SJiaqing Zhao messages::actionParameterNotSupported( 690828252d5SJiaqing Zhao asyncResp->res, "CertificateCollection", "GenerateCSR"); 691828252d5SJiaqing Zhao return; 692828252d5SJiaqing Zhao } 693828252d5SJiaqing Zhao 694828252d5SJiaqing Zhao // supporting only EC and RSA algorithm 695828252d5SJiaqing Zhao if (*optKeyPairAlgorithm != "EC" && *optKeyPairAlgorithm != "RSA") 696828252d5SJiaqing Zhao { 697828252d5SJiaqing Zhao messages::actionParameterNotSupported( 698828252d5SJiaqing Zhao asyncResp->res, "KeyPairAlgorithm", "GenerateCSR"); 699828252d5SJiaqing Zhao return; 700828252d5SJiaqing Zhao } 701828252d5SJiaqing Zhao 702828252d5SJiaqing Zhao // supporting only 2048 key bit length for RSA algorithm due to 703828252d5SJiaqing Zhao // time consumed in generating private key 704828252d5SJiaqing Zhao if (*optKeyPairAlgorithm == "RSA" && *optKeyBitLength != rsaKeyBitLength) 705828252d5SJiaqing Zhao { 706e2616cc5SEd Tanous messages::propertyValueNotInList(asyncResp->res, *optKeyBitLength, 707e2616cc5SEd Tanous "KeyBitLength"); 708828252d5SJiaqing Zhao return; 709828252d5SJiaqing Zhao } 710828252d5SJiaqing Zhao 711828252d5SJiaqing Zhao // validate KeyUsage supporting only 1 type based on URL 712828252d5SJiaqing Zhao if (certURI.starts_with( 713828252d5SJiaqing Zhao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates")) 714828252d5SJiaqing Zhao { 715828252d5SJiaqing Zhao if (optKeyUsage->empty()) 716828252d5SJiaqing Zhao { 717b2ba3072SPatrick Williams optKeyUsage->emplace_back("ServerAuthentication"); 718828252d5SJiaqing Zhao } 719828252d5SJiaqing Zhao else if (optKeyUsage->size() == 1) 720828252d5SJiaqing Zhao { 721828252d5SJiaqing Zhao if ((*optKeyUsage)[0] != "ServerAuthentication") 722828252d5SJiaqing Zhao { 723828252d5SJiaqing Zhao messages::propertyValueNotInList(asyncResp->res, 724828252d5SJiaqing Zhao (*optKeyUsage)[0], "KeyUsage"); 725828252d5SJiaqing Zhao return; 726828252d5SJiaqing Zhao } 727828252d5SJiaqing Zhao } 728828252d5SJiaqing Zhao else 729828252d5SJiaqing Zhao { 730828252d5SJiaqing Zhao messages::actionParameterNotSupported(asyncResp->res, "KeyUsage", 731828252d5SJiaqing Zhao "GenerateCSR"); 732828252d5SJiaqing Zhao return; 733828252d5SJiaqing Zhao } 734828252d5SJiaqing Zhao } 735828252d5SJiaqing Zhao else if (certURI.starts_with( 736828252d5SJiaqing Zhao "/redfish/v1/AccountService/LDAP/Certificates")) 737828252d5SJiaqing Zhao { 738828252d5SJiaqing Zhao if (optKeyUsage->empty()) 739828252d5SJiaqing Zhao { 740b2ba3072SPatrick Williams optKeyUsage->emplace_back("ClientAuthentication"); 741828252d5SJiaqing Zhao } 742828252d5SJiaqing Zhao else if (optKeyUsage->size() == 1) 743828252d5SJiaqing Zhao { 744828252d5SJiaqing Zhao if ((*optKeyUsage)[0] != "ClientAuthentication") 745828252d5SJiaqing Zhao { 746828252d5SJiaqing Zhao messages::propertyValueNotInList(asyncResp->res, 747828252d5SJiaqing Zhao (*optKeyUsage)[0], "KeyUsage"); 748828252d5SJiaqing Zhao return; 749828252d5SJiaqing Zhao } 750828252d5SJiaqing Zhao } 751828252d5SJiaqing Zhao else 752828252d5SJiaqing Zhao { 753828252d5SJiaqing Zhao messages::actionParameterNotSupported(asyncResp->res, "KeyUsage", 754828252d5SJiaqing Zhao "GenerateCSR"); 755828252d5SJiaqing Zhao return; 756828252d5SJiaqing Zhao } 757828252d5SJiaqing Zhao } 758828252d5SJiaqing Zhao 759828252d5SJiaqing Zhao // Only allow one CSR matcher at a time so setting retry 760828252d5SJiaqing Zhao // time-out and timer expiry to 10 seconds for now. 761828252d5SJiaqing Zhao static const int timeOut = 10; 762828252d5SJiaqing Zhao if (csrMatcher) 763828252d5SJiaqing Zhao { 764828252d5SJiaqing Zhao messages::serviceTemporarilyUnavailable(asyncResp->res, 765828252d5SJiaqing Zhao std::to_string(timeOut)); 766828252d5SJiaqing Zhao return; 767828252d5SJiaqing Zhao } 768828252d5SJiaqing Zhao 769828252d5SJiaqing Zhao // Make this static so it survives outside this method 770828252d5SJiaqing Zhao static boost::asio::steady_timer timeout(*req.ioService); 771828252d5SJiaqing Zhao timeout.expires_after(std::chrono::seconds(timeOut)); 772828252d5SJiaqing Zhao timeout.async_wait([asyncResp](const boost::system::error_code& ec) { 773828252d5SJiaqing Zhao csrMatcher = nullptr; 774828252d5SJiaqing Zhao if (ec) 775828252d5SJiaqing Zhao { 776828252d5SJiaqing Zhao // operation_aborted is expected if timer is canceled 777828252d5SJiaqing Zhao // before completion. 778828252d5SJiaqing Zhao if (ec != boost::asio::error::operation_aborted) 779828252d5SJiaqing Zhao { 78062598e31SEd Tanous BMCWEB_LOG_ERROR("Async_wait failed {}", ec); 781828252d5SJiaqing Zhao } 782828252d5SJiaqing Zhao return; 783828252d5SJiaqing Zhao } 78462598e31SEd Tanous BMCWEB_LOG_ERROR("Timed out waiting for Generating CSR"); 785828252d5SJiaqing Zhao messages::internalError(asyncResp->res); 786828252d5SJiaqing Zhao }); 787828252d5SJiaqing Zhao 788828252d5SJiaqing Zhao // create a matcher to wait on CSR object 78962598e31SEd Tanous BMCWEB_LOG_DEBUG("create matcher with path {}", objectPath); 790828252d5SJiaqing Zhao std::string match("type='signal'," 791828252d5SJiaqing Zhao "interface='org.freedesktop.DBus.ObjectManager'," 792828252d5SJiaqing Zhao "path='" + 793828252d5SJiaqing Zhao objectPath + 794828252d5SJiaqing Zhao "'," 795828252d5SJiaqing Zhao "member='InterfacesAdded'"); 796828252d5SJiaqing Zhao csrMatcher = std::make_unique<sdbusplus::bus::match_t>( 797828252d5SJiaqing Zhao *crow::connections::systemBus, match, 798828252d5SJiaqing Zhao [asyncResp, service, objectPath, certURI](sdbusplus::message_t& m) { 799828252d5SJiaqing Zhao timeout.cancel(); 800828252d5SJiaqing Zhao if (m.is_method_error()) 801828252d5SJiaqing Zhao { 80262598e31SEd Tanous BMCWEB_LOG_ERROR("Dbus method error!!!"); 803828252d5SJiaqing Zhao messages::internalError(asyncResp->res); 804828252d5SJiaqing Zhao return; 805828252d5SJiaqing Zhao } 806828252d5SJiaqing Zhao 80780f79a40SMichael Shen dbus::utility::DBusInterfacesMap interfacesProperties; 808828252d5SJiaqing Zhao 809828252d5SJiaqing Zhao sdbusplus::message::object_path csrObjectPath; 810828252d5SJiaqing Zhao m.read(csrObjectPath, interfacesProperties); 81162598e31SEd Tanous BMCWEB_LOG_DEBUG("CSR object added{}", csrObjectPath.str); 812828252d5SJiaqing Zhao for (const auto& interface : interfacesProperties) 813828252d5SJiaqing Zhao { 814828252d5SJiaqing Zhao if (interface.first == "xyz.openbmc_project.Certs.CSR") 815828252d5SJiaqing Zhao { 816828252d5SJiaqing Zhao getCSR(asyncResp, certURI, service, objectPath, 817828252d5SJiaqing Zhao csrObjectPath.str); 818828252d5SJiaqing Zhao break; 819828252d5SJiaqing Zhao } 820828252d5SJiaqing Zhao } 821828252d5SJiaqing Zhao }); 822828252d5SJiaqing Zhao crow::connections::systemBus->async_method_call( 8235e7e2dc5SEd Tanous [asyncResp](const boost::system::error_code& ec, const std::string&) { 824828252d5SJiaqing Zhao if (ec) 825828252d5SJiaqing Zhao { 82662598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error: {}", ec.message()); 827828252d5SJiaqing Zhao messages::internalError(asyncResp->res); 828828252d5SJiaqing Zhao return; 829828252d5SJiaqing Zhao } 830828252d5SJiaqing Zhao }, 831828252d5SJiaqing Zhao service, objectPath, "xyz.openbmc_project.Certs.CSR.Create", 832828252d5SJiaqing Zhao "GenerateCSR", *optAlternativeNames, *optChallengePassword, city, 833828252d5SJiaqing Zhao commonName, *optContactPerson, country, *optEmail, *optGivenName, 834828252d5SJiaqing Zhao *optInitials, *optKeyBitLength, *optKeyCurveId, *optKeyPairAlgorithm, 835828252d5SJiaqing Zhao *optKeyUsage, organization, organizationalUnit, state, *optSurname, 836828252d5SJiaqing Zhao *optUnstructuredName); 837828252d5SJiaqing Zhao } 838828252d5SJiaqing Zhao 839828252d5SJiaqing Zhao inline void requestRoutesCertificateService(App& app) 840828252d5SJiaqing Zhao { 841828252d5SJiaqing Zhao BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/") 842828252d5SJiaqing Zhao .privileges(redfish::privileges::getCertificateService) 843002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 844828252d5SJiaqing Zhao std::bind_front(handleCertificateServiceGet, std::ref(app))); 845828252d5SJiaqing Zhao 846828252d5SJiaqing Zhao BMCWEB_ROUTE(app, "/redfish/v1/CertificateService/CertificateLocations/") 847828252d5SJiaqing Zhao .privileges(redfish::privileges::getCertificateLocations) 848828252d5SJiaqing Zhao .methods(boost::beast::http::verb::get)( 849828252d5SJiaqing Zhao std::bind_front(handleCertificateLocationsGet, std::ref(app))); 850828252d5SJiaqing Zhao 851828252d5SJiaqing Zhao BMCWEB_ROUTE( 852828252d5SJiaqing Zhao app, 853828252d5SJiaqing Zhao "/redfish/v1/CertificateService/Actions/CertificateService.ReplaceCertificate/") 854828252d5SJiaqing Zhao .privileges(redfish::privileges::postCertificateService) 855828252d5SJiaqing Zhao .methods(boost::beast::http::verb::post)( 856828252d5SJiaqing Zhao std::bind_front(handleReplaceCertificateAction, std::ref(app))); 857828252d5SJiaqing Zhao 858828252d5SJiaqing Zhao BMCWEB_ROUTE( 859828252d5SJiaqing Zhao app, 860828252d5SJiaqing Zhao "/redfish/v1/CertificateService/Actions/CertificateService.GenerateCSR/") 861828252d5SJiaqing Zhao .privileges(redfish::privileges::postCertificateService) 862828252d5SJiaqing Zhao .methods(boost::beast::http::verb::post)( 863828252d5SJiaqing Zhao std::bind_front(handleGenerateCSRAction, std::ref(app))); 864828252d5SJiaqing Zhao } // requestRoutesCertificateService 865828252d5SJiaqing Zhao 866828252d5SJiaqing Zhao inline void handleHTTPSCertificateCollectionGet( 867828252d5SJiaqing Zhao App& app, const crow::Request& req, 868828252d5SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 869828252d5SJiaqing Zhao { 8703ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 87145ca1b86SEd Tanous { 87245ca1b86SEd Tanous return; 87345ca1b86SEd Tanous } 8741476687dSEd Tanous 8751476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 8761476687dSEd Tanous "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates"; 8771476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 8781476687dSEd Tanous "#CertificateCollection.CertificateCollection"; 8791476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "HTTPS Certificates Collection"; 8801476687dSEd Tanous asyncResp->res.jsonValue["Description"] = 8811476687dSEd Tanous "A Collection of HTTPS certificate instances"; 8828d1b46d7Szhanghch05 883d3f92ce7SJiaqing Zhao getCertificateList(asyncResp, certs::httpsObjectPath, 884d3f92ce7SJiaqing Zhao "/Members"_json_pointer, 885d3f92ce7SJiaqing Zhao "/Members@odata.count"_json_pointer); 886828252d5SJiaqing Zhao } 8875968caeeSMarri Devender Rao 888828252d5SJiaqing Zhao inline void handleHTTPSCertificateCollectionPost( 889828252d5SJiaqing Zhao App& app, const crow::Request& req, 890828252d5SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 891828252d5SJiaqing Zhao { 8923ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 89345ca1b86SEd Tanous { 89445ca1b86SEd Tanous return; 89545ca1b86SEd Tanous } 89662598e31SEd Tanous BMCWEB_LOG_DEBUG("HTTPSCertificateCollection::doPost"); 8978d1b46d7Szhanghch05 8981476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "HTTPS Certificate"; 8991476687dSEd Tanous asyncResp->res.jsonValue["Description"] = "HTTPS Certificate"; 9005968caeeSMarri Devender Rao 901b2896149SEd Tanous std::string certHttpBody = getCertificateFromReqBody(asyncResp, req); 90258eb238fSKowalski, Kamil 903b2896149SEd Tanous if (certHttpBody.empty()) 90458eb238fSKowalski, Kamil { 90562598e31SEd Tanous BMCWEB_LOG_ERROR("Cannot get certificate from request body."); 906a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 90758eb238fSKowalski, Kamil return; 90858eb238fSKowalski, Kamil } 90958eb238fSKowalski, Kamil 9105968caeeSMarri Devender Rao std::shared_ptr<CertificateFile> certFile = 911b2896149SEd Tanous std::make_shared<CertificateFile>(certHttpBody); 9125968caeeSMarri Devender Rao 9135968caeeSMarri Devender Rao crow::connections::systemBus->async_method_call( 9145e7e2dc5SEd Tanous [asyncResp, certFile](const boost::system::error_code& ec, 915656ec7e3SZbigniew Kurzynski const std::string& objectPath) { 9165968caeeSMarri Devender Rao if (ec) 9175968caeeSMarri Devender Rao { 91862598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error: {}", ec); 9195968caeeSMarri Devender Rao messages::internalError(asyncResp->res); 9205968caeeSMarri Devender Rao return; 9215968caeeSMarri Devender Rao } 922717b9802SJiaqing Zhao 923717b9802SJiaqing Zhao sdbusplus::message::object_path path(objectPath); 924717b9802SJiaqing Zhao std::string certId = path.filename(); 925ef4c65b7SEd Tanous const boost::urls::url certURL = boost::urls::format( 926ef4c65b7SEd Tanous "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/{}", 927ef4c65b7SEd Tanous certId); 928828252d5SJiaqing Zhao getCertificateProperties(asyncResp, objectPath, certs::httpsServiceName, 929828252d5SJiaqing Zhao certId, certURL, "HTTPS Certificate"); 93062598e31SEd Tanous BMCWEB_LOG_DEBUG("HTTPS certificate install file={}", 93162598e31SEd Tanous certFile->getCertFilePath()); 9325968caeeSMarri Devender Rao }, 933828252d5SJiaqing Zhao certs::httpsServiceName, certs::httpsObjectPath, certs::certInstallIntf, 934828252d5SJiaqing Zhao "Install", certFile->getCertFilePath()); 935828252d5SJiaqing Zhao } 9365968caeeSMarri Devender Rao 937828252d5SJiaqing Zhao inline void handleHTTPSCertificateGet( 938828252d5SJiaqing Zhao App& app, const crow::Request& req, 939828252d5SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id) 9407e860f15SJohn Edward Broadbent { 9413ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 94245ca1b86SEd Tanous { 94345ca1b86SEd Tanous return; 94445ca1b86SEd Tanous } 9457e860f15SJohn Edward Broadbent 94662598e31SEd Tanous BMCWEB_LOG_DEBUG("HTTPS Certificate ID={}", id); 947ef4c65b7SEd Tanous const boost::urls::url certURL = boost::urls::format( 948ef4c65b7SEd Tanous "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/{}", id); 949828252d5SJiaqing Zhao std::string objPath = 950828252d5SJiaqing Zhao sdbusplus::message::object_path(certs::httpsObjectPath) / id; 951828252d5SJiaqing Zhao getCertificateProperties(asyncResp, objPath, certs::httpsServiceName, id, 952828252d5SJiaqing Zhao certURL, "HTTPS Certificate"); 9537e860f15SJohn Edward Broadbent } 95437cce918SMarri Devender Rao 955828252d5SJiaqing Zhao inline void requestRoutesHTTPSCertificate(App& app) 95637cce918SMarri Devender Rao { 957828252d5SJiaqing Zhao BMCWEB_ROUTE(app, 958828252d5SJiaqing Zhao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/") 959ed398213SEd Tanous .privileges(redfish::privileges::getCertificateCollection) 960828252d5SJiaqing Zhao .methods(boost::beast::http::verb::get)(std::bind_front( 961828252d5SJiaqing Zhao handleHTTPSCertificateCollectionGet, std::ref(app))); 962828252d5SJiaqing Zhao 963828252d5SJiaqing Zhao BMCWEB_ROUTE(app, 964828252d5SJiaqing Zhao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/") 965828252d5SJiaqing Zhao .privileges(redfish::privileges::postCertificateCollection) 966828252d5SJiaqing Zhao .methods(boost::beast::http::verb::post)(std::bind_front( 967828252d5SJiaqing Zhao handleHTTPSCertificateCollectionPost, std::ref(app))); 968828252d5SJiaqing Zhao 969828252d5SJiaqing Zhao BMCWEB_ROUTE( 970828252d5SJiaqing Zhao app, 971828252d5SJiaqing Zhao "/redfish/v1/Managers/bmc/NetworkProtocol/HTTPS/Certificates/<str>/") 972828252d5SJiaqing Zhao .privileges(redfish::privileges::getCertificate) 973002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 974828252d5SJiaqing Zhao std::bind_front(handleHTTPSCertificateGet, std::ref(app))); 975828252d5SJiaqing Zhao } 976828252d5SJiaqing Zhao 977828252d5SJiaqing Zhao inline void handleLDAPCertificateCollectionGet( 978828252d5SJiaqing Zhao App& app, const crow::Request& req, 979828252d5SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 980828252d5SJiaqing Zhao { 9813ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 98245ca1b86SEd Tanous { 98345ca1b86SEd Tanous return; 98445ca1b86SEd Tanous } 9851476687dSEd Tanous 9861476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 9871476687dSEd Tanous "/redfish/v1/AccountService/LDAP/Certificates"; 9881476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 9891476687dSEd Tanous "#CertificateCollection.CertificateCollection"; 9901476687dSEd Tanous asyncResp->res.jsonValue["Name"] = "LDAP Certificates Collection"; 9911476687dSEd Tanous asyncResp->res.jsonValue["Description"] = 9921476687dSEd Tanous "A Collection of LDAP certificate instances"; 9938d1b46d7Szhanghch05 994d3f92ce7SJiaqing Zhao getCertificateList(asyncResp, certs::ldapObjectPath, 995d3f92ce7SJiaqing Zhao "/Members"_json_pointer, 996d3f92ce7SJiaqing Zhao "/Members@odata.count"_json_pointer); 997828252d5SJiaqing Zhao } 99837cce918SMarri Devender Rao 999828252d5SJiaqing Zhao inline void handleLDAPCertificateCollectionPost( 1000828252d5SJiaqing Zhao App& app, const crow::Request& req, 1001828252d5SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1002828252d5SJiaqing Zhao { 10033ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 100445ca1b86SEd Tanous { 100545ca1b86SEd Tanous return; 100645ca1b86SEd Tanous } 1007b2896149SEd Tanous std::string certHttpBody = getCertificateFromReqBody(asyncResp, req); 100858eb238fSKowalski, Kamil 1009b2896149SEd Tanous if (certHttpBody.empty()) 101058eb238fSKowalski, Kamil { 101162598e31SEd Tanous BMCWEB_LOG_ERROR("Cannot get certificate from request body."); 1012a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 101358eb238fSKowalski, Kamil return; 101458eb238fSKowalski, Kamil } 101558eb238fSKowalski, Kamil 101658eb238fSKowalski, Kamil std::shared_ptr<CertificateFile> certFile = 1017b2896149SEd Tanous std::make_shared<CertificateFile>(certHttpBody); 101858eb238fSKowalski, Kamil 101937cce918SMarri Devender Rao crow::connections::systemBus->async_method_call( 10205e7e2dc5SEd Tanous [asyncResp, certFile](const boost::system::error_code& ec, 1021656ec7e3SZbigniew Kurzynski const std::string& objectPath) { 102237cce918SMarri Devender Rao if (ec) 102337cce918SMarri Devender Rao { 102462598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error: {}", ec); 102537cce918SMarri Devender Rao messages::internalError(asyncResp->res); 102637cce918SMarri Devender Rao return; 102737cce918SMarri Devender Rao } 1028717b9802SJiaqing Zhao 1029717b9802SJiaqing Zhao sdbusplus::message::object_path path(objectPath); 1030717b9802SJiaqing Zhao std::string certId = path.filename(); 1031ef4c65b7SEd Tanous const boost::urls::url certURL = boost::urls::format( 1032ef4c65b7SEd Tanous "/redfish/v1/AccountService/LDAP/Certificates/{}", certId); 1033828252d5SJiaqing Zhao getCertificateProperties(asyncResp, objectPath, certs::ldapServiceName, 1034828252d5SJiaqing Zhao certId, certURL, "LDAP Certificate"); 103562598e31SEd Tanous BMCWEB_LOG_DEBUG("LDAP certificate install file={}", 103662598e31SEd Tanous certFile->getCertFilePath()); 103737cce918SMarri Devender Rao }, 1038828252d5SJiaqing Zhao certs::ldapServiceName, certs::ldapObjectPath, certs::certInstallIntf, 1039828252d5SJiaqing Zhao "Install", certFile->getCertFilePath()); 1040828252d5SJiaqing Zhao } 104137cce918SMarri Devender Rao 1042828252d5SJiaqing Zhao inline void handleLDAPCertificateGet( 1043828252d5SJiaqing Zhao App& app, const crow::Request& req, 1044828252d5SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id) 104537cce918SMarri Devender Rao { 10463ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 104745ca1b86SEd Tanous { 104845ca1b86SEd Tanous return; 104945ca1b86SEd Tanous } 1050717b9802SJiaqing Zhao 105162598e31SEd Tanous BMCWEB_LOG_DEBUG("LDAP Certificate ID={}", id); 1052ef4c65b7SEd Tanous const boost::urls::url certURL = boost::urls::format( 1053ef4c65b7SEd Tanous "/redfish/v1/AccountService/LDAP/Certificates/{}", id); 1054717b9802SJiaqing Zhao std::string objPath = 1055717b9802SJiaqing Zhao sdbusplus::message::object_path(certs::ldapObjectPath) / id; 1056717b9802SJiaqing Zhao getCertificateProperties(asyncResp, objPath, certs::ldapServiceName, id, 1057717b9802SJiaqing Zhao certURL, "LDAP Certificate"); 1058828252d5SJiaqing Zhao } 1059828252d5SJiaqing Zhao 106099612247SJiaqing Zhao inline void handleLDAPCertificateDelete( 106199612247SJiaqing Zhao App& app, const crow::Request& req, 106299612247SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id) 106399612247SJiaqing Zhao { 106499612247SJiaqing Zhao if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 106599612247SJiaqing Zhao { 106699612247SJiaqing Zhao return; 106799612247SJiaqing Zhao } 106899612247SJiaqing Zhao 106962598e31SEd Tanous BMCWEB_LOG_DEBUG("Delete LDAP Certificate ID={}", id); 107099612247SJiaqing Zhao std::string objPath = 107199612247SJiaqing Zhao sdbusplus::message::object_path(certs::ldapObjectPath) / id; 107299612247SJiaqing Zhao 107399612247SJiaqing Zhao deleteCertificate(asyncResp, certs::ldapServiceName, objPath); 107499612247SJiaqing Zhao } 107599612247SJiaqing Zhao 1076828252d5SJiaqing Zhao inline void requestRoutesLDAPCertificate(App& app) 1077cfcd5f6bSMarri Devender Rao { 1078828252d5SJiaqing Zhao BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/") 1079828252d5SJiaqing Zhao .privileges(redfish::privileges::getCertificateCollection) 1080828252d5SJiaqing Zhao .methods(boost::beast::http::verb::get)( 1081828252d5SJiaqing Zhao std::bind_front(handleLDAPCertificateCollectionGet, std::ref(app))); 1082828252d5SJiaqing Zhao 1083828252d5SJiaqing Zhao BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/") 1084828252d5SJiaqing Zhao .privileges(redfish::privileges::postCertificateCollection) 1085828252d5SJiaqing Zhao .methods(boost::beast::http::verb::post)(std::bind_front( 1086828252d5SJiaqing Zhao handleLDAPCertificateCollectionPost, std::ref(app))); 1087828252d5SJiaqing Zhao 1088828252d5SJiaqing Zhao BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/") 1089ed398213SEd Tanous .privileges(redfish::privileges::getCertificate) 1090002d39b4SEd Tanous .methods(boost::beast::http::verb::get)( 1091828252d5SJiaqing Zhao std::bind_front(handleLDAPCertificateGet, std::ref(app))); 109299612247SJiaqing Zhao 109399612247SJiaqing Zhao BMCWEB_ROUTE(app, "/redfish/v1/AccountService/LDAP/Certificates/<str>/") 109499612247SJiaqing Zhao .privileges(redfish::privileges::deleteCertificate) 109599612247SJiaqing Zhao .methods(boost::beast::http::verb::delete_)( 109699612247SJiaqing Zhao std::bind_front(handleLDAPCertificateDelete, std::ref(app))); 1097828252d5SJiaqing Zhao } // requestRoutesLDAPCertificate 1098828252d5SJiaqing Zhao 1099828252d5SJiaqing Zhao inline void handleTrustStoreCertificateCollectionGet( 1100828252d5SJiaqing Zhao App& app, const crow::Request& req, 1101828252d5SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1102828252d5SJiaqing Zhao { 11033ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 110445ca1b86SEd Tanous { 110545ca1b86SEd Tanous return; 110645ca1b86SEd Tanous } 11071476687dSEd Tanous 11081476687dSEd Tanous asyncResp->res.jsonValue["@odata.id"] = 11091476687dSEd Tanous "/redfish/v1/Managers/bmc/Truststore/Certificates/"; 11101476687dSEd Tanous asyncResp->res.jsonValue["@odata.type"] = 11111476687dSEd Tanous "#CertificateCollection.CertificateCollection"; 1112002d39b4SEd Tanous asyncResp->res.jsonValue["Name"] = "TrustStore Certificates Collection"; 11131476687dSEd Tanous asyncResp->res.jsonValue["Description"] = 11141476687dSEd Tanous "A Collection of TrustStore certificate instances"; 11158d1b46d7Szhanghch05 1116d3f92ce7SJiaqing Zhao getCertificateList(asyncResp, certs::authorityObjectPath, 1117d3f92ce7SJiaqing Zhao "/Members"_json_pointer, 1118d3f92ce7SJiaqing Zhao "/Members@odata.count"_json_pointer); 1119828252d5SJiaqing Zhao } 1120cfcd5f6bSMarri Devender Rao 1121828252d5SJiaqing Zhao inline void handleTrustStoreCertificateCollectionPost( 1122828252d5SJiaqing Zhao App& app, const crow::Request& req, 1123828252d5SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) 1124828252d5SJiaqing Zhao { 11253ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 112645ca1b86SEd Tanous { 112745ca1b86SEd Tanous return; 112845ca1b86SEd Tanous } 1129b2896149SEd Tanous std::string certHttpBody = getCertificateFromReqBody(asyncResp, req); 1130a08752f5SZbigniew Kurzynski 1131b2896149SEd Tanous if (certHttpBody.empty()) 1132a08752f5SZbigniew Kurzynski { 113362598e31SEd Tanous BMCWEB_LOG_ERROR("Cannot get certificate from request body."); 1134a08752f5SZbigniew Kurzynski messages::unrecognizedRequestBody(asyncResp->res); 1135a08752f5SZbigniew Kurzynski return; 1136a08752f5SZbigniew Kurzynski } 1137a08752f5SZbigniew Kurzynski 1138a08752f5SZbigniew Kurzynski std::shared_ptr<CertificateFile> certFile = 1139b2896149SEd Tanous std::make_shared<CertificateFile>(certHttpBody); 1140cfcd5f6bSMarri Devender Rao crow::connections::systemBus->async_method_call( 11415e7e2dc5SEd Tanous [asyncResp, certFile](const boost::system::error_code& ec, 1142656ec7e3SZbigniew Kurzynski const std::string& objectPath) { 1143cfcd5f6bSMarri Devender Rao if (ec) 1144cfcd5f6bSMarri Devender Rao { 114562598e31SEd Tanous BMCWEB_LOG_ERROR("DBUS response error: {}", ec); 1146cfcd5f6bSMarri Devender Rao messages::internalError(asyncResp->res); 1147cfcd5f6bSMarri Devender Rao return; 1148cfcd5f6bSMarri Devender Rao } 1149656ec7e3SZbigniew Kurzynski 1150717b9802SJiaqing Zhao sdbusplus::message::object_path path(objectPath); 1151717b9802SJiaqing Zhao std::string certId = path.filename(); 1152ef4c65b7SEd Tanous const boost::urls::url certURL = boost::urls::format( 1153ef4c65b7SEd Tanous "/redfish/v1/Managers/bmc/Truststore/Certificates/{}", certId); 1154717b9802SJiaqing Zhao getCertificateProperties(asyncResp, objectPath, 1155828252d5SJiaqing Zhao certs::authorityServiceName, certId, certURL, 1156828252d5SJiaqing Zhao "TrustStore Certificate"); 115762598e31SEd Tanous BMCWEB_LOG_DEBUG("TrustStore certificate install file={}", 115862598e31SEd Tanous certFile->getCertFilePath()); 1159cfcd5f6bSMarri Devender Rao }, 1160cfcd5f6bSMarri Devender Rao certs::authorityServiceName, certs::authorityObjectPath, 11610fda0f12SGeorge Liu certs::certInstallIntf, "Install", certFile->getCertFilePath()); 1162828252d5SJiaqing Zhao } 1163cfcd5f6bSMarri Devender Rao 1164828252d5SJiaqing Zhao inline void handleTrustStoreCertificateGet( 1165828252d5SJiaqing Zhao App& app, const crow::Request& req, 1166828252d5SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id) 1167cfcd5f6bSMarri Devender Rao { 11683ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 116945ca1b86SEd Tanous { 117045ca1b86SEd Tanous return; 117145ca1b86SEd Tanous } 1172717b9802SJiaqing Zhao 117362598e31SEd Tanous BMCWEB_LOG_DEBUG("Truststore Certificate ID={}", id); 1174ef4c65b7SEd Tanous const boost::urls::url certURL = boost::urls::format( 1175ef4c65b7SEd Tanous "/redfish/v1/Managers/bmc/Truststore/Certificates/{}", id); 1176717b9802SJiaqing Zhao std::string objPath = 1177717b9802SJiaqing Zhao sdbusplus::message::object_path(certs::authorityObjectPath) / id; 1178828252d5SJiaqing Zhao getCertificateProperties(asyncResp, objPath, certs::authorityServiceName, 1179828252d5SJiaqing Zhao id, certURL, "TrustStore Certificate"); 1180828252d5SJiaqing Zhao } 118107a60299SZbigniew Kurzynski 1182828252d5SJiaqing Zhao inline void handleTrustStoreCertificateDelete( 1183828252d5SJiaqing Zhao App& app, const crow::Request& req, 1184828252d5SJiaqing Zhao const std::shared_ptr<bmcweb::AsyncResp>& asyncResp, const std::string& id) 1185828252d5SJiaqing Zhao { 11863ba00073SCarson Labrado if (!redfish::setUpRedfishRoute(app, req, asyncResp)) 118745ca1b86SEd Tanous { 118845ca1b86SEd Tanous return; 118945ca1b86SEd Tanous } 119007a60299SZbigniew Kurzynski 119162598e31SEd Tanous BMCWEB_LOG_DEBUG("Delete TrustStore Certificate ID={}", id); 1192717b9802SJiaqing Zhao std::string objPath = 1193717b9802SJiaqing Zhao sdbusplus::message::object_path(certs::authorityObjectPath) / id; 119407a60299SZbigniew Kurzynski 11957a3a8f7aSJiaqing Zhao deleteCertificate(asyncResp, certs::authorityServiceName, objPath); 1196828252d5SJiaqing Zhao } 1197828252d5SJiaqing Zhao 1198828252d5SJiaqing Zhao inline void requestRoutesTrustStoreCertificate(App& app) 1199828252d5SJiaqing Zhao { 1200828252d5SJiaqing Zhao BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/") 1201828252d5SJiaqing Zhao .privileges(redfish::privileges::getCertificate) 1202828252d5SJiaqing Zhao .methods(boost::beast::http::verb::get)(std::bind_front( 1203828252d5SJiaqing Zhao handleTrustStoreCertificateCollectionGet, std::ref(app))); 1204828252d5SJiaqing Zhao 1205828252d5SJiaqing Zhao BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/") 1206828252d5SJiaqing Zhao .privileges(redfish::privileges::postCertificateCollection) 1207828252d5SJiaqing Zhao .methods(boost::beast::http::verb::post)(std::bind_front( 1208828252d5SJiaqing Zhao handleTrustStoreCertificateCollectionPost, std::ref(app))); 1209828252d5SJiaqing Zhao 1210828252d5SJiaqing Zhao BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/") 1211828252d5SJiaqing Zhao .privileges(redfish::privileges::getCertificate) 1212828252d5SJiaqing Zhao .methods(boost::beast::http::verb::get)( 1213828252d5SJiaqing Zhao std::bind_front(handleTrustStoreCertificateGet, std::ref(app))); 1214828252d5SJiaqing Zhao 1215828252d5SJiaqing Zhao BMCWEB_ROUTE(app, "/redfish/v1/Managers/bmc/Truststore/Certificates/<str>/") 1216828252d5SJiaqing Zhao .privileges(redfish::privileges::deleteCertificate) 1217828252d5SJiaqing Zhao .methods(boost::beast::http::verb::delete_)( 1218828252d5SJiaqing Zhao std::bind_front(handleTrustStoreCertificateDelete, std::ref(app))); 12197e860f15SJohn Edward Broadbent } // requestRoutesTrustStoreCertificate 12205968caeeSMarri Devender Rao } // namespace redfish 1221